Home | History | Annotate | Download | only in icu
      1 /*
      2 ******************************************************************************
      3 *
      4 *   Copyright (C) 1999-2006, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 ******************************************************************************
      8 *   file name:  utf_impl.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 1999sep13
     14 *   created by: Markus W. Scherer
     15 *
     16 *   This file provides implementation functions for macros in the utfXX.h
     17 *   that would otherwise be too long as macros.
     18 */
     19 
     20 #include "base/third_party/icu/icu_utf.h"
     21 
     22 namespace base_icu {
     23 
     24 /**
     25  * UTF8_ERROR_VALUE_1 and UTF8_ERROR_VALUE_2 are special error values for UTF-8,
     26  * which need 1 or 2 bytes in UTF-8:
     27  * \code
     28  * U+0015 = NAK = Negative Acknowledge, C0 control character
     29  * U+009f = highest C1 control character
     30  * \endcode
     31  *
     32  * These are used by UTF8_..._SAFE macros so that they can return an error value
     33  * that needs the same number of code units (bytes) as were seen by
     34  * a macro. They should be tested with UTF_IS_ERROR() or UTF_IS_VALID().
     35  *
     36  * @deprecated ICU 2.4. Obsolete, see utf_old.h.
     37  */
     38 #define CBUTF8_ERROR_VALUE_1 0x15
     39 
     40 /**
     41  * See documentation on UTF8_ERROR_VALUE_1 for details.
     42  *
     43  * @deprecated ICU 2.4. Obsolete, see utf_old.h.
     44  */
     45 #define CBUTF8_ERROR_VALUE_2 0x9f
     46 
     47 
     48 /**
     49  * Error value for all UTFs. This code point value will be set by macros with e>
     50  * checking if an error is detected.
     51  *
     52  * @deprecated ICU 2.4. Obsolete, see utf_old.h.
     53  */
     54 #define CBUTF_ERROR_VALUE 0xffff
     55 
     56 /*
     57  * This table could be replaced on many machines by
     58  * a few lines of assembler code using an
     59  * "index of first 0-bit from msb" instruction and
     60  * one or two more integer instructions.
     61  *
     62  * For example, on an i386, do something like
     63  * - MOV AL, leadByte
     64  * - NOT AL         (8-bit, leave b15..b8==0..0, reverse only b7..b0)
     65  * - MOV AH, 0
     66  * - BSR BX, AX     (16-bit)
     67  * - MOV AX, 6      (result)
     68  * - JZ finish      (ZF==1 if leadByte==0xff)
     69  * - SUB AX, BX (result)
     70  * -finish:
     71  * (BSR: Bit Scan Reverse, scans for a 1-bit, starting from the MSB)
     72  *
     73  * In Unicode, all UTF-8 byte sequences with more than 4 bytes are illegal;
     74  * lead bytes above 0xf4 are illegal.
     75  * We keep them in this table for skipping long ISO 10646-UTF-8 sequences.
     76  */
     77 const uint8_t utf8_countTrailBytes[256] =
     78     {
     79         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     80         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     81         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     82 
     83         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     84         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     85         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     86 
     87         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     88         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     89         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     90 
     91         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     92         1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     93 
     94         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
     95         3, 3,       /* illegal in Unicode */
     96         4, 4, 4, 4, /* illegal in Unicode */
     97         5, 5,       /* illegal in Unicode */
     98         0, 0        /* illegal bytes 0xfe and 0xff */
     99 };
    100 
    101 static const UChar32
    102 utf8_minLegal[4]={ 0, 0x80, 0x800, 0x10000 };
    103 
    104 static const UChar32
    105 utf8_errorValue[6]={
    106     CBUTF8_ERROR_VALUE_1, CBUTF8_ERROR_VALUE_2, CBUTF_ERROR_VALUE, 0x10ffff,
    107     0x3ffffff, 0x7fffffff
    108 };
    109 
    110 /*
    111  * Handle the non-inline part of the U8_NEXT() macro and its obsolete sibling
    112  * UTF8_NEXT_CHAR_SAFE().
    113  *
    114  * The "strict" parameter controls the error behavior:
    115  * <0  "Safe" behavior of U8_NEXT(): All illegal byte sequences yield a negative
    116  *     code point result.
    117  *  0  Obsolete "safe" behavior of UTF8_NEXT_CHAR_SAFE(..., FALSE):
    118  *     All illegal byte sequences yield a positive code point such that this
    119  *     result code point would be encoded with the same number of bytes as
    120  *     the illegal sequence.
    121  * >0  Obsolete "strict" behavior of UTF8_NEXT_CHAR_SAFE(..., TRUE):
    122  *     Same as the obsolete "safe" behavior, but non-characters are also treated
    123  *     like illegal sequences.
    124  *
    125  * The special negative (<0) value -2 is used for lenient treatment of surrogate
    126  * code points as legal. Some implementations use this for roundtripping of
    127  * Unicode 16-bit strings that are not well-formed UTF-16, that is, they
    128  * contain unpaired surrogates.
    129  *
    130  * Note that a UBool is the same as an int8_t.
    131  */
    132 UChar32 utf8_nextCharSafeBody(const uint8_t* s,
    133                               int32_t* pi,
    134                               int32_t length,
    135                               UChar32 c,
    136                               UBool strict) {
    137   int32_t i = *pi;
    138   uint8_t count = CBU8_COUNT_TRAIL_BYTES(c);
    139     if((i)+count<=(length)) {
    140       uint8_t trail, illegal = 0;
    141 
    142         CBU8_MASK_LEAD_BYTE((c), count);
    143         /* count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff */
    144         switch(count) {
    145         /* each branch falls through to the next one */
    146         case 5:
    147         case 4:
    148             /* count>=4 is always illegal: no more than 3 trail bytes in Unicode's UTF-8 */
    149             illegal=1;
    150             break;
    151         case 3:
    152             trail=s[(i)++];
    153             (c)=((c)<<6)|(trail&0x3f);
    154             if(c<0x110) {
    155                 illegal|=(trail&0xc0)^0x80;
    156             } else {
    157                 /* code point>0x10ffff, outside Unicode */
    158                 illegal=1;
    159                 break;
    160             }
    161         case 2:
    162             trail=s[(i)++];
    163             (c)=((c)<<6)|(trail&0x3f);
    164             illegal|=(trail&0xc0)^0x80;
    165         case 1:
    166             trail=s[(i)++];
    167             (c)=((c)<<6)|(trail&0x3f);
    168             illegal|=(trail&0xc0)^0x80;
    169             break;
    170         case 0:
    171             if(strict>=0) {
    172                 return CBUTF8_ERROR_VALUE_1;
    173             } else {
    174                 return CBU_SENTINEL;
    175             }
    176         /* no default branch to optimize switch()  - all values are covered */
    177         }
    178 
    179         /*
    180          * All the error handling should return a value
    181          * that needs count bytes so that UTF8_GET_CHAR_SAFE() works right.
    182          *
    183          * Starting with Unicode 3.0.1, non-shortest forms are illegal.
    184          * Starting with Unicode 3.2, surrogate code points must not be
    185          * encoded in UTF-8, and there are no irregular sequences any more.
    186          *
    187          * U8_ macros (new in ICU 2.4) return negative values for error conditions.
    188          */
    189 
    190         /* correct sequence - all trail bytes have (b7..b6)==(10)? */
    191         /* illegal is also set if count>=4 */
    192         if(illegal || (c)<utf8_minLegal[count] || (CBU_IS_SURROGATE(c) && strict!=-2)) {
    193             /* error handling */
    194             uint8_t errorCount = count;
    195             /* don't go beyond this sequence */
    196             i=*pi;
    197             while(count>0 && CBU8_IS_TRAIL(s[i])) {
    198                 ++(i);
    199                 --count;
    200             }
    201             if(strict>=0) {
    202                 c=utf8_errorValue[errorCount-count];
    203             } else {
    204                 c=CBU_SENTINEL;
    205             }
    206         } else if((strict)>0 && CBU_IS_UNICODE_NONCHAR(c)) {
    207             /* strict: forbid non-characters like U+fffe */
    208             c=utf8_errorValue[count];
    209         }
    210     } else /* too few bytes left */ {
    211         /* error handling */
    212         int32_t i0 = i;
    213         /* don't just set (i)=(length) in case there is an illegal sequence */
    214         while((i)<(length) && CBU8_IS_TRAIL(s[i])) {
    215             ++(i);
    216         }
    217         if(strict>=0) {
    218             c=utf8_errorValue[i-i0];
    219         } else {
    220             c=CBU_SENTINEL;
    221         }
    222     }
    223     *pi=i;
    224     return c;
    225 }
    226 
    227 }  // namespace base_icu
    228