michael@0: /* michael@0: ********************************************************************** michael@0: * Copyright (C) 2002-2011, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ********************************************************************** michael@0: * file name: ucnv_u32.c michael@0: * encoding: US-ASCII michael@0: * tab size: 8 (not used) michael@0: * indentation:4 michael@0: * michael@0: * created on: 2002jul01 michael@0: * created by: Markus W. Scherer michael@0: * michael@0: * UTF-32 converter implementation. Used to be in ucnv_utf.c. michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: michael@0: #if !UCONFIG_NO_CONVERSION michael@0: michael@0: #include "unicode/ucnv.h" michael@0: #include "unicode/utf.h" michael@0: #include "ucnv_bld.h" michael@0: #include "ucnv_cnv.h" michael@0: #include "cmemory.h" michael@0: michael@0: #define MAXIMUM_UCS2 0x0000FFFF michael@0: #define MAXIMUM_UTF 0x0010FFFF michael@0: #define HALF_SHIFT 10 michael@0: #define HALF_BASE 0x0010000 michael@0: #define HALF_MASK 0x3FF michael@0: #define SURROGATE_HIGH_START 0xD800 michael@0: #define SURROGATE_LOW_START 0xDC00 michael@0: michael@0: /* -SURROGATE_LOW_START + HALF_BASE */ michael@0: #define SURROGATE_LOW_BASE 9216 michael@0: michael@0: enum { michael@0: UCNV_NEED_TO_WRITE_BOM=1 michael@0: }; michael@0: michael@0: /* UTF-32BE ----------------------------------------------------------------- */ michael@0: michael@0: static void michael@0: T_UConverter_toUnicode_UTF32_BE(UConverterToUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const unsigned char *mySource = (unsigned char *) args->source; michael@0: UChar *myTarget = args->target; michael@0: const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit; michael@0: const UChar *targetLimit = args->targetLimit; michael@0: unsigned char *toUBytes = args->converter->toUBytes; michael@0: uint32_t ch, i; michael@0: michael@0: /* Restore state of current sequence */ michael@0: if (args->converter->toUnicodeStatus && myTarget < targetLimit) { michael@0: i = args->converter->toULength; /* restore # of bytes consumed */ michael@0: args->converter->toULength = 0; michael@0: michael@0: ch = args->converter->toUnicodeStatus - 1;/*Stores the previously calculated ch from a previous call*/ michael@0: args->converter->toUnicodeStatus = 0; michael@0: goto morebytes; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) { michael@0: i = 0; michael@0: ch = 0; michael@0: morebytes: michael@0: while (i < sizeof(uint32_t)) { michael@0: if (mySource < sourceLimit) { michael@0: ch = (ch << 8) | (uint8_t)(*mySource); michael@0: toUBytes[i++] = (char) *(mySource++); michael@0: } michael@0: else { michael@0: /* stores a partially calculated target*/ michael@0: /* + 1 to make 0 a valid character */ michael@0: args->converter->toUnicodeStatus = ch + 1; michael@0: args->converter->toULength = (int8_t) i; michael@0: goto donefornow; michael@0: } michael@0: } michael@0: michael@0: if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) { michael@0: /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */ michael@0: if (ch <= MAXIMUM_UCS2) michael@0: { michael@0: /* fits in 16 bits */ michael@0: *(myTarget++) = (UChar) ch; michael@0: } michael@0: else { michael@0: /* write out the surrogates */ michael@0: *(myTarget++) = U16_LEAD(ch); michael@0: ch = U16_TRAIL(ch); michael@0: if (myTarget < targetLimit) { michael@0: *(myTarget++) = (UChar)ch; michael@0: } michael@0: else { michael@0: /* Put in overflow buffer (not handled here) */ michael@0: args->converter->UCharErrorBuffer[0] = (UChar) ch; michael@0: args->converter->UCharErrorBufferLength = 1; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: args->converter->toULength = (int8_t)i; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: donefornow: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) { michael@0: /* End of target buffer */ michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = myTarget; michael@0: args->source = (const char *) mySource; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC(UConverterToUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const unsigned char *mySource = (unsigned char *) args->source; michael@0: UChar *myTarget = args->target; michael@0: int32_t *myOffsets = args->offsets; michael@0: const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit; michael@0: const UChar *targetLimit = args->targetLimit; michael@0: unsigned char *toUBytes = args->converter->toUBytes; michael@0: uint32_t ch, i; michael@0: int32_t offsetNum = 0; michael@0: michael@0: /* Restore state of current sequence */ michael@0: if (args->converter->toUnicodeStatus && myTarget < targetLimit) { michael@0: i = args->converter->toULength; /* restore # of bytes consumed */ michael@0: args->converter->toULength = 0; michael@0: michael@0: ch = args->converter->toUnicodeStatus - 1;/*Stores the previously calculated ch from a previous call*/ michael@0: args->converter->toUnicodeStatus = 0; michael@0: goto morebytes; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) { michael@0: i = 0; michael@0: ch = 0; michael@0: morebytes: michael@0: while (i < sizeof(uint32_t)) { michael@0: if (mySource < sourceLimit) { michael@0: ch = (ch << 8) | (uint8_t)(*mySource); michael@0: toUBytes[i++] = (char) *(mySource++); michael@0: } michael@0: else { michael@0: /* stores a partially calculated target*/ michael@0: /* + 1 to make 0 a valid character */ michael@0: args->converter->toUnicodeStatus = ch + 1; michael@0: args->converter->toULength = (int8_t) i; michael@0: goto donefornow; michael@0: } michael@0: } michael@0: michael@0: if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) { michael@0: /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */ michael@0: if (ch <= MAXIMUM_UCS2) { michael@0: /* fits in 16 bits */ michael@0: *(myTarget++) = (UChar) ch; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else { michael@0: /* write out the surrogates */ michael@0: *(myTarget++) = U16_LEAD(ch); michael@0: *myOffsets++ = offsetNum; michael@0: ch = U16_TRAIL(ch); michael@0: if (myTarget < targetLimit) michael@0: { michael@0: *(myTarget++) = (UChar)ch; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else { michael@0: /* Put in overflow buffer (not handled here) */ michael@0: args->converter->UCharErrorBuffer[0] = (UChar) ch; michael@0: args->converter->UCharErrorBufferLength = 1; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: args->converter->toULength = (int8_t)i; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: offsetNum += i; michael@0: } michael@0: michael@0: donefornow: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) michael@0: { michael@0: /* End of target buffer */ michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = myTarget; michael@0: args->source = (const char *) mySource; michael@0: args->offsets = myOffsets; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_fromUnicode_UTF32_BE(UConverterFromUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const UChar *mySource = args->source; michael@0: unsigned char *myTarget; michael@0: const UChar *sourceLimit = args->sourceLimit; michael@0: const unsigned char *targetLimit = (unsigned char *) args->targetLimit; michael@0: UChar32 ch, ch2; michael@0: unsigned int indexToWrite; michael@0: unsigned char temp[sizeof(uint32_t)]; michael@0: michael@0: if(mySource >= sourceLimit) { michael@0: /* no input, nothing to do */ michael@0: return; michael@0: } michael@0: michael@0: /* write the BOM if necessary */ michael@0: if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { michael@0: static const char bom[]={ 0, 0, (char)0xfe, (char)0xff }; michael@0: ucnv_fromUWriteBytes(args->converter, michael@0: bom, 4, michael@0: &args->target, args->targetLimit, michael@0: &args->offsets, -1, michael@0: err); michael@0: args->converter->fromUnicodeStatus=0; michael@0: } michael@0: michael@0: myTarget = (unsigned char *) args->target; michael@0: temp[0] = 0; michael@0: michael@0: if (args->converter->fromUChar32) { michael@0: ch = args->converter->fromUChar32; michael@0: args->converter->fromUChar32 = 0; michael@0: goto lowsurogate; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) { michael@0: ch = *(mySource++); michael@0: michael@0: if (U_IS_SURROGATE(ch)) { michael@0: if (U_IS_LEAD(ch)) { michael@0: lowsurogate: michael@0: if (mySource < sourceLimit) { michael@0: ch2 = *mySource; michael@0: if (U_IS_TRAIL(ch2)) { michael@0: ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE; michael@0: mySource++; michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* ran out of source */ michael@0: args->converter->fromUChar32 = ch; michael@0: if (args->flush) { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */ michael@0: temp[1] = (uint8_t) (ch >> 16 & 0x1F); michael@0: temp[2] = (uint8_t) (ch >> 8); /* unsigned cast implicitly does (ch & FF) */ michael@0: temp[3] = (uint8_t) (ch); /* unsigned cast implicitly does (ch & FF) */ michael@0: michael@0: for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) { michael@0: if (myTarget < targetLimit) { michael@0: *(myTarget++) = temp[indexToWrite]; michael@0: } michael@0: else { michael@0: args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite]; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) { michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = (char *) myTarget; michael@0: args->source = mySource; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const UChar *mySource = args->source; michael@0: unsigned char *myTarget; michael@0: int32_t *myOffsets; michael@0: const UChar *sourceLimit = args->sourceLimit; michael@0: const unsigned char *targetLimit = (unsigned char *) args->targetLimit; michael@0: UChar32 ch, ch2; michael@0: int32_t offsetNum = 0; michael@0: unsigned int indexToWrite; michael@0: unsigned char temp[sizeof(uint32_t)]; michael@0: michael@0: if(mySource >= sourceLimit) { michael@0: /* no input, nothing to do */ michael@0: return; michael@0: } michael@0: michael@0: /* write the BOM if necessary */ michael@0: if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { michael@0: static const char bom[]={ 0, 0, (char)0xfe, (char)0xff }; michael@0: ucnv_fromUWriteBytes(args->converter, michael@0: bom, 4, michael@0: &args->target, args->targetLimit, michael@0: &args->offsets, -1, michael@0: err); michael@0: args->converter->fromUnicodeStatus=0; michael@0: } michael@0: michael@0: myTarget = (unsigned char *) args->target; michael@0: myOffsets = args->offsets; michael@0: temp[0] = 0; michael@0: michael@0: if (args->converter->fromUChar32) { michael@0: ch = args->converter->fromUChar32; michael@0: args->converter->fromUChar32 = 0; michael@0: goto lowsurogate; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) { michael@0: ch = *(mySource++); michael@0: michael@0: if (U_IS_SURROGATE(ch)) { michael@0: if (U_IS_LEAD(ch)) { michael@0: lowsurogate: michael@0: if (mySource < sourceLimit) { michael@0: ch2 = *mySource; michael@0: if (U_IS_TRAIL(ch2)) { michael@0: ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE; michael@0: mySource++; michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* ran out of source */ michael@0: args->converter->fromUChar32 = ch; michael@0: if (args->flush) { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */ michael@0: temp[1] = (uint8_t) (ch >> 16 & 0x1F); michael@0: temp[2] = (uint8_t) (ch >> 8); /* unsigned cast implicitly does (ch & FF) */ michael@0: temp[3] = (uint8_t) (ch); /* unsigned cast implicitly does (ch & FF) */ michael@0: michael@0: for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) { michael@0: if (myTarget < targetLimit) { michael@0: *(myTarget++) = temp[indexToWrite]; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else { michael@0: args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite]; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: } michael@0: offsetNum = offsetNum + 1 + (temp[1] != 0); michael@0: } michael@0: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) { michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = (char *) myTarget; michael@0: args->source = mySource; michael@0: args->offsets = myOffsets; michael@0: } michael@0: michael@0: static UChar32 michael@0: T_UConverter_getNextUChar_UTF32_BE(UConverterToUnicodeArgs* args, michael@0: UErrorCode* err) michael@0: { michael@0: const uint8_t *mySource; michael@0: UChar32 myUChar; michael@0: int32_t length; michael@0: michael@0: mySource = (const uint8_t *)args->source; michael@0: if (mySource >= (const uint8_t *)args->sourceLimit) michael@0: { michael@0: /* no input */ michael@0: *err = U_INDEX_OUTOFBOUNDS_ERROR; michael@0: return 0xffff; michael@0: } michael@0: michael@0: length = (int32_t)((const uint8_t *)args->sourceLimit - mySource); michael@0: if (length < 4) michael@0: { michael@0: /* got a partial character */ michael@0: uprv_memcpy(args->converter->toUBytes, mySource, length); michael@0: args->converter->toULength = (int8_t)length; michael@0: args->source = (const char *)(mySource + length); michael@0: *err = U_TRUNCATED_CHAR_FOUND; michael@0: return 0xffff; michael@0: } michael@0: michael@0: /* Don't even try to do a direct cast because the value may be on an odd address. */ michael@0: myUChar = ((UChar32)mySource[0] << 24) michael@0: | ((UChar32)mySource[1] << 16) michael@0: | ((UChar32)mySource[2] << 8) michael@0: | ((UChar32)mySource[3]); michael@0: michael@0: args->source = (const char *)(mySource + 4); michael@0: if ((uint32_t)myUChar <= MAXIMUM_UTF && !U_IS_SURROGATE(myUChar)) { michael@0: return myUChar; michael@0: } michael@0: michael@0: uprv_memcpy(args->converter->toUBytes, mySource, 4); michael@0: args->converter->toULength = 4; michael@0: michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: return 0xffff; michael@0: } michael@0: michael@0: static const UConverterImpl _UTF32BEImpl = { michael@0: UCNV_UTF32_BigEndian, michael@0: michael@0: NULL, michael@0: NULL, michael@0: michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: michael@0: T_UConverter_toUnicode_UTF32_BE, michael@0: T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC, michael@0: T_UConverter_fromUnicode_UTF32_BE, michael@0: T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC, michael@0: T_UConverter_getNextUChar_UTF32_BE, michael@0: michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: ucnv_getNonSurrogateUnicodeSet michael@0: }; michael@0: michael@0: /* The 1232 CCSID refers to any version of Unicode with any endianess of UTF-32 */ michael@0: static const UConverterStaticData _UTF32BEStaticData = { michael@0: sizeof(UConverterStaticData), michael@0: "UTF-32BE", michael@0: 1232, michael@0: UCNV_IBM, UCNV_UTF32_BigEndian, 4, 4, michael@0: { 0, 0, 0xff, 0xfd }, 4, FALSE, FALSE, michael@0: 0, michael@0: 0, michael@0: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */ michael@0: }; michael@0: michael@0: const UConverterSharedData _UTF32BEData = { michael@0: sizeof(UConverterSharedData), ~((uint32_t) 0), michael@0: NULL, NULL, &_UTF32BEStaticData, FALSE, &_UTF32BEImpl, michael@0: 0 michael@0: }; michael@0: michael@0: /* UTF-32LE ---------------------------------------------------------- */ michael@0: michael@0: static void michael@0: T_UConverter_toUnicode_UTF32_LE(UConverterToUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const unsigned char *mySource = (unsigned char *) args->source; michael@0: UChar *myTarget = args->target; michael@0: const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit; michael@0: const UChar *targetLimit = args->targetLimit; michael@0: unsigned char *toUBytes = args->converter->toUBytes; michael@0: uint32_t ch, i; michael@0: michael@0: /* Restore state of current sequence */ michael@0: if (args->converter->toUnicodeStatus && myTarget < targetLimit) michael@0: { michael@0: i = args->converter->toULength; /* restore # of bytes consumed */ michael@0: args->converter->toULength = 0; michael@0: michael@0: /* Stores the previously calculated ch from a previous call*/ michael@0: ch = args->converter->toUnicodeStatus - 1; michael@0: args->converter->toUnicodeStatus = 0; michael@0: goto morebytes; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) michael@0: { michael@0: i = 0; michael@0: ch = 0; michael@0: morebytes: michael@0: while (i < sizeof(uint32_t)) michael@0: { michael@0: if (mySource < sourceLimit) michael@0: { michael@0: ch |= ((uint8_t)(*mySource)) << (i * 8); michael@0: toUBytes[i++] = (char) *(mySource++); michael@0: } michael@0: else michael@0: { michael@0: /* stores a partially calculated target*/ michael@0: /* + 1 to make 0 a valid character */ michael@0: args->converter->toUnicodeStatus = ch + 1; michael@0: args->converter->toULength = (int8_t) i; michael@0: goto donefornow; michael@0: } michael@0: } michael@0: michael@0: if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) { michael@0: /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */ michael@0: if (ch <= MAXIMUM_UCS2) { michael@0: /* fits in 16 bits */ michael@0: *(myTarget++) = (UChar) ch; michael@0: } michael@0: else { michael@0: /* write out the surrogates */ michael@0: *(myTarget++) = U16_LEAD(ch); michael@0: ch = U16_TRAIL(ch); michael@0: if (myTarget < targetLimit) { michael@0: *(myTarget++) = (UChar)ch; michael@0: } michael@0: else { michael@0: /* Put in overflow buffer (not handled here) */ michael@0: args->converter->UCharErrorBuffer[0] = (UChar) ch; michael@0: args->converter->UCharErrorBufferLength = 1; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: args->converter->toULength = (int8_t)i; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: donefornow: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) michael@0: { michael@0: /* End of target buffer */ michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = myTarget; michael@0: args->source = (const char *) mySource; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC(UConverterToUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const unsigned char *mySource = (unsigned char *) args->source; michael@0: UChar *myTarget = args->target; michael@0: int32_t *myOffsets = args->offsets; michael@0: const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit; michael@0: const UChar *targetLimit = args->targetLimit; michael@0: unsigned char *toUBytes = args->converter->toUBytes; michael@0: uint32_t ch, i; michael@0: int32_t offsetNum = 0; michael@0: michael@0: /* Restore state of current sequence */ michael@0: if (args->converter->toUnicodeStatus && myTarget < targetLimit) michael@0: { michael@0: i = args->converter->toULength; /* restore # of bytes consumed */ michael@0: args->converter->toULength = 0; michael@0: michael@0: /* Stores the previously calculated ch from a previous call*/ michael@0: ch = args->converter->toUnicodeStatus - 1; michael@0: args->converter->toUnicodeStatus = 0; michael@0: goto morebytes; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) michael@0: { michael@0: i = 0; michael@0: ch = 0; michael@0: morebytes: michael@0: while (i < sizeof(uint32_t)) michael@0: { michael@0: if (mySource < sourceLimit) michael@0: { michael@0: ch |= ((uint8_t)(*mySource)) << (i * 8); michael@0: toUBytes[i++] = (char) *(mySource++); michael@0: } michael@0: else michael@0: { michael@0: /* stores a partially calculated target*/ michael@0: /* + 1 to make 0 a valid character */ michael@0: args->converter->toUnicodeStatus = ch + 1; michael@0: args->converter->toULength = (int8_t) i; michael@0: goto donefornow; michael@0: } michael@0: } michael@0: michael@0: if (ch <= MAXIMUM_UTF && !U_IS_SURROGATE(ch)) michael@0: { michael@0: /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */ michael@0: if (ch <= MAXIMUM_UCS2) michael@0: { michael@0: /* fits in 16 bits */ michael@0: *(myTarget++) = (UChar) ch; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else { michael@0: /* write out the surrogates */ michael@0: *(myTarget++) = U16_LEAD(ch); michael@0: *(myOffsets++) = offsetNum; michael@0: ch = U16_TRAIL(ch); michael@0: if (myTarget < targetLimit) michael@0: { michael@0: *(myTarget++) = (UChar)ch; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else michael@0: { michael@0: /* Put in overflow buffer (not handled here) */ michael@0: args->converter->UCharErrorBuffer[0] = (UChar) ch; michael@0: args->converter->UCharErrorBufferLength = 1; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: else michael@0: { michael@0: args->converter->toULength = (int8_t)i; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: offsetNum += i; michael@0: } michael@0: michael@0: donefornow: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) michael@0: { michael@0: /* End of target buffer */ michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = myTarget; michael@0: args->source = (const char *) mySource; michael@0: args->offsets = myOffsets; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_fromUnicode_UTF32_LE(UConverterFromUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const UChar *mySource = args->source; michael@0: unsigned char *myTarget; michael@0: const UChar *sourceLimit = args->sourceLimit; michael@0: const unsigned char *targetLimit = (unsigned char *) args->targetLimit; michael@0: UChar32 ch, ch2; michael@0: unsigned int indexToWrite; michael@0: unsigned char temp[sizeof(uint32_t)]; michael@0: michael@0: if(mySource >= sourceLimit) { michael@0: /* no input, nothing to do */ michael@0: return; michael@0: } michael@0: michael@0: /* write the BOM if necessary */ michael@0: if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { michael@0: static const char bom[]={ (char)0xff, (char)0xfe, 0, 0 }; michael@0: ucnv_fromUWriteBytes(args->converter, michael@0: bom, 4, michael@0: &args->target, args->targetLimit, michael@0: &args->offsets, -1, michael@0: err); michael@0: args->converter->fromUnicodeStatus=0; michael@0: } michael@0: michael@0: myTarget = (unsigned char *) args->target; michael@0: temp[3] = 0; michael@0: michael@0: if (args->converter->fromUChar32) michael@0: { michael@0: ch = args->converter->fromUChar32; michael@0: args->converter->fromUChar32 = 0; michael@0: goto lowsurogate; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) michael@0: { michael@0: ch = *(mySource++); michael@0: michael@0: if (U16_IS_SURROGATE(ch)) { michael@0: if (U16_IS_LEAD(ch)) michael@0: { michael@0: lowsurogate: michael@0: if (mySource < sourceLimit) michael@0: { michael@0: ch2 = *mySource; michael@0: if (U16_IS_TRAIL(ch2)) { michael@0: ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE; michael@0: mySource++; michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* ran out of source */ michael@0: args->converter->fromUChar32 = ch; michael@0: if (args->flush) { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */ michael@0: temp[2] = (uint8_t) (ch >> 16 & 0x1F); michael@0: temp[1] = (uint8_t) (ch >> 8); /* unsigned cast implicitly does (ch & FF) */ michael@0: temp[0] = (uint8_t) (ch); /* unsigned cast implicitly does (ch & FF) */ michael@0: michael@0: for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) michael@0: { michael@0: if (myTarget < targetLimit) michael@0: { michael@0: *(myTarget++) = temp[indexToWrite]; michael@0: } michael@0: else michael@0: { michael@0: args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite]; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) michael@0: { michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = (char *) myTarget; michael@0: args->source = mySource; michael@0: } michael@0: michael@0: static void michael@0: T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args, michael@0: UErrorCode * err) michael@0: { michael@0: const UChar *mySource = args->source; michael@0: unsigned char *myTarget; michael@0: int32_t *myOffsets; michael@0: const UChar *sourceLimit = args->sourceLimit; michael@0: const unsigned char *targetLimit = (unsigned char *) args->targetLimit; michael@0: UChar32 ch, ch2; michael@0: unsigned int indexToWrite; michael@0: unsigned char temp[sizeof(uint32_t)]; michael@0: int32_t offsetNum = 0; michael@0: michael@0: if(mySource >= sourceLimit) { michael@0: /* no input, nothing to do */ michael@0: return; michael@0: } michael@0: michael@0: /* write the BOM if necessary */ michael@0: if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { michael@0: static const char bom[]={ (char)0xff, (char)0xfe, 0, 0 }; michael@0: ucnv_fromUWriteBytes(args->converter, michael@0: bom, 4, michael@0: &args->target, args->targetLimit, michael@0: &args->offsets, -1, michael@0: err); michael@0: args->converter->fromUnicodeStatus=0; michael@0: } michael@0: michael@0: myTarget = (unsigned char *) args->target; michael@0: myOffsets = args->offsets; michael@0: temp[3] = 0; michael@0: michael@0: if (args->converter->fromUChar32) michael@0: { michael@0: ch = args->converter->fromUChar32; michael@0: args->converter->fromUChar32 = 0; michael@0: goto lowsurogate; michael@0: } michael@0: michael@0: while (mySource < sourceLimit && myTarget < targetLimit) michael@0: { michael@0: ch = *(mySource++); michael@0: michael@0: if (U16_IS_SURROGATE(ch)) { michael@0: if (U16_IS_LEAD(ch)) michael@0: { michael@0: lowsurogate: michael@0: if (mySource < sourceLimit) michael@0: { michael@0: ch2 = *mySource; michael@0: if (U16_IS_TRAIL(ch2)) michael@0: { michael@0: ch = ((ch - SURROGATE_HIGH_START) << HALF_SHIFT) + ch2 + SURROGATE_LOW_BASE; michael@0: mySource++; michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* ran out of source */ michael@0: args->converter->fromUChar32 = ch; michael@0: if (args->flush) { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: else { michael@0: /* this is an unmatched trail code unit (2nd surrogate) */ michael@0: /* callback(illegal) */ michael@0: args->converter->fromUChar32 = ch; michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* We cannot get any larger than 10FFFF because we are coming from UTF-16 */ michael@0: temp[2] = (uint8_t) (ch >> 16 & 0x1F); michael@0: temp[1] = (uint8_t) (ch >> 8); /* unsigned cast implicitly does (ch & FF) */ michael@0: temp[0] = (uint8_t) (ch); /* unsigned cast implicitly does (ch & FF) */ michael@0: michael@0: for (indexToWrite = 0; indexToWrite <= sizeof(uint32_t) - 1; indexToWrite++) michael@0: { michael@0: if (myTarget < targetLimit) michael@0: { michael@0: *(myTarget++) = temp[indexToWrite]; michael@0: *(myOffsets++) = offsetNum; michael@0: } michael@0: else michael@0: { michael@0: args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = temp[indexToWrite]; michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: } michael@0: offsetNum = offsetNum + 1 + (temp[2] != 0); michael@0: } michael@0: michael@0: if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err)) michael@0: { michael@0: *err = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: michael@0: args->target = (char *) myTarget; michael@0: args->source = mySource; michael@0: args->offsets = myOffsets; michael@0: } michael@0: michael@0: static UChar32 michael@0: T_UConverter_getNextUChar_UTF32_LE(UConverterToUnicodeArgs* args, michael@0: UErrorCode* err) michael@0: { michael@0: const uint8_t *mySource; michael@0: UChar32 myUChar; michael@0: int32_t length; michael@0: michael@0: mySource = (const uint8_t *)args->source; michael@0: if (mySource >= (const uint8_t *)args->sourceLimit) michael@0: { michael@0: /* no input */ michael@0: *err = U_INDEX_OUTOFBOUNDS_ERROR; michael@0: return 0xffff; michael@0: } michael@0: michael@0: length = (int32_t)((const uint8_t *)args->sourceLimit - mySource); michael@0: if (length < 4) michael@0: { michael@0: /* got a partial character */ michael@0: uprv_memcpy(args->converter->toUBytes, mySource, length); michael@0: args->converter->toULength = (int8_t)length; michael@0: args->source = (const char *)(mySource + length); michael@0: *err = U_TRUNCATED_CHAR_FOUND; michael@0: return 0xffff; michael@0: } michael@0: michael@0: /* Don't even try to do a direct cast because the value may be on an odd address. */ michael@0: myUChar = ((UChar32)mySource[3] << 24) michael@0: | ((UChar32)mySource[2] << 16) michael@0: | ((UChar32)mySource[1] << 8) michael@0: | ((UChar32)mySource[0]); michael@0: michael@0: args->source = (const char *)(mySource + 4); michael@0: if ((uint32_t)myUChar <= MAXIMUM_UTF && !U_IS_SURROGATE(myUChar)) { michael@0: return myUChar; michael@0: } michael@0: michael@0: uprv_memcpy(args->converter->toUBytes, mySource, 4); michael@0: args->converter->toULength = 4; michael@0: michael@0: *err = U_ILLEGAL_CHAR_FOUND; michael@0: return 0xffff; michael@0: } michael@0: michael@0: static const UConverterImpl _UTF32LEImpl = { michael@0: UCNV_UTF32_LittleEndian, michael@0: michael@0: NULL, michael@0: NULL, michael@0: michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: michael@0: T_UConverter_toUnicode_UTF32_LE, michael@0: T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC, michael@0: T_UConverter_fromUnicode_UTF32_LE, michael@0: T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC, michael@0: T_UConverter_getNextUChar_UTF32_LE, michael@0: michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: ucnv_getNonSurrogateUnicodeSet michael@0: }; michael@0: michael@0: /* The 1232 CCSID refers to any version of Unicode with any endianess of UTF-32 */ michael@0: static const UConverterStaticData _UTF32LEStaticData = { michael@0: sizeof(UConverterStaticData), michael@0: "UTF-32LE", michael@0: 1234, michael@0: UCNV_IBM, UCNV_UTF32_LittleEndian, 4, 4, michael@0: { 0xfd, 0xff, 0, 0 }, 4, FALSE, FALSE, michael@0: 0, michael@0: 0, michael@0: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */ michael@0: }; michael@0: michael@0: michael@0: const UConverterSharedData _UTF32LEData = { michael@0: sizeof(UConverterSharedData), ~((uint32_t) 0), michael@0: NULL, NULL, &_UTF32LEStaticData, FALSE, &_UTF32LEImpl, michael@0: 0 michael@0: }; michael@0: michael@0: /* UTF-32 (Detect BOM) ------------------------------------------------------ */ michael@0: michael@0: /* michael@0: * Detect a BOM at the beginning of the stream and select UTF-32BE or UTF-32LE michael@0: * accordingly. michael@0: * michael@0: * State values: michael@0: * 0 initial state michael@0: * 1 saw 00 michael@0: * 2 saw 00 00 michael@0: * 3 saw 00 00 FE michael@0: * 4 - michael@0: * 5 saw FF michael@0: * 6 saw FF FE michael@0: * 7 saw FF FE 00 michael@0: * 8 UTF-32BE mode michael@0: * 9 UTF-32LE mode michael@0: * michael@0: * During detection: state&3==number of matching bytes so far. michael@0: * michael@0: * On output, emit U+FEFF as the first code point. michael@0: */ michael@0: michael@0: static void michael@0: _UTF32Reset(UConverter *cnv, UConverterResetChoice choice) { michael@0: if(choice<=UCNV_RESET_TO_UNICODE) { michael@0: /* reset toUnicode: state=0 */ michael@0: cnv->mode=0; michael@0: } michael@0: if(choice!=UCNV_RESET_TO_UNICODE) { michael@0: /* reset fromUnicode: prepare to output the UTF-32PE BOM */ michael@0: cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM; michael@0: } michael@0: } michael@0: michael@0: static void michael@0: _UTF32Open(UConverter *cnv, michael@0: UConverterLoadArgs *pArgs, michael@0: UErrorCode *pErrorCode) { michael@0: _UTF32Reset(cnv, UCNV_RESET_BOTH); michael@0: } michael@0: michael@0: static const char utf32BOM[8]={ 0, 0, (char)0xfe, (char)0xff, (char)0xff, (char)0xfe, 0, 0 }; michael@0: michael@0: static void michael@0: _UTF32ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, michael@0: UErrorCode *pErrorCode) { michael@0: UConverter *cnv=pArgs->converter; michael@0: const char *source=pArgs->source; michael@0: const char *sourceLimit=pArgs->sourceLimit; michael@0: int32_t *offsets=pArgs->offsets; michael@0: michael@0: int32_t state, offsetDelta; michael@0: char b; michael@0: michael@0: state=cnv->mode; michael@0: michael@0: /* michael@0: * If we detect a BOM in this buffer, then we must add the BOM size to the michael@0: * offsets because the actual converter function will not see and count the BOM. michael@0: * offsetDelta will have the number of the BOM bytes that are in the current buffer. michael@0: */ michael@0: offsetDelta=0; michael@0: michael@0: while(sourcesource); michael@0: } else if(state==8) { michael@0: state=9; /* detect UTF-32LE */ michael@0: offsetDelta=(int32_t)(source-pArgs->source); michael@0: } michael@0: } else { michael@0: /* switch to UTF-32BE and pass the previous bytes */ michael@0: int32_t count=(int32_t)(source-pArgs->source); /* number of bytes from this buffer */ michael@0: michael@0: /* reset the source */ michael@0: source=pArgs->source; michael@0: michael@0: if(count==(state&3)) { michael@0: /* simple: all in the same buffer, just reset source */ michael@0: } else { michael@0: UBool oldFlush=pArgs->flush; michael@0: michael@0: /* some of the bytes are from a previous buffer, replay those first */ michael@0: pArgs->source=utf32BOM+(state&4); /* select the correct BOM */ michael@0: pArgs->sourceLimit=pArgs->source+((state&3)-count); /* replay previous bytes */ michael@0: pArgs->flush=FALSE; /* this sourceLimit is not the real source stream limit */ michael@0: michael@0: /* no offsets: bytes from previous buffer, and not enough for output */ michael@0: T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode); michael@0: michael@0: /* restore real pointers; pArgs->source will be set in case 8/9 */ michael@0: pArgs->sourceLimit=sourceLimit; michael@0: pArgs->flush=oldFlush; michael@0: } michael@0: state=8; michael@0: continue; michael@0: } michael@0: break; michael@0: case 8: michael@0: /* call UTF-32BE */ michael@0: pArgs->source=source; michael@0: if(offsets==NULL) { michael@0: T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode); michael@0: } else { michael@0: T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC(pArgs, pErrorCode); michael@0: } michael@0: source=pArgs->source; michael@0: break; michael@0: case 9: michael@0: /* call UTF-32LE */ michael@0: pArgs->source=source; michael@0: if(offsets==NULL) { michael@0: T_UConverter_toUnicode_UTF32_LE(pArgs, pErrorCode); michael@0: } else { michael@0: T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC(pArgs, pErrorCode); michael@0: } michael@0: source=pArgs->source; michael@0: break; michael@0: default: michael@0: break; /* does not occur */ michael@0: } michael@0: } michael@0: michael@0: /* add BOM size to offsets - see comment at offsetDelta declaration */ michael@0: if(offsets!=NULL && offsetDelta!=0) { michael@0: int32_t *offsetsLimit=pArgs->offsets; michael@0: while(offsetssource=source; michael@0: michael@0: if(source==sourceLimit && pArgs->flush) { michael@0: /* handle truncated input */ michael@0: switch(state) { michael@0: case 0: michael@0: break; /* no input at all, nothing to do */ michael@0: case 8: michael@0: T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode); michael@0: break; michael@0: case 9: michael@0: T_UConverter_toUnicode_UTF32_LE(pArgs, pErrorCode); michael@0: break; michael@0: default: michael@0: /* handle 0source=utf32BOM+(state&4); /* select the correct BOM */ michael@0: pArgs->sourceLimit=pArgs->source+(state&3); /* replay bytes */ michael@0: michael@0: /* no offsets: not enough for output */ michael@0: T_UConverter_toUnicode_UTF32_BE(pArgs, pErrorCode); michael@0: pArgs->source=source; michael@0: pArgs->sourceLimit=sourceLimit; michael@0: state=8; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: cnv->mode=state; michael@0: } michael@0: michael@0: static UChar32 michael@0: _UTF32GetNextUChar(UConverterToUnicodeArgs *pArgs, michael@0: UErrorCode *pErrorCode) { michael@0: switch(pArgs->converter->mode) { michael@0: case 8: michael@0: return T_UConverter_getNextUChar_UTF32_BE(pArgs, pErrorCode); michael@0: case 9: michael@0: return T_UConverter_getNextUChar_UTF32_LE(pArgs, pErrorCode); michael@0: default: michael@0: return UCNV_GET_NEXT_UCHAR_USE_TO_U; michael@0: } michael@0: } michael@0: michael@0: static const UConverterImpl _UTF32Impl = { michael@0: UCNV_UTF32, michael@0: michael@0: NULL, michael@0: NULL, michael@0: michael@0: _UTF32Open, michael@0: NULL, michael@0: _UTF32Reset, michael@0: michael@0: _UTF32ToUnicodeWithOffsets, michael@0: _UTF32ToUnicodeWithOffsets, michael@0: #if U_IS_BIG_ENDIAN michael@0: T_UConverter_fromUnicode_UTF32_BE, michael@0: T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC, michael@0: #else michael@0: T_UConverter_fromUnicode_UTF32_LE, michael@0: T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC, michael@0: #endif michael@0: _UTF32GetNextUChar, michael@0: michael@0: NULL, /* ### TODO implement getStarters for all Unicode encodings?! */ michael@0: NULL, michael@0: NULL, michael@0: NULL, michael@0: ucnv_getNonSurrogateUnicodeSet michael@0: }; michael@0: michael@0: /* The 1236 CCSID refers to any version of Unicode with a BOM sensitive endianess of UTF-32 */ michael@0: static const UConverterStaticData _UTF32StaticData = { michael@0: sizeof(UConverterStaticData), michael@0: "UTF-32", michael@0: 1236, michael@0: UCNV_IBM, UCNV_UTF32, 4, 4, michael@0: #if U_IS_BIG_ENDIAN michael@0: { 0, 0, 0xff, 0xfd }, 4, michael@0: #else michael@0: { 0xfd, 0xff, 0, 0 }, 4, michael@0: #endif michael@0: FALSE, FALSE, michael@0: 0, michael@0: 0, michael@0: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */ michael@0: }; michael@0: michael@0: const UConverterSharedData _UTF32Data = { michael@0: sizeof(UConverterSharedData), ~((uint32_t) 0), michael@0: NULL, NULL, &_UTF32StaticData, FALSE, &_UTF32Impl, michael@0: 0 michael@0: }; michael@0: michael@0: #endif