Home | History | Annotate | Download | only in common
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 **********************************************************************
      5 *   Copyright (C) 2002-2015, International Business Machines
      6 *   Corporation and others.  All Rights Reserved.
      7 **********************************************************************
      8 *   file name:  ucnv_u32.c
      9 *   encoding:   UTF-8
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2002jul01
     14 *   created by: Markus W. Scherer
     15 *
     16 *   UTF-32 converter implementation. Used to be in ucnv_utf.c.
     17 */
     18 
     19 #include "unicode/utypes.h"
     20 
     21 #if !UCONFIG_NO_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
     22 
     23 #include "unicode/ucnv.h"
     24 #include "unicode/utf.h"
     25 #include "ucnv_bld.h"
     26 #include "ucnv_cnv.h"
     27 #include "cmemory.h"
     28 
     29 #define MAXIMUM_UCS2            0x0000FFFF
     30 #define MAXIMUM_UTF             0x0010FFFF
     31 #define HALF_SHIFT              10
     32 #define HALF_BASE               0x0010000
     33 #define HALF_MASK               0x3FF
     34 #define SURROGATE_HIGH_START    0xD800
     35 #define SURROGATE_LOW_START     0xDC00
     36 
     37 /* -SURROGATE_LOW_START + HALF_BASE */
     38 #define SURROGATE_LOW_BASE      9216
     39 
     40 enum {
     41     UCNV_NEED_TO_WRITE_BOM=1
     42 };
     43 
     44 /* UTF-32BE ----------------------------------------------------------------- */
     45 U_CDECL_BEGIN
     46 static void U_CALLCONV
     47 T_UConverter_toUnicode_UTF32_BE(UConverterToUnicodeArgs * args,
     48                                 UErrorCode * err)
     49 {
     50     const unsigned char *mySource = (unsigned char *) args->source;
     51     UChar *myTarget = args->target;
     52     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
     53     const UChar *targetLimit = args->targetLimit;
     54     unsigned char *toUBytes = args->converter->toUBytes;
     55     uint32_t ch, i;
     56 
     57     /* Restore state of current sequence */
     58     if (args->converter->toULength > 0 && myTarget < targetLimit) {
     59         i = args->converter->toULength;       /* restore # of bytes consumed */
     60         args->converter->toULength = 0;
     61 
     62         ch = args->converter->toUnicodeStatus - 1;/*Stores the previously calculated ch from a previous call*/
     63         args->converter->toUnicodeStatus = 0;
     64         goto morebytes;
     65     }
     66 
     67     while (mySource < sourceLimit && myTarget < targetLimit) {
     68         i = 0;
     69         ch = 0;
     70 morebytes:
     71         while (i < sizeof(uint32_t)) {
     72             if (mySource < sourceLimit) {
     73                 ch = (ch << 8) | (uint8_t)(*mySource);
     74                 toUBytes[i++] = (char) *(mySource++);
     75             }
     76             else {
     77                 /* stores a partially calculated target*/
     78                 /* + 1 to make 0 a valid character */
     79                 args->converter->toUnicodeStatus = ch + 1;
     80                 args->converter->toULength = (int8_t) i;
     81                 goto donefornow;
     82             }
     83         }
     84 
     85         if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) {
     86             /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
     87             if (ch <= MAXIMUM_UCS2)
     88             {
     89                 /* fits in 16 bits */
     90                 *(myTarget++) = (UChar) ch;
     91             }
     92             else {
     93                 /* write out the surrogates */
     94                 *(myTarget++) = U16_LEAD(ch);
     95                 ch = U16_TRAIL(ch);
     96                 if (myTarget < targetLimit) {
     97                     *(myTarget++) = (UChar)ch;
     98                 }
     99                 else {
    100                     /* Put in overflow buffer (not handled here) */
    101                     args->converter->UCharErrorBuffer[0] = (UChar) ch;
    102                     args->converter->UCharErrorBufferLength = 1;
    103                     *err = U_BUFFER_OVERFLOW_ERROR;
    104                     break;
    105                 }
    106             }
    107         }
    108         else {
    109             args->converter->toULength = (int8_t)i;
    110             *err = U_ILLEGAL_CHAR_FOUND;
    111             break;
    112         }
    113     }
    114 
    115 donefornow:
    116     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) {
    117         /* End of target buffer */
    118         *err = U_BUFFER_OVERFLOW_ERROR;
    119     }
    120 
    121     args->target = myTarget;
    122     args->source = (const char *) mySource;
    123 }
    124 
    125 static void U_CALLCONV
    126 T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC(UConverterToUnicodeArgs * args,
    127                                              UErrorCode * err)
    128 {
    129     const unsigned char *mySource = (unsigned char *) args->source;
    130     UChar *myTarget = args->target;
    131     int32_t *myOffsets = args->offsets;
    132     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
    133     const UChar *targetLimit = args->targetLimit;
    134     unsigned char *toUBytes = args->converter->toUBytes;
    135     uint32_t ch, i;
    136     int32_t offsetNum = 0;
    137 
    138     /* Restore state of current sequence */
    139     if (args->converter->toULength > 0 && myTarget < targetLimit) {
    140         i = args->converter->toULength;       /* restore # of bytes consumed */
    141         args->converter->toULength = 0;
    142 
    143         ch = args->converter->toUnicodeStatus - 1;/*Stores the previously calculated ch from a previous call*/
    144         args->converter->toUnicodeStatus = 0;
    145         goto morebytes;
    146     }
    147 
    148     while (mySource < sourceLimit && myTarget < targetLimit) {
    149         i = 0;
    150         ch = 0;
    151 morebytes:
    152         while (i < sizeof(uint32_t)) {
    153             if (mySource < sourceLimit) {
    154                 ch = (ch << 8) | (uint8_t)(*mySource);
    155                 toUBytes[i++] = (char) *(mySource++);
    156             }
    157             else {
    158                 /* stores a partially calculated target*/
    159                 /* + 1 to make 0 a valid character */
    160                 args->converter->toUnicodeStatus = ch + 1;
    161                 args->converter->toULength = (int8_t) i;
    162                 goto donefornow;
    163             }
    164         }
    165 
    166         if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) {
    167             /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
    168             if (ch <= MAXIMUM_UCS2) {
    169                 /* fits in 16 bits */
    170                 *(myTarget++) = (UChar) ch;
    171                 *(myOffsets++) = offsetNum;
    172             }
    173             else {
    174                 /* write out the surrogates */
    175                 *(myTarget++) = U16_LEAD(ch);
    176                 *myOffsets++ = offsetNum;
    177                 ch = U16_TRAIL(ch);
    178                 if (myTarget < targetLimit)
    179                 {
    180                     *(myTarget++) = (UChar)ch;
    181                     *(myOffsets++) = offsetNum;
    182                 }
    183                 else {
    184                     /* Put in overflow buffer (not handled here) */
    185                     args->converter->UCharErrorBuffer[0] = (UChar) ch;
    186                     args->converter->UCharErrorBufferLength = 1;
    187                     *err = U_BUFFER_OVERFLOW_ERROR;
    188                     break;
    189                 }
    190             }
    191         }
    192         else {
    193             args->converter->toULength = (int8_t)i;
    194             *err = U_ILLEGAL_CHAR_FOUND;
    195             break;
    196         }
    197         offsetNum += i;
    198     }
    199 
    200 donefornow:
    201     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
    202     {
    203         /* End of target buffer */
    204         *err = U_BUFFER_OVERFLOW_ERROR;
    205     }
    206 
    207     args->target = myTarget;
    208     args->source = (const char *) mySource;
    209     args->offsets = myOffsets;
    210 }
    211 
    212 static void U_CALLCONV
    213 T_UConverter_fromUnicode_UTF32_BE(UConverterFromUnicodeArgs * args,
    214                                   UErrorCode * err)
    215 {
    216     const UChar *mySource = args->source;
    217     unsigned char *myTarget;
    218     const UChar *sourceLimit = args->sourceLimit;
    219     const unsigned char *targetLimit = (unsigned char *) args->targetLimit;
    220     UChar32 ch, ch2;
    221     unsigned int indexToWrite;
    222     unsigned char temp[sizeof(uint32_t)];
    223 
    224     if(mySource >= sourceLimit) {
    225         /* no input, nothing to do */
    226         return;
    227     }
    228 
    229     /* write the BOM if necessary */
    230     if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
    231         static const char bom[]={ 0, 0, (char)0xfeu, (char)0xffu };
    232         ucnv_fromUWriteBytes(args->converter,
    233                              bom, 4,
    234                              &args->target, args->targetLimit,
    235                              &args->offsets, -1,
    236                              err);
    237         args->converter->fromUnicodeStatus=0;
    238     }
    239 
    240     myTarget = (unsigned char *) args->target;
    241     temp[0] = 0;
    242 
    243     if (args->converter->fromUChar32) {
    244         ch = args->converter->fromUChar32;
    245         args->converter->fromUChar32 = 0;
    246         goto lowsurogate;
    247     }
    248 
    249     while (mySource < sourceLimit && myTarget < targetLimit) {
    250         ch = *(mySource++);
    251 
    252         if (U_IS_SURROGATE(ch)) {
    253             if (U_IS_LEAD(ch)) {
    254 lowsurogate:
    255                 if (mySource < sourceLimit) {
    256                     ch2 = *mySource;
    257                     if (U_IS_TRAIL(ch2)) {
    258                         ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE;
    259                         mySource++;
    260                     }
    261                     else {
    262                         /* this is an unmatched trail code unit (2nd surrogate) */
    263                         /* callback(illegal) */
    264                         args->converter->fromUChar32 = ch;
    265                         *err = U_ILLEGAL_CHAR_FOUND;
    266                         break;
    267                     }
    268                 }
    269                 else {
    270                     /* ran out of source */
    271                     args->converter->fromUChar32 = ch;
    272                     if (args->flush) {
    273                         /* this is an unmatched trail code unit (2nd surrogate) */
    274                         /* callback(illegal) */
    275                         *err = U_ILLEGAL_CHAR_FOUND;
    276                     }
    277                     break;
    278                 }
    279             }
    280             else {
    281                 /* this is an unmatched trail code unit (2nd surrogate) */
    282                 /* callback(illegal) */
    283                 args->converter->fromUChar32 = ch;
    284                 *err = U_ILLEGAL_CHAR_FOUND;
    285                 break;
    286             }
    287         }
    288 
    289         /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */
    290         temp[1] = (uint8_t) (ch >> 16 & 0x1F);
    291         temp[2] = (uint8_t) (ch >> 8);  /* unsigned cast implicitly does (ch & FF) */
    292         temp[3] = (uint8_t) (ch);       /* unsigned cast implicitly does (ch & FF) */
    293 
    294         for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) {
    295             if (myTarget < targetLimit) {
    296                 *(myTarget++) = temp[indexToWrite];
    297             }
    298             else {
    299                 args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite];
    300                 *err = U_BUFFER_OVERFLOW_ERROR;
    301             }
    302         }
    303     }
    304 
    305     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) {
    306         *err = U_BUFFER_OVERFLOW_ERROR;
    307     }
    308 
    309     args->target = (char *) myTarget;
    310     args->source = mySource;
    311 }
    312 
    313 static void U_CALLCONV
    314 T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args,
    315                                                UErrorCode * err)
    316 {
    317     const UChar *mySource = args->source;
    318     unsigned char *myTarget;
    319     int32_t *myOffsets;
    320     const UChar *sourceLimit = args->sourceLimit;
    321     const unsigned char *targetLimit = (unsigned char *) args->targetLimit;
    322     UChar32 ch, ch2;
    323     int32_t offsetNum = 0;
    324     unsigned int indexToWrite;
    325     unsigned char temp[sizeof(uint32_t)];
    326 
    327     if(mySource >= sourceLimit) {
    328         /* no input, nothing to do */
    329         return;
    330     }
    331 
    332     /* write the BOM if necessary */
    333     if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
    334         static const char bom[]={ 0, 0, (char)0xfeu, (char)0xffu };
    335         ucnv_fromUWriteBytes(args->converter,
    336                              bom, 4,
    337                              &args->target, args->targetLimit,
    338                              &args->offsets, -1,
    339                              err);
    340         args->converter->fromUnicodeStatus=0;
    341     }
    342 
    343     myTarget = (unsigned char *) args->target;
    344     myOffsets = args->offsets;
    345     temp[0] = 0;
    346 
    347     if (args->converter->fromUChar32) {
    348         ch = args->converter->fromUChar32;
    349         args->converter->fromUChar32 = 0;
    350         goto lowsurogate;
    351     }
    352 
    353     while (mySource < sourceLimit && myTarget < targetLimit) {
    354         ch = *(mySource++);
    355 
    356         if (U_IS_SURROGATE(ch)) {
    357             if (U_IS_LEAD(ch)) {
    358 lowsurogate:
    359                 if (mySource < sourceLimit) {
    360                     ch2 = *mySource;
    361                     if (U_IS_TRAIL(ch2)) {
    362                         ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE;
    363                         mySource++;
    364                     }
    365                     else {
    366                         /* this is an unmatched trail code unit (2nd surrogate) */
    367                         /* callback(illegal) */
    368                         args->converter->fromUChar32 = ch;
    369                         *err = U_ILLEGAL_CHAR_FOUND;
    370                         break;
    371                     }
    372                 }
    373                 else {
    374                     /* ran out of source */
    375                     args->converter->fromUChar32 = ch;
    376                     if (args->flush) {
    377                         /* this is an unmatched trail code unit (2nd surrogate) */
    378                         /* callback(illegal) */
    379                         *err = U_ILLEGAL_CHAR_FOUND;
    380                     }
    381                     break;
    382                 }
    383             }
    384             else {
    385                 /* this is an unmatched trail code unit (2nd surrogate) */
    386                 /* callback(illegal) */
    387                 args->converter->fromUChar32 = ch;
    388                 *err = U_ILLEGAL_CHAR_FOUND;
    389                 break;
    390             }
    391         }
    392 
    393         /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */
    394         temp[1] = (uint8_t) (ch >> 16 & 0x1F);
    395         temp[2] = (uint8_t) (ch >> 8);  /* unsigned cast implicitly does (ch & FF) */
    396         temp[3] = (uint8_t) (ch);       /* unsigned cast implicitly does (ch & FF) */
    397 
    398         for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) {
    399             if (myTarget < targetLimit) {
    400                 *(myTarget++) = temp[indexToWrite];
    401                 *(myOffsets++) = offsetNum;
    402             }
    403             else {
    404                 args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite];
    405                 *err = U_BUFFER_OVERFLOW_ERROR;
    406             }
    407         }
    408         offsetNum = offsetNum + 1 + (temp[1] != 0);
    409     }
    410 
    411     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) {
    412         *err = U_BUFFER_OVERFLOW_ERROR;
    413     }
    414 
    415     args->target = (char *) myTarget;
    416     args->source = mySource;
    417     args->offsets = myOffsets;
    418 }
    419 
    420 static UChar32 U_CALLCONV
    421 T_UConverter_getNextUChar_UTF32_BE(UConverterToUnicodeArgs* args,
    422                                    UErrorCode* err)
    423 {
    424     const uint8_t *mySource;
    425     UChar32 myUChar;
    426     int32_t length;
    427 
    428     mySource = (const uint8_t *)args->source;
    429     if (mySource >= (const uint8_t *)args->sourceLimit)
    430     {
    431         /* no input */
    432         *err = U_INDEX_OUTOFBOUNDS_ERROR;
    433         return 0xffff;
    434     }
    435 
    436     length = (int32_t)((const uint8_t *)args->sourceLimit - mySource);
    437     if (length < 4)
    438     {
    439         /* got a partial character */
    440         uprv_memcpy(args->converter->toUBytes, mySource, length);
    441         args->converter->toULength = (int8_t)length;
    442         args->source = (const char *)(mySource + length);
    443         *err = U_TRUNCATED_CHAR_FOUND;
    444         return 0xffff;
    445     }
    446 
    447     /* Don't even try to do a direct cast because the value may be on an odd address. */
    448     myUChar = ((UChar32)mySource[0] << 24)
    449             | ((UChar32)mySource[1] << 16)
    450             | ((UChar32)mySource[2] << 8)
    451             | ((UChar32)mySource[3]);
    452 
    453     args->source = (const char *)(mySource + 4);
    454     if ((uint32_t)myUChar <= MAXIMUM_UTF && !U_IS_SURROGATE(myUChar)) {
    455         return myUChar;
    456     }
    457 
    458     uprv_memcpy(args->converter->toUBytes, mySource, 4);
    459     args->converter->toULength = 4;
    460 
    461     *err = U_ILLEGAL_CHAR_FOUND;
    462     return 0xffff;
    463 }
    464 U_CDECL_END
    465 static const UConverterImpl _UTF32BEImpl = {
    466     UCNV_UTF32_BigEndian,
    467 
    468     NULL,
    469     NULL,
    470 
    471     NULL,
    472     NULL,
    473     NULL,
    474 
    475     T_UConverter_toUnicode_UTF32_BE,
    476     T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC,
    477     T_UConverter_fromUnicode_UTF32_BE,
    478     T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC,
    479     T_UConverter_getNextUChar_UTF32_BE,
    480 
    481     NULL,
    482     NULL,
    483     NULL,
    484     NULL,
    485     ucnv_getNonSurrogateUnicodeSet,
    486 
    487     NULL,
    488     NULL
    489 };
    490 
    491 /* The 1232 CCSID refers to any version of Unicode with any endianess of UTF-32 */
    492 static const UConverterStaticData _UTF32BEStaticData = {
    493     sizeof(UConverterStaticData),
    494     "UTF-32BE",
    495     1232,
    496     UCNV_IBM, UCNV_UTF32_BigEndian, 4, 4,
    497     { 0, 0, 0xff, 0xfd }, 4, FALSE, FALSE,
    498     0,
    499     0,
    500     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
    501 };
    502 
    503 const UConverterSharedData _UTF32BEData =
    504         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32BEStaticData, &_UTF32BEImpl);
    505 
    506 /* UTF-32LE ---------------------------------------------------------- */
    507 U_CDECL_BEGIN
    508 static void U_CALLCONV
    509 T_UConverter_toUnicode_UTF32_LE(UConverterToUnicodeArgs * args,
    510                                 UErrorCode * err)
    511 {
    512     const unsigned char *mySource = (unsigned char *) args->source;
    513     UChar *myTarget = args->target;
    514     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
    515     const UChar *targetLimit = args->targetLimit;
    516     unsigned char *toUBytes = args->converter->toUBytes;
    517     uint32_t ch, i;
    518 
    519     /* Restore state of current sequence */
    520     if (args->converter->toULength > 0 && myTarget < targetLimit)
    521     {
    522         i = args->converter->toULength;       /* restore # of bytes consumed */
    523         args->converter->toULength = 0;
    524 
    525         /* Stores the previously calculated ch from a previous call*/
    526         ch = args->converter->toUnicodeStatus - 1;
    527         args->converter->toUnicodeStatus = 0;
    528         goto morebytes;
    529     }
    530 
    531     while (mySource < sourceLimit && myTarget < targetLimit)
    532     {
    533         i = 0;
    534         ch = 0;
    535 morebytes:
    536         while (i < sizeof(uint32_t))
    537         {
    538             if (mySource < sourceLimit)
    539             {
    540                 ch |= ((uint8_t)(*mySource)) << (i * 8);
    541                 toUBytes[i++] = (char) *(mySource++);
    542             }
    543             else
    544             {
    545                 /* stores a partially calculated target*/
    546                 /* + 1 to make 0 a valid character */
    547                 args->converter->toUnicodeStatus = ch + 1;
    548                 args->converter->toULength = (int8_t) i;
    549                 goto donefornow;
    550             }
    551         }
    552 
    553         if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) {
    554             /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
    555             if (ch <= MAXIMUM_UCS2) {
    556                 /* fits in 16 bits */
    557                 *(myTarget++) = (UChar) ch;
    558             }
    559             else {
    560                 /* write out the surrogates */
    561                 *(myTarget++) = U16_LEAD(ch);
    562                 ch = U16_TRAIL(ch);
    563                 if (myTarget < targetLimit) {
    564                     *(myTarget++) = (UChar)ch;
    565                 }
    566                 else {
    567                     /* Put in overflow buffer (not handled here) */
    568                     args->converter->UCharErrorBuffer[0] = (UChar) ch;
    569                     args->converter->UCharErrorBufferLength = 1;
    570                     *err = U_BUFFER_OVERFLOW_ERROR;
    571                     break;
    572                 }
    573             }
    574         }
    575         else {
    576             args->converter->toULength = (int8_t)i;
    577             *err = U_ILLEGAL_CHAR_FOUND;
    578             break;
    579         }
    580     }
    581 
    582 donefornow:
    583     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
    584     {
    585         /* End of target buffer */
    586         *err = U_BUFFER_OVERFLOW_ERROR;
    587     }
    588 
    589     args->target = myTarget;
    590     args->source = (const char *) mySource;
    591 }
    592 
    593 static void U_CALLCONV
    594 T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC(UConverterToUnicodeArgs * args,
    595                                              UErrorCode * err)
    596 {
    597     const unsigned char *mySource = (unsigned char *) args->source;
    598     UChar *myTarget = args->target;
    599     int32_t *myOffsets = args->offsets;
    600     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
    601     const UChar *targetLimit = args->targetLimit;
    602     unsigned char *toUBytes = args->converter->toUBytes;
    603     uint32_t ch, i;
    604     int32_t offsetNum = 0;
    605 
    606     /* Restore state of current sequence */
    607     if (args->converter->toULength > 0 && myTarget < targetLimit)
    608     {
    609         i = args->converter->toULength;       /* restore # of bytes consumed */
    610         args->converter->toULength = 0;
    611 
    612         /* Stores the previously calculated ch from a previous call*/
    613         ch = args->converter->toUnicodeStatus - 1;
    614         args->converter->toUnicodeStatus = 0;
    615         goto morebytes;
    616     }
    617 
    618     while (mySource < sourceLimit && myTarget < targetLimit)
    619     {
    620         i = 0;
    621         ch = 0;
    622 morebytes:
    623         while (i < sizeof(uint32_t))
    624         {
    625             if (mySource < sourceLimit)
    626             {
    627                 ch |= ((uint8_t)(*mySource)) << (i * 8);
    628                 toUBytes[i++] = (char) *(mySource++);
    629             }
    630             else
    631             {
    632                 /* stores a partially calculated target*/
    633                 /* + 1 to make 0 a valid character */
    634                 args->converter->toUnicodeStatus = ch + 1;
    635                 args->converter->toULength = (int8_t) i;
    636                 goto donefornow;
    637             }
    638         }
    639 
    640         if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch))
    641         {
    642             /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
    643             if (ch <= MAXIMUM_UCS2)
    644             {
    645                 /* fits in 16 bits */
    646                 *(myTarget++) = (UChar) ch;
    647                 *(myOffsets++) = offsetNum;
    648             }
    649             else {
    650                 /* write out the surrogates */
    651                 *(myTarget++) = U16_LEAD(ch);
    652                 *(myOffsets++) = offsetNum;
    653                 ch = U16_TRAIL(ch);
    654                 if (myTarget < targetLimit)
    655                 {
    656                     *(myTarget++) = (UChar)ch;
    657                     *(myOffsets++) = offsetNum;
    658                 }
    659                 else
    660                 {
    661                     /* Put in overflow buffer (not handled here) */
    662                     args->converter->UCharErrorBuffer[0] = (UChar) ch;
    663                     args->converter->UCharErrorBufferLength = 1;
    664                     *err = U_BUFFER_OVERFLOW_ERROR;
    665                     break;
    666                 }
    667             }
    668         }
    669         else
    670         {
    671             args->converter->toULength = (int8_t)i;
    672             *err = U_ILLEGAL_CHAR_FOUND;
    673             break;
    674         }
    675         offsetNum += i;
    676     }
    677 
    678 donefornow:
    679     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
    680     {
    681         /* End of target buffer */
    682         *err = U_BUFFER_OVERFLOW_ERROR;
    683     }
    684 
    685     args->target = myTarget;
    686     args->source = (const char *) mySource;
    687     args->offsets = myOffsets;
    688 }
    689 
    690 static void U_CALLCONV
    691 T_UConverter_fromUnicode_UTF32_LE(UConverterFromUnicodeArgs * args,
    692                                   UErrorCode * err)
    693 {
    694     const UChar *mySource = args->source;
    695     unsigned char *myTarget;
    696     const UChar *sourceLimit = args->sourceLimit;
    697     const unsigned char *targetLimit = (unsigned char *) args->targetLimit;
    698     UChar32 ch, ch2;
    699     unsigned int indexToWrite;
    700     unsigned char temp[sizeof(uint32_t)];
    701 
    702     if(mySource >= sourceLimit) {
    703         /* no input, nothing to do */
    704         return;
    705     }
    706 
    707     /* write the BOM if necessary */
    708     if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
    709         static const char bom[]={ (char)0xffu, (char)0xfeu, 0, 0 };
    710         ucnv_fromUWriteBytes(args->converter,
    711                              bom, 4,
    712                              &args->target, args->targetLimit,
    713                              &args->offsets, -1,
    714                              err);
    715         args->converter->fromUnicodeStatus=0;
    716     }
    717 
    718     myTarget = (unsigned char *) args->target;
    719     temp[3] = 0;
    720 
    721     if (args->converter->fromUChar32)
    722     {
    723         ch = args->converter->fromUChar32;
    724         args->converter->fromUChar32 = 0;
    725         goto lowsurogate;
    726     }
    727 
    728     while (mySource < sourceLimit && myTarget < targetLimit)
    729     {
    730         ch = *(mySource++);
    731 
    732         if (U16_IS_SURROGATE(ch)) {
    733             if (U16_IS_LEAD(ch))
    734             {
    735 lowsurogate:
    736                 if (mySource < sourceLimit)
    737                 {
    738                     ch2 = *mySource;
    739                     if (U16_IS_TRAIL(ch2)) {
    740                         ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE;
    741                         mySource++;
    742                     }
    743                     else {
    744                         /* this is an unmatched trail code unit (2nd surrogate) */
    745                         /* callback(illegal) */
    746                         args->converter->fromUChar32 = ch;
    747                         *err = U_ILLEGAL_CHAR_FOUND;
    748                         break;
    749                     }
    750                 }
    751                 else {
    752                     /* ran out of source */
    753                     args->converter->fromUChar32 = ch;
    754                     if (args->flush) {
    755                         /* this is an unmatched trail code unit (2nd surrogate) */
    756                         /* callback(illegal) */
    757                         *err = U_ILLEGAL_CHAR_FOUND;
    758                     }
    759                     break;
    760                 }
    761             }
    762             else {
    763                 /* this is an unmatched trail code unit (2nd surrogate) */
    764                 /* callback(illegal) */
    765                 args->converter->fromUChar32 = ch;
    766                 *err = U_ILLEGAL_CHAR_FOUND;
    767                 break;
    768             }
    769         }
    770 
    771         /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */
    772         temp[2] = (uint8_t) (ch >> 16 & 0x1F);
    773         temp[1] = (uint8_t) (ch >> 8);  /* unsigned cast implicitly does (ch & FF) */
    774         temp[0] = (uint8_t) (ch);       /* unsigned cast implicitly does (ch & FF) */
    775 
    776         for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++)
    777         {
    778             if (myTarget < targetLimit)
    779             {
    780                 *(myTarget++) = temp[indexToWrite];
    781             }
    782             else
    783             {
    784                 args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite];
    785                 *err = U_BUFFER_OVERFLOW_ERROR;
    786             }
    787         }
    788     }
    789 
    790     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
    791     {
    792         *err = U_BUFFER_OVERFLOW_ERROR;
    793     }
    794 
    795     args->target = (char *) myTarget;
    796     args->source = mySource;
    797 }
    798 
    799 static void U_CALLCONV
    800 T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args,
    801                                                UErrorCode * err)
    802 {
    803     const UChar *mySource = args->source;
    804     unsigned char *myTarget;
    805     int32_t *myOffsets;
    806     const UChar *sourceLimit = args->sourceLimit;
    807     const unsigned char *targetLimit = (unsigned char *) args->targetLimit;
    808     UChar32 ch, ch2;
    809     unsigned int indexToWrite;
    810     unsigned char temp[sizeof(uint32_t)];
    811     int32_t offsetNum = 0;
    812 
    813     if(mySource >= sourceLimit) {
    814         /* no input, nothing to do */
    815         return;
    816     }
    817 
    818     /* write the BOM if necessary */
    819     if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
    820         static const char bom[]={ (char)0xffu, (char)0xfeu, 0, 0 };
    821         ucnv_fromUWriteBytes(args->converter,
    822                              bom, 4,
    823                              &args->target, args->targetLimit,
    824                              &args->offsets, -1,
    825                              err);
    826         args->converter->fromUnicodeStatus=0;
    827     }
    828 
    829     myTarget = (unsigned char *) args->target;
    830     myOffsets = args->offsets;
    831     temp[3] = 0;
    832 
    833     if (args->converter->fromUChar32)
    834     {
    835         ch = args->converter->fromUChar32;
    836         args->converter->fromUChar32 = 0;
    837         goto lowsurogate;
    838     }
    839 
    840     while (mySource < sourceLimit && myTarget < targetLimit)
    841     {
    842         ch = *(mySource++);
    843 
    844         if (U16_IS_SURROGATE(ch)) {
    845             if (U16_IS_LEAD(ch))
    846             {
    847 lowsurogate:
    848                 if (mySource < sourceLimit)
    849                 {
    850                     ch2 = *mySource;
    851                     if (U16_IS_TRAIL(ch2))
    852                     {
    853                         ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE;
    854                         mySource++;
    855                     }
    856                     else {
    857                         /* this is an unmatched trail code unit (2nd surrogate) */
    858                         /* callback(illegal) */
    859                         args->converter->fromUChar32 = ch;
    860                         *err = U_ILLEGAL_CHAR_FOUND;
    861                         break;
    862                     }
    863                 }
    864                 else {
    865                     /* ran out of source */
    866                     args->converter->fromUChar32 = ch;
    867                     if (args->flush) {
    868                         /* this is an unmatched trail code unit (2nd surrogate) */
    869                         /* callback(illegal) */
    870                         *err = U_ILLEGAL_CHAR_FOUND;
    871                     }
    872                     break;
    873                 }
    874             }
    875             else {
    876                 /* this is an unmatched trail code unit (2nd surrogate) */
    877                 /* callback(illegal) */
    878                 args->converter->fromUChar32 = ch;
    879                 *err = U_ILLEGAL_CHAR_FOUND;
    880                 break;
    881             }
    882         }
    883 
    884         /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */
    885         temp[2] = (uint8_t) (ch >> 16 & 0x1F);
    886         temp[1] = (uint8_t) (ch >> 8);  /* unsigned cast implicitly does (ch & FF) */
    887         temp[0] = (uint8_t) (ch);       /* unsigned cast implicitly does (ch & FF) */
    888 
    889         for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++)
    890         {
    891             if (myTarget < targetLimit)
    892             {
    893                 *(myTarget++) = temp[indexToWrite];
    894                 *(myOffsets++) = offsetNum;
    895             }
    896             else
    897             {
    898                 args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite];
    899                 *err = U_BUFFER_OVERFLOW_ERROR;
    900             }
    901         }
    902         offsetNum = offsetNum + 1 + (temp[2] != 0);
    903     }
    904 
    905     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
    906     {
    907         *err = U_BUFFER_OVERFLOW_ERROR;
    908     }
    909 
    910     args->target = (char *) myTarget;
    911     args->source = mySource;
    912     args->offsets = myOffsets;
    913 }
    914 
    915 static UChar32 U_CALLCONV
    916 T_UConverter_getNextUChar_UTF32_LE(UConverterToUnicodeArgs* args,
    917                                    UErrorCode* err)
    918 {
    919     const uint8_t *mySource;
    920     UChar32 myUChar;
    921     int32_t length;
    922 
    923     mySource = (const uint8_t *)args->source;
    924     if (mySource >= (const uint8_t *)args->sourceLimit)
    925     {
    926         /* no input */
    927         *err = U_INDEX_OUTOFBOUNDS_ERROR;
    928         return 0xffff;
    929     }
    930 
    931     length = (int32_t)((const uint8_t *)args->sourceLimit - mySource);
    932     if (length < 4)
    933     {
    934         /* got a partial character */
    935         uprv_memcpy(args->converter->toUBytes, mySource, length);
    936         args->converter->toULength = (int8_t)length;
    937         args->source = (const char *)(mySource + length);
    938         *err = U_TRUNCATED_CHAR_FOUND;
    939         return 0xffff;
    940     }
    941 
    942     /* Don't even try to do a direct cast because the value may be on an odd address. */
    943     myUChar = ((UChar32)mySource[3] << 24)
    944             | ((UChar32)mySource[2] << 16)
    945             | ((UChar32)mySource[1] << 8)
    946             | ((UChar32)mySource[0]);
    947 
    948     args->source = (const char *)(mySource + 4);
    949     if ((uint32_t)myUChar <= MAXIMUM_UTF && !U_IS_SURROGATE(myUChar)) {
    950         return myUChar;
    951     }
    952 
    953     uprv_memcpy(args->converter->toUBytes, mySource, 4);
    954     args->converter->toULength = 4;
    955 
    956     *err = U_ILLEGAL_CHAR_FOUND;
    957     return 0xffff;
    958 }
    959 U_CDECL_END
    960 static const UConverterImpl _UTF32LEImpl = {
    961     UCNV_UTF32_LittleEndian,
    962 
    963     NULL,
    964     NULL,
    965 
    966     NULL,
    967     NULL,
    968     NULL,
    969 
    970     T_UConverter_toUnicode_UTF32_LE,
    971     T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC,
    972     T_UConverter_fromUnicode_UTF32_LE,
    973     T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC,
    974     T_UConverter_getNextUChar_UTF32_LE,
    975 
    976     NULL,
    977     NULL,
    978     NULL,
    979     NULL,
    980     ucnv_getNonSurrogateUnicodeSet,
    981 
    982     NULL,
    983     NULL
    984 };
    985 
    986 /* The 1232 CCSID refers to any version of Unicode with any endianess of UTF-32 */
    987 static const UConverterStaticData _UTF32LEStaticData = {
    988     sizeof(UConverterStaticData),
    989     "UTF-32LE",
    990     1234,
    991     UCNV_IBM, UCNV_UTF32_LittleEndian, 4, 4,
    992     { 0xfd, 0xff, 0, 0 }, 4, FALSE, FALSE,
    993     0,
    994     0,
    995     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
    996 };
    997 
    998 
    999 const UConverterSharedData _UTF32LEData =
   1000         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32LEStaticData, &_UTF32LEImpl);
   1001 
   1002 /* UTF-32 (Detect BOM) ------------------------------------------------------ */
   1003 
   1004 /*
   1005  * Detect a BOM at the beginning of the stream and select UTF-32BE or UTF-32LE
   1006  * accordingly.
   1007  *
   1008  * State values:
   1009  * 0    initial state
   1010  * 1    saw 00
   1011  * 2    saw 00 00
   1012  * 3    saw 00 00 FE
   1013  * 4    -
   1014  * 5    saw FF
   1015  * 6    saw FF FE
   1016  * 7    saw FF FE 00
   1017  * 8    UTF-32BE mode
   1018  * 9    UTF-32LE mode
   1019  *
   1020  * During detection: state&3==number of matching bytes so far.
   1021  *
   1022  * On output, emit U+FEFF as the first code point.
   1023  */
   1024 U_CDECL_BEGIN
   1025 static void U_CALLCONV
   1026 _UTF32Reset(UConverter *cnv, UConverterResetChoice choice) {
   1027     if(choice<=UCNV_RESET_TO_UNICODE) {
   1028         /* reset toUnicode: state=0 */
   1029         cnv->mode=0;
   1030     }
   1031     if(choice!=UCNV_RESET_TO_UNICODE) {
   1032         /* reset fromUnicode: prepare to output the UTF-32PE BOM */
   1033         cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
   1034     }
   1035 }
   1036 
   1037 static void U_CALLCONV
   1038 _UTF32Open(UConverter *cnv,
   1039            UConverterLoadArgs *pArgs,
   1040            UErrorCode *pErrorCode) {
   1041     (void)pArgs;
   1042     (void)pErrorCode;
   1043     _UTF32Reset(cnv, UCNV_RESET_BOTH);
   1044 }
   1045 
   1046 static const char utf32BOM[8]={ 0, 0, (char)0xfeu, (char)0xffu, (char)0xffu, (char)0xfeu, 0, 0 };
   1047 
   1048 static void U_CALLCONV
   1049 _UTF32ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
   1050                            UErrorCode *pErrorCode) {
   1051     UConverter *cnv=pArgs->converter;
   1052     const char *source=pArgs->source;
   1053     const char *sourceLimit=pArgs->sourceLimit;
   1054     int32_t *offsets=pArgs->offsets;
   1055 
   1056     int32_t state, offsetDelta;
   1057     char b;
   1058 
   1059     state=cnv->mode;
   1060 
   1061     /*
   1062      * If we detect a BOM in this buffer, then we must add the BOM size to the
   1063      * offsets because the actual converter function will not see and count the BOM.
   1064      * offsetDelta will have the number of the BOM bytes that are in the current buffer.
   1065      */
   1066     offsetDelta=0;
   1067 
   1068     while(source<sourceLimit && U_SUCCESS(*pErrorCode)) {
   1069         switch(state) {
   1070         case 0:
   1071             b=*source;
   1072             if(b==0) {
   1073                 state=1; /* could be 00 00 FE FF */
   1074             } else if(b==(char)0xffu) {
   1075                 state=5; /* could be FF FE 00 00 */
   1076             } else {
   1077                 state=8; /* default to UTF-32BE */
   1078                 continue;
   1079             }
   1080             ++source;
   1081             break;
   1082         case 1:
   1083         case 2:
   1084         case 3:
   1085         case 5:
   1086         case 6:
   1087         case 7:
   1088             if(*source==utf32BOM[state]) {
   1089                 ++state;
   1090                 ++source;
   1091                 if(state==4) {
   1092                     state=8; /* detect UTF-32BE */
   1093                     offsetDelta=(int32_t)(source-pArgs->source);
   1094                 } else if(state==8) {
   1095                     state=9; /* detect UTF-32LE */
   1096                     offsetDelta=(int32_t)(source-pArgs->source);
   1097                 }
   1098             } else {
   1099                 /* switch to UTF-32BE and pass the previous bytes */
   1100                 int32_t count=(int32_t)(source-pArgs->source); /* number of bytes from this buffer */
   1101 
   1102                 /* reset the source */
   1103                 source=pArgs->source;
   1104 
   1105                 if(count==(state&3)) {
   1106                     /* simple: all in the same buffer, just reset source */
   1107                 } else {
   1108                     UBool oldFlush=pArgs->flush;
   1109 
   1110                     /* some of the bytes are from a previous buffer, replay those first */
   1111                     pArgs->source=utf32BOM+(state&4); /* select the correct BOM */
   1112                     pArgs->sourceLimit=pArgs->source+((state&3)-count); /* replay previous bytes */
   1113                     pArgs->flush=FALSE; /* this sourceLimit is not the real source stream limit */
   1114 
   1115                     /* no offsets: bytes from previous buffer, and not enough for output */
   1116                     T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode);
   1117 
   1118                     /* restore real pointers; pArgs->source will be set in case 8/9 */
   1119                     pArgs->sourceLimit=sourceLimit;
   1120                     pArgs->flush=oldFlush;
   1121                 }
   1122                 state=8;
   1123                 continue;
   1124             }
   1125             break;
   1126         case 8:
   1127             /* call UTF-32BE */
   1128             pArgs->source=source;
   1129             if(offsets==NULL) {
   1130                 T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode);
   1131             } else {
   1132                 T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC(pArgs, pErrorCode);
   1133             }
   1134             source=pArgs->source;
   1135             break;
   1136         case 9:
   1137             /* call UTF-32LE */
   1138             pArgs->source=source;
   1139             if(offsets==NULL) {
   1140                 T_UConverter_toUnicode_UTF32_LE(pArgs, pErrorCode);
   1141             } else {
   1142                 T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC(pArgs, pErrorCode);
   1143             }
   1144             source=pArgs->source;
   1145             break;
   1146         default:
   1147             break; /* does not occur */
   1148         }
   1149     }
   1150 
   1151     /* add BOM size to offsets - see comment at offsetDelta declaration */
   1152     if(offsets!=NULL && offsetDelta!=0) {
   1153         int32_t *offsetsLimit=pArgs->offsets;
   1154         while(offsets<offsetsLimit) {
   1155             *offsets++ += offsetDelta;
   1156         }
   1157     }
   1158 
   1159     pArgs->source=source;
   1160 
   1161     if(source==sourceLimit && pArgs->flush) {
   1162         /* handle truncated input */
   1163         switch(state) {
   1164         case 0:
   1165             break; /* no input at all, nothing to do */
   1166         case 8:
   1167             T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode);
   1168             break;
   1169         case 9:
   1170             T_UConverter_toUnicode_UTF32_LE(pArgs, pErrorCode);
   1171             break;
   1172         default:
   1173             /* handle 0<state<8: call UTF-32BE with too-short input */
   1174             pArgs->source=utf32BOM+(state&4); /* select the correct BOM */
   1175             pArgs->sourceLimit=pArgs->source+(state&3); /* replay bytes */
   1176 
   1177             /* no offsets: not enough for output */
   1178             T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode);
   1179             pArgs->source=source;
   1180             pArgs->sourceLimit=sourceLimit;
   1181             state=8;
   1182             break;
   1183         }
   1184     }
   1185 
   1186     cnv->mode=state;
   1187 }
   1188 
   1189 static UChar32 U_CALLCONV
   1190 _UTF32GetNextUChar(UConverterToUnicodeArgs *pArgs,
   1191                    UErrorCode *pErrorCode) {
   1192     switch(pArgs->converter->mode) {
   1193     case 8:
   1194         return T_UConverter_getNextUChar_UTF32_BE(pArgs, pErrorCode);
   1195     case 9:
   1196         return T_UConverter_getNextUChar_UTF32_LE(pArgs, pErrorCode);
   1197     default:
   1198         return UCNV_GET_NEXT_UCHAR_USE_TO_U;
   1199     }
   1200 }
   1201 U_CDECL_END
   1202 static const UConverterImpl _UTF32Impl = {
   1203     UCNV_UTF32,
   1204 
   1205     NULL,
   1206     NULL,
   1207 
   1208     _UTF32Open,
   1209     NULL,
   1210     _UTF32Reset,
   1211 
   1212     _UTF32ToUnicodeWithOffsets,
   1213     _UTF32ToUnicodeWithOffsets,
   1214 #if U_IS_BIG_ENDIAN
   1215     T_UConverter_fromUnicode_UTF32_BE,
   1216     T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC,
   1217 #else
   1218     T_UConverter_fromUnicode_UTF32_LE,
   1219     T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC,
   1220 #endif
   1221     _UTF32GetNextUChar,
   1222 
   1223     NULL, /* ### TODO implement getStarters for all Unicode encodings?! */
   1224     NULL,
   1225     NULL,
   1226     NULL,
   1227     ucnv_getNonSurrogateUnicodeSet,
   1228 
   1229     NULL,
   1230     NULL
   1231 };
   1232 
   1233 /* The 1236 CCSID refers to any version of Unicode with a BOM sensitive endianess of UTF-32 */
   1234 static const UConverterStaticData _UTF32StaticData = {
   1235     sizeof(UConverterStaticData),
   1236     "UTF-32",
   1237     1236,
   1238     UCNV_IBM, UCNV_UTF32, 4, 4,
   1239 #if U_IS_BIG_ENDIAN
   1240     { 0, 0, 0xff, 0xfd }, 4,
   1241 #else
   1242     { 0xfd, 0xff, 0, 0 }, 4,
   1243 #endif
   1244     FALSE, FALSE,
   1245     0,
   1246     0,
   1247     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
   1248 };
   1249 
   1250 const UConverterSharedData _UTF32Data =
   1251         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32StaticData, &_UTF32Impl);
   1252 
   1253 #endif
   1254