Main Page   Class Hierarchy   Compound List   File List   Header Files   Sources   Compound Members   File Members  

utf8.h

00001 /*
00002 *******************************************************************************
00003 *
00004 *   Copyright (C) 1999-2000, International Business Machines
00005 *   Corporation and others.  All Rights Reserved.
00006 *
00007 *******************************************************************************
00008 *   file name:  utf8.h
00009 *   encoding:   US-ASCII
00010 *   tab size:   8 (not used)
00011 *   indentation:4
00012 *
00013 *   created on: 1999sep13
00014 *   created by: Markus W. Scherer
00015 *
00016 *   This file defines macros to deal with UTF-8 code units and code points.
00017 *   Signatures and semantics are the same as for the similarly named macros
00018 *   in utf16.h.
00019 *   utf8.h is included by utf.h after unicode/umachine.h
00020 *   and some common definitions.
00021 */
00022 
00023 
00024 /* utf.h must be included first. */
00025 #ifndef __UTF_H__
00026 # include "unicode/utf.h"
00027 #endif
00028 
00029 #ifndef __UTF8_H__
00030 #define __UTF8_H__
00031 
00032 /* internal definitions ----------------------------------------------------- */
00033 
00034 U_CAPI uint8_t U_EXPORT2
00035 utf8_countTrailBytes[256];
00036 
00037 /*
00038  * Count the trail bytes for a lead byte -
00039  * this macro should be used so that the assembler code
00040  * that is mentioned in utf_impl.c could be used here.
00041  */
00042 #define UTF8_COUNT_TRAIL_BYTES(leadByte) (utf8_countTrailBytes[(uint8_t)leadByte])
00043 
00044 /* use a macro here, too - there may be a simpler way with some machines */
00045 #define UTF8_MASK_LEAD_BYTE(leadByte, countTrailBytes) ((leadByte)&=(1<<(6-(countTrailBytes)))-1)
00046 
00047 U_CAPI UChar32 U_EXPORT2
00048 utf8_nextCharSafeBody(const uint8_t *s, UTextOffset *pi, UTextOffset length, UChar32 c, UBool strict);
00049 
00050 U_CAPI UTextOffset U_EXPORT2
00051 utf8_appendCharSafeBody(uint8_t *s, UTextOffset i, UTextOffset length, UChar32 c);
00052 
00053 U_CAPI UChar32 U_EXPORT2
00054 utf8_prevCharSafeBody(const uint8_t *s, UTextOffset start, UTextOffset *pi, UChar32 c, UBool strict);
00055 
00056 U_CAPI UTextOffset U_EXPORT2
00057 utf8_back1SafeBody(const uint8_t *s, UTextOffset start, UTextOffset i);
00058 
00059 /*
00060  * For the semantics of all of these macros, see utf16.h.
00061  * The UTF-8 macros favor sequences more the shorter they are.
00062  * Sometimes, only the single-byte case is covered by a macro,
00063  * while longer sequences are handled by a function call.
00064  */
00065 
00066 /* single-code point definitions -------------------------------------------- */
00067 
00068 /* classes of code unit values */
00069 #define UTF8_IS_SINGLE(uchar) ((uchar)&0x80==0)
00070 #define UTF8_IS_LEAD(uchar) ((uint8_t)((uchar)-0xc0)<0x3e)
00071 #define UTF8_IS_TRAIL(uchar) ((uchar)&0xc0==0x80)
00072 
00073 /* number of code units per code point */
00074 #define UTF8_NEED_MULTIPLE_UCHAR(c) ((uint32_t)(c)>0x7f)
00075 
00076 /*
00077  * ICU does not deal with code points >0x10ffff
00078  * unless necessary for advancing in the byte stream.
00079  *
00080  * These length macros take into account that for values >0x10ffff
00081  * the "safe" append macros would write the error code point 0xffff
00082  * with 3 bytes.
00083  * Code point comparisons need to be in uint32_t because UChar32
00084  * may be a signed type, and negative values must be recognized.
00085  */
00086 #if 1
00087 #   define UTF8_CHAR_LENGTH(c) \
00088         ((uint32_t)(c)<=0x7f ? 1 : \
00089             ((uint32_t)(c)<=0x7ff ? 2 : \
00090                 ((uint32_t)((c)-0x10000)>0xfffff ? 3 : 4) \
00091             ) \
00092         )
00093 #else
00094 #   define UTF8_CHAR_LENGTH(c) \
00095         ((uint32_t)(c)<=0x7f ? 1 : \
00096             ((uint32_t)(c)<=0x7ff ? 2 : \
00097                 ((uint32_t)(c)<=0xffff ? 3 : \
00098                     ((uint32_t)(c)<=0x10ffff ? 4 : \
00099                         ((uint32_t)(c)<=0x3ffffff ? 5 : \
00100                             ((uint32_t)(c)<=0x7fffffff ? 6 : 3) \
00101                         ) \
00102                     ) \
00103                 ) \
00104             ) \
00105         )
00106 #endif
00107 
00108 #define UTF8_MAX_CHAR_LENGTH 4
00109 
00110 /* average number of code units compared to UTF-16 */
00111 #define UTF8_ARRAY_SIZE(size) ((5*(size))/2)
00112 
00113 #define UTF8_GET_CHAR_UNSAFE(s, i, c) { \
00114     UTextOffset __I=(UTextOffset)(i); \
00115     UTF8_SET_CHAR_START_UNSAFE(s, __I); \
00116     UTF8_NEXT_CHAR_UNSAFE(s, __I, c); \
00117 }
00118 
00119 #define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) { \
00120     UTextOffset __I=(UTextOffset)(i); \
00121     UTF8_SET_CHAR_START_SAFE(s, start, __I); \
00122     UTF8_NEXT_CHAR_SAFE(s, __I, length, c, strict); \
00123 }
00124 
00125 /* definitions with forward iteration --------------------------------------- */
00126 
00127 /*
00128  * Read a Unicode scalar value from an array of UTF-8 bytes.
00129  * Only values <=0x10ffff are accepted, and if an error occurs,
00130  * then c will be set such that UTF_IS_ERROR(c).
00131  * The _UNSAFE macro is fast and does not check for errors.
00132  * The _SAFE macro checks for errors and optionally for
00133  * irregular sequences, too, i.e., for sequences that
00134  * are longer than necessary, such as <c0 80> instead of <0>.
00135  * The strict checks also check for surrogates and
00136  * for 0xXXXXfffe and 0xXXXXffff.
00137  */
00138 #define UTF8_NEXT_CHAR_UNSAFE(s, i, c) { \
00139     (c)=(s)[(i)++]; \
00140     if((uint8_t)((c)-0xc0)<0x35) { \
00141         uint8_t __count=UTF8_COUNT_TRAIL_BYTES(c); \
00142         UTF8_MASK_LEAD_BYTE(c, __count); \
00143         switch(__count) { \
00144         /* each following branch falls through to the next one */ \
00145         case 3: \
00146             (c)=((c)<<6)|((s)[(i)++]&0x3f); \
00147         case 2: \
00148             (c)=((c)<<6)|((s)[(i)++]&0x3f); \
00149         case 1: \
00150             (c)=((c)<<6)|((s)[(i)++]&0x3f); \
00151         /* no other branches to optimize switch() */ \
00152             break; \
00153         } \
00154     } \
00155 }
00156 
00157 #define UTF8_APPEND_CHAR_UNSAFE(s, i, c) { \
00158     if((uint32_t)(c)<=0x7f) { \
00159         (s)[(i)++]=(uint8_t)(c); \
00160     } else { \
00161         if((uint32_t)(c)<=0x7ff) { \
00162             (s)[(i)++]=(uint8_t)((c)>>6)|0xc0; \
00163         } else { \
00164             if((uint32_t)(c)<=0xffff) { \
00165                 (s)[(i)++]=(uint8_t)((c)>>12)|0xe0; \
00166             } else { \
00167                 (s)[(i)++]=(uint8_t)((c)>>18)|0xf0; \
00168                 (s)[(i)++]=(uint8_t)((c)>>12)&0x3f|0x80; \
00169             } \
00170             (s)[(i)++]=(uint8_t)((c)>>6)&0x3f|0x80; \
00171         } \
00172         (s)[(i)++]=(uint8_t)(c)&0x3f|0x80; \
00173     } \
00174 }
00175 
00176 #define UTF8_FWD_1_UNSAFE(s, i) { \
00177     (i)+=1+UTF8_COUNT_TRAIL_BYTES((s)[i]); \
00178 }
00179 
00180 #define UTF8_FWD_N_UNSAFE(s, i, n) { \
00181     UTextOffset __N=(n); \
00182     while(__N>0) { \
00183         UTF8_FWD_1_UNSAFE(s, i); \
00184         --__N; \
00185     } \
00186 }
00187 
00188 #define UTF8_SET_CHAR_START_UNSAFE(s, i) { \
00189     while(UTF8_IS_TRAIL((s)[i])) { --(i); } \
00190 }
00191 
00192 #define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) { \
00193     (c)=(s)[(i)++]; \
00194     if(UTF8_IS_LEAD(c)) { \
00195         (c)=utf8_nextCharSafeBody(s, &(i), (UTextOffset)(length), c, strict); \
00196     } \
00197 }
00198 
00199 #define UTF8_APPEND_CHAR_SAFE(s, i, length, c) { \
00200     if((uint32_t)(c)<=0x7f) { \
00201         (s)[(i)++]=(uint8_t)(c); \
00202     } else { \
00203         (i)=utf8_appendCharSafeBody(s, (UTextOffset)(i), (UTextOffset)(length), c); \
00204     } \
00205 }
00206 
00207 #define UTF8_FWD_1_SAFE(s, i, length) { \
00208     uint8_t __b=(s)[(i)++]; \
00209     if(UTF8_IS_LEAD(__b)) { \
00210         uint8_t __count=UTF8_COUNT_TRAIL_BYTES(__b); \
00211         if((i)+__count>(length)) { \
00212             __count=(length)-(i); \
00213         } \
00214         while(__count>0 && UTF8_IS_TRAIL((s)[i])) { \
00215             ++(i); \
00216             --__count; \
00217         } \
00218     } \
00219 }
00220 
00221 #define UTF8_FWD_N_SAFE(s, i, length, n) { \
00222     UTextOffset __N=(n); \
00223     while(__N>0 && (i)<(length)) { \
00224         UTF8_FWD_1_SAFE(s, i, length); \
00225         --__N; \
00226     } \
00227 }
00228 
00229 #define UTF8_SET_CHAR_START_SAFE(s, start, i) { \
00230     if(UTF8_IS_TRAIL((s)[(i)])) { \
00231         (i)=utf8_back1SafeBody(s, start, (UTextOffset)(i)); \
00232     } \
00233 }
00234 
00235 /* definitions with backward iteration -------------------------------------- */
00236 
00237 #define UTF8_PREV_CHAR_UNSAFE(s, i, c) { \
00238     (c)=(s)[--(i)]; \
00239     if(UTF8_IS_TRAIL(c)) { \
00240         uint8_t __b, __count=1, __shift=6; \
00241 \
00242         /* c is a trail byte */ \
00243         (c)&=0x3f; \
00244         for(;;) { \
00245             __b=(s)[--(i)]; \
00246             if(__b>=0xc0) { \
00247                 UTF8_MASK_LEAD_BYTE(__b, __count); \
00248                 (c)|=(UChar32)__b<<__shift; \
00249                 break; \
00250             } else { \
00251                 (c)|=(UChar32)(__b&0x3f)<<__shift; \
00252                 ++__count; \
00253                 __shift+=6; \
00254             } \
00255         } \
00256     } \
00257 }
00258 
00259 #define UTF8_BACK_1_UNSAFE(s, i) { \
00260     while(UTF8_IS_TRAIL((s)[--(i)])) {} \
00261 }
00262 
00263 #define UTF8_BACK_N_UNSAFE(s, i, n) { \
00264     UTextOffset __N=(n); \
00265     while(__N>0) { \
00266         UTF8_BACK_1_UNSAFE(s, i); \
00267         --__N; \
00268     } \
00269 }
00270 
00271 #define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) { \
00272     UTF8_BACK_1_UNSAFE(s, i); \
00273     UTF8_FWD_1_UNSAFE(s, i); \
00274 }
00275 
00276 #define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) { \
00277     (c)=(s)[--(i)]; \
00278     if(UTF8_IS_TRAIL((c))) { \
00279         (c)=utf8_prevCharSafeBody(s, start, &(i), c, strict); \
00280     } \
00281 }
00282 
00283 #define UTF8_BACK_1_SAFE(s, start, i) { \
00284     if(UTF8_IS_TRAIL((s)[--(i)])) { \
00285         (i)=utf8_back1SafeBody(s, start, (UTextOffset)(i)); \
00286     } \
00287 }
00288 
00289 #define UTF8_BACK_N_SAFE(s, start, i, n) { \
00290     UTextOffset __N=(n); \
00291     while(__N>0 && (i)>(start)) { \
00292         UTF8_BACK_1_SAFE(s, start, i); \
00293         --__N; \
00294     } \
00295 }
00296 
00297 #define UTF8_SET_CHAR_LIMIT_SAFE(s, start, i, length) { \
00298     if((start)<(i) && (i)<(length)) { \
00299         UTF8_BACK_1_SAFE(s, start, i); \
00300         (i)+=1+UTF8_COUNT_TRAIL_BYTES((s)[i]); \
00301         if((i)>(length)) { \
00302             (i)=(length); \
00303         } \
00304     } \
00305 }
00306 
00307 #endif

Generated at Mon Jun 5 12:53:09 2000 for ICU1.5 by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999