/* ******************************************************************************** * * * COPYRIGHT: * * (C) Copyright International Business Machines Corporation, 1998 * * Licensed Material - Program-Property of IBM - All Rights Reserved. * * US Government Users Restricted Rights - Use, duplication, or disclosure * * restricted by GSA ADP Schedule Contract with IBM Corp. * * * ******************************************************************************** * * * uconv_bld.c: * * Defines functions that are used in the creation/initialization/deletion * of converters and related structures. * uses uconv_io.h routines to access disk information * is used by ucnv.h to implement public API create/delete/flushCache routines */ #include "ucnv_io.h" #include "uhash.h" #include "ucmp16.h" #include "ucmp8.h" #include "ucnv_bld.h" #include "ucnv_err.h" #include "ucnv_imp.h" #include "ucnv.h" #include "umutex.h" #include "cstring.h" #include "cmemory.h" #include "filestrm.h" /*Array used to generate ALGORITHMIC_CONVERTERS_HASHTABLE *should ALWAYS BE EMPTY STRING TERMINATED. */ static const char *algorithmicConverterNames[] = { "LATIN_1", "UTF8", "UTF16_BigEndian", "UTF16_LittleEndian", "UTF16_PlatformEndian", "UTF16_OppositeEndian", "ISO_2022", "JIS", "EUC", "GB", "" }; /*Takes an alias name gets an actual converter file name *goes to disk and opens it. *allocates the memory and returns a new UConverter object */ static UConverter *createConverterFromFile (const char *converterName, UErrorCode * err); static UConverter *createConverterFromAlgorithmicType (const char *realName, UErrorCode * err); /*Given a file returns a newly allocated CompactByteArray based on the a serialized one */ static CompactByteArray *createCompactByteArrayFromFile (FileStream * infile, UErrorCode * err); /*Given a file returns a newly allocated CompactShortArray based on the a serialized one */ static CompactShortArray *createCompactShortArrayFromFile (FileStream * infile, UErrorCode * err); /*Currently we have function to take us from a codepage name to *a platform type and a codepage number *assuming the following *codepage name = $PLATFORM-#CODEPAGE *e.g. ibm-949 = platform type = UCNV_IBM and codepage # = 949 *the functions below implement that */ static UConverterPlatform getPlatformFromName (char *name); static int32_t getCodepageNumberFromName (char *name); static UConverterType getAlgorithmicTypeFromName (const char *realName); /*these functions initialize the lightweight mutable part of the *object to correct values based on the sharedData defaults. */ static void initializeDataConverter (UConverter * myConverter); static void initializeAlgorithmicConverter (UConverter * myConverter); /** *hash function for UConverterSharedData */ static int32_t uhash_hashSharedData (void *sharedData); /*initializes some global variables */ UHashtable *SHARED_DATA_HASHTABLE = NULL; UHashtable *ALGORITHMIC_CONVERTERS_HASHTABLE = NULL; CompactShortArray* createCompactShortArrayFromFile (FileStream * infile, UErrorCode * err) { int32_t i = 0; int16_t *myShortArray = NULL; uint16_t *myIndexArray = NULL; int32_t myValuesCount = 0; int32_t myIndexCount = 0; int32_t myBlockShift = 0; if (U_FAILURE (*err)) return NULL; /*reads in the lengths of the 2 serialized array */ T_FileStream_read (infile, &myValuesCount, sizeof (int32_t)); T_FileStream_read (infile, &myIndexCount, sizeof (int32_t)); T_FileStream_read (infile, &myBlockShift, sizeof (int32_t)); if (myValuesCount < 0) { *err = U_INVALID_TABLE_FILE; return NULL; } myShortArray = (int16_t *) icu_malloc (myValuesCount * sizeof (int16_t)); if (myShortArray == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*reads in the first array */ T_FileStream_read (infile, myShortArray, myValuesCount * sizeof (int16_t)); if (myIndexCount < 0) { icu_free (myShortArray); *err = U_INVALID_TABLE_FILE; return NULL; } myIndexArray = (uint16_t *) icu_malloc (myIndexCount * sizeof (uint16_t)); if (myIndexArray == NULL) { icu_free (myShortArray); *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*reads in the second array */ T_FileStream_read (infile, myIndexArray, myIndexCount * sizeof (uint16_t)); /*create a compact array from the data just read *that adopts our newly created arrays */ return ucmp16_openAdoptWithBlockShift (myIndexArray, myShortArray, myValuesCount, 0, myBlockShift); } CompactByteArray* createCompactByteArrayFromFile (FileStream * infile, UErrorCode * err) { int32_t i = 0; int8_t *myByteArray = NULL; uint16_t *myIndexArray = NULL; int32_t myValuesCount = 0; int32_t myIndexCount = 0; if (U_FAILURE (*err)) return NULL; /*reads in the lengths of the 2 serialized array */ T_FileStream_read (infile, &myValuesCount, sizeof (int32_t)); T_FileStream_read (infile, &myIndexCount, sizeof (int32_t)); if (myValuesCount < 0) { *err = U_INVALID_TABLE_FILE; return NULL; } myByteArray = (int8_t *) icu_malloc (myValuesCount * sizeof (int8_t)); if (myByteArray == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*reads in the first array */ T_FileStream_read (infile, myByteArray, myValuesCount * sizeof (int8_t)); if (myIndexCount < 0) { icu_free (myByteArray); *err = U_INVALID_TABLE_FILE; return NULL; } myIndexArray = (uint16_t *) icu_malloc (myIndexCount * sizeof (uint16_t)); if (myIndexArray == NULL) { icu_free (myByteArray); *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*reads in the second array */ T_FileStream_read (infile, myIndexArray, myIndexCount * sizeof (uint16_t)); /*create a compact array from the data just read *that adopts our newly created arrays */ return ucmp8_openAdopt (myIndexArray, myByteArray, myValuesCount); } UConverter* createConverterFromFile (const char *fileName, UErrorCode * err) { int32_t i = 0; const int8_t *myByteArray = NULL; const uint16_t *myIndexArray = NULL; int32_t myValuesCount = 0; int32_t myIndexCount = 0; UConverter *myConverter = NULL; int32_t myCheck; FileStream *infile = NULL; int8_t errorLevel = 0; char throwAway[UCNV_COPYRIGHT_STRING_LENGTH]; if (U_FAILURE (*err)) return NULL; infile = openConverterFile (fileName); if (infile == NULL) { *err = U_FILE_ACCESS_ERROR; return NULL; } /*Reads the UCNV_FILE_CHECK_MARKER to assess the integrity of the file */ T_FileStream_read (infile, &myCheck, sizeof (int32_t)); if (myCheck != UCNV_FILE_CHECK_MARKER) { T_FileStream_close (infile); *err = U_INVALID_TABLE_FILE; return NULL; } /*Skips the copyright*/ T_FileStream_read(infile , throwAway, UCNV_COPYRIGHT_STRING_LENGTH); myConverter = (UConverter *) icu_malloc (sizeof (UConverter)); if (myConverter == NULL) { T_FileStream_close (infile); *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } myConverter->sharedData = (UConverterSharedData *) icu_malloc (sizeof (UConverterSharedData)); if (myConverter->sharedData == NULL) { T_FileStream_close (infile); icu_free (myConverter); *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*Reads in the UConverterSharedData object straight from file */ T_FileStream_read (infile, myConverter->sharedData, sizeof (UConverterSharedData)); /*switches over the types of conversions *allocates appropriate amounts of memory for the table *and calls functions to read in the CompactArrays */ switch (myConverter->sharedData->conversionType) { case UCNV_SBCS: { myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterSBCSTable)); if (myConverter->sharedData->table == NULL) { icu_free (myConverter->sharedData); icu_free (myConverter); *err = U_MEMORY_ALLOCATION_ERROR; break; } T_FileStream_read (infile, myConverter->sharedData->table->sbcs.toUnicode, 256 * sizeof (UChar)); myConverter->sharedData->table->sbcs.fromUnicode = createCompactByteArrayFromFile (infile, err); } break; case UCNV_DBCS: case UCNV_EBCDIC_STATEFUL: { myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterDBCSTable)); if (myConverter->sharedData->table == NULL) { icu_free (myConverter->sharedData); icu_free (myConverter); *err = U_MEMORY_ALLOCATION_ERROR; break; } myConverter->sharedData->table->dbcs.toUnicode = createCompactShortArrayFromFile (infile, err); myConverter->sharedData->table->dbcs.fromUnicode = createCompactShortArrayFromFile (infile, err); } break; case UCNV_MBCS: { myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterMBCSTable)); if (myConverter->sharedData->table == NULL) { icu_free (myConverter->sharedData); icu_free (myConverter); *err = U_MEMORY_ALLOCATION_ERROR; break; } T_FileStream_read (infile, myConverter->sharedData->table->mbcs.starters, 256 * sizeof (bool_t)); myConverter->sharedData->table->mbcs.toUnicode = createCompactShortArrayFromFile (infile, err); myConverter->sharedData->table->mbcs.fromUnicode = createCompactShortArrayFromFile (infile, err); } break; default: { /*If it isn't any of the above, the file is invalid */ *err = U_INVALID_TABLE_FILE; icu_free (myConverter->sharedData); icu_free (myConverter); } }; /*there could be a U_FAILURE on the createCompact{Short,Byte}ArrayFromFile *calls, if so we don't want to initialize */ T_FileStream_close (infile); if (U_SUCCESS (*err)) { initializeDataConverter (myConverter); } return myConverter; } void copyPlatformString (char *platformString, UConverterPlatform pltfrm) { switch (pltfrm) { case UCNV_IBM: { icu_strcpy (platformString, "ibm"); break; } default: { icu_strcpy (platformString, ""); break; } }; return; } /*returns a converter type from a string */ UConverterType getAlgorithmicTypeFromName (const char *realName) { if (icu_strcmp (realName, "UTF8") == 0) return UCNV_UTF8; else if (icu_strcmp (realName, "UTF16_BigEndian") == 0) return UCNV_UTF16_BigEndian; else if (icu_strcmp (realName, "UTF16_LittleEndian") == 0) return UCNV_UTF16_LittleEndian; else if (icu_strcmp (realName, "LATIN_1") == 0) return UCNV_LATIN_1; else if (icu_strcmp (realName, "JIS") == 0) return UCNV_JIS; else if (icu_strcmp (realName, "EUC") == 0) return UCNV_EUC; else if (icu_strcmp (realName, "GB") == 0) return UCNV_GB; else if (icu_strcmp (realName, "ISO_2022") == 0) return UCNV_ISO_2022; else if (icu_strcmp (realName, "UTF16_PlatformEndian") == 0) # if U_IS_BIG_ENDIAN return UCNV_UTF16_BigEndian; # else return UCNV_UTF16_LittleEndian; # endif else if (icu_strcmp (realName, "UTF16_OppositeEndian") == 0) # if U_IS_BIG_ENDIAN return UCNV_UTF16_LittleEndian; # else return UCNV_UTF16_BigEndian; # endif else return UCNV_UNSUPPORTED_CONVERTER; } UConverterPlatform getPlatformFromName (char *name) { char myPlatform[10]; char mySeparators[2] = {'-', '\0'}; getToken (myPlatform, name, mySeparators); strtoupper (myPlatform); if (icu_strcmp (myPlatform, "IBM") == 0) return UCNV_IBM; else return UCNV_UNKNOWN; } int32_t getCodepageNumberFromName (char *name) { char myNumber[10]; char mySeparators[2] = {'-', '\0'}; char *line = NULL; line = getToken (myNumber, name, mySeparators); getToken (myNumber, line, mySeparators); return T_CString_stringToInteger (myNumber, 10); } int32_t uhash_hashSharedData (void *sharedData) { return uhash_hashIString(((UConverterSharedData *) sharedData)->name); } /*Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */ void shareConverterData (UConverterSharedData * data) { UErrorCode err = U_ZERO_ERROR; /*Lazy evaluates the Hashtable itself */ if (SHARED_DATA_HASHTABLE == NULL) { UHashtable* myHT = uhash_openSize ((UHashFunction) uhash_hashSharedData, AVAILABLE_CONVERTERS, &err); if (U_FAILURE (err)) return; umtx_lock (NULL); if (SHARED_DATA_HASHTABLE == NULL) SHARED_DATA_HASHTABLE = myHT; else uhash_close(myHT); umtx_unlock (NULL); } umtx_lock (NULL); uhash_put(SHARED_DATA_HASHTABLE, data, &err); umtx_unlock (NULL); return; } UConverterSharedData *getSharedConverterData (const char *name) { /*special case when no Table has yet been created we return NULL */ if (SHARED_DATA_HASHTABLE == NULL) return NULL; else /* return (UConverterSharedData *) uhash_get (SHARED_DATA_HASHTABLE, uhash_hashString (name));*/ { UConverterSharedData *i = (UConverterSharedData*)uhash_get (SHARED_DATA_HASHTABLE, uhash_hashIString (name)); return i; } } /*frees the string of memory blocks associates with a sharedConverter *if and only if the referenceCounter == 0 */ bool_t deleteSharedConverterData (UConverterSharedData * deadSharedData) { if (deadSharedData->referenceCounter > 0) return FALSE; switch (deadSharedData->conversionType) { case UCNV_SBCS: { ucmp8_close (deadSharedData->table->sbcs.fromUnicode); icu_free (deadSharedData->table); icu_free (deadSharedData); }; break; case UCNV_MBCS: { ucmp16_close (deadSharedData->table->mbcs.fromUnicode); ucmp16_close (deadSharedData->table->mbcs.toUnicode); icu_free (deadSharedData->table); icu_free (deadSharedData); }; break; case UCNV_DBCS: case UCNV_EBCDIC_STATEFUL: { ucmp16_close (deadSharedData->table->dbcs.fromUnicode); ucmp16_close (deadSharedData->table->dbcs.toUnicode); icu_free (deadSharedData->table); icu_free (deadSharedData); }; break; default: icu_free (deadSharedData); }; return TRUE; } int32_t uhash_hashIString(const void* name) { char myName[UCNV_MAX_CONVERTER_NAME_LENGTH]; icu_strcpy(myName, (char*)name); strtoupper(myName); return uhash_hashString(myName); } bool_t isDataBasedConverter (const char *name) { int32_t i = 0; bool_t result = FALSE; UErrorCode err = U_ZERO_ERROR; /*Lazy evaluates the hashtable */ if (ALGORITHMIC_CONVERTERS_HASHTABLE == NULL) { UHashtable* myHT; { myHT = uhash_open (uhash_hashIString, &err); if (U_FAILURE (err)) return FALSE; while (algorithmicConverterNames[i][0] != '\0') { /*Stores in the hashtable a pointer to the statically init'ed array containing *the names */ uhash_put (myHT, (void *) algorithmicConverterNames[i], &err); i++; /*Some Compilers (Solaris WSpro and MSVC-Release Mode *don't differentiate between i++ and ++i *so we have to increment in a line by itself */ } } umtx_lock (NULL); if (ALGORITHMIC_CONVERTERS_HASHTABLE == NULL) ALGORITHMIC_CONVERTERS_HASHTABLE = myHT; else uhash_close(myHT); umtx_unlock (NULL); } if (uhash_get (ALGORITHMIC_CONVERTERS_HASHTABLE, uhash_hashIString (name)) == NULL) { result = TRUE; } return result; } /*Logic determines if the converter is Algorithmic AND/OR cached *depending on that: * -we either go to get data from disk and cache it (Data=TRUE, Cached=False) * -Get it from a Hashtable (Data=X, Cached=TRUE) * -Call dataConverter initializer (Data=TRUE, Cached=TRUE) * -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE) */ UConverter * createConverter (const char *converterName, UErrorCode * err) { char realName[UCNV_MAX_CONVERTER_NAME_LENGTH]; UConverter *myUConverter = NULL; UConverterSharedData *mySharedConverterData = NULL; if (U_FAILURE (*err)) return NULL; if (resolveName (realName, converterName) == FALSE) { *err = U_INVALID_TABLE_FILE; return NULL; } if (isDataBasedConverter (realName)) { mySharedConverterData = getSharedConverterData (realName); if (mySharedConverterData == NULL) { /*Not cached, we need to stream it in from file */ myUConverter = createConverterFromFile (converterName, err); if (U_FAILURE (*err) || (myUConverter == NULL)) { return myUConverter; } else { /*shared it with other library clients */ shareConverterData (myUConverter->sharedData); return myUConverter; } } else { /*Is already cached, point to an existing one */ myUConverter = (UConverter *) icu_malloc (sizeof (UConverter)); if (myUConverter == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*update the reference counter: one more client */ umtx_lock (NULL); mySharedConverterData->referenceCounter++; umtx_unlock (NULL); myUConverter->sharedData = mySharedConverterData; initializeDataConverter (myUConverter); return myUConverter; } } else { /*with have an algorithmic converter */ mySharedConverterData = getSharedConverterData (realName); /*Non cached */ if (mySharedConverterData == NULL) { myUConverter = createConverterFromAlgorithmicType (realName, err); if (U_FAILURE (*err) || (myUConverter == NULL)) { icu_free (myUConverter); return NULL; } else { /* put the shared object in shared table */ shareConverterData (myUConverter->sharedData); return myUConverter; } } else { myUConverter = (UConverter *) icu_malloc (sizeof (UConverter)); if (myUConverter == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } /*Increase the reference counter */ umtx_lock (NULL); mySharedConverterData->referenceCounter++; umtx_unlock (NULL); /*initializes the converter */ myUConverter->sharedData = mySharedConverterData; initializeAlgorithmicConverter (myUConverter); return myUConverter; } return myUConverter; } return NULL; } /*Initializes the mutable lightweight portion of the object *By copying data from UConverter->sharedData->defaultConverter */ void initializeDataConverter (UConverter * myUConverter) { myUConverter->mode = UCNV_SI; myUConverter->UCharErrorBufferLength = 0; myUConverter->charErrorBufferLength = 0; myUConverter->subCharLen = myUConverter->sharedData->defaultConverterValues.subCharLen; icu_memcpy (myUConverter->subChar, myUConverter->sharedData->defaultConverterValues.subChar, myUConverter->subCharLen); myUConverter->toUnicodeStatus = 0x00; myUConverter->fromUnicodeStatus = 0x00; myUConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0x00; myUConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE; myUConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE; myUConverter->extraInfo = NULL; return; } /* This function initializes algorithmic converters * based on there type */ void initializeAlgorithmicConverter (UConverter * myConverter) { char UTF8_subChar[] = {(char) 0xFF, (char) 0xFF, (char) 0xFF}; char UTF16BE_subChar[] = {(char) 0xFF, (char) 0xFD}; char UTF16LE_subChar[] = {(char) 0xFD, (char) 0xFF}; char EUC_subChar[] = {(char) 0xAF, (char) 0xFE}; char GB_subChar[] = {(char) 0xFF, (char) 0xFF}; char JIS_subChar[] = {(char) 0xFF, (char) 0xFF}; char LATIN1_subChar = 0x1A; myConverter->mode = UCNV_SI; myConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE; myConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE; myConverter->charErrorBufferLength = 0; myConverter->UCharErrorBufferLength = 0; myConverter->extraInfo = NULL; switch (myConverter->sharedData->conversionType) { case UCNV_UTF8: { myConverter->sharedData->minBytesPerChar = 1; myConverter->sharedData->maxBytesPerChar = 4; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 3; myConverter->subCharLen = 3; myConverter->toUnicodeStatus = 0; myConverter->fromUnicodeStatus = 0; /* srl */ myConverter->sharedData->platform = UCNV_IBM; myConverter->sharedData->codepage = 1208; icu_strcpy(myConverter->sharedData->name, "UTF8"); icu_memcpy (myConverter->subChar, UTF8_subChar, 3); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF8_subChar, 3); break; } case UCNV_LATIN_1: { myConverter->sharedData->minBytesPerChar = 1; myConverter->sharedData->maxBytesPerChar = 1; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 1; myConverter->subCharLen = 1; myConverter->toUnicodeStatus = 0; myConverter->sharedData->platform = UCNV_IBM; myConverter->sharedData->codepage = 819; icu_strcpy(myConverter->sharedData->name, "LATIN_1"); *(myConverter->subChar) = LATIN1_subChar; *(myConverter->sharedData->defaultConverterValues.subChar) = LATIN1_subChar; break; } case UCNV_UTF16_BigEndian: { myConverter->sharedData->minBytesPerChar = 2; myConverter->sharedData->maxBytesPerChar = 2; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 2; myConverter->subCharLen = 2; myConverter->toUnicodeStatus = 0; myConverter->fromUnicodeStatus = 0; icu_strcpy(myConverter->sharedData->name, "UTF_16BE"); myConverter->sharedData->platform = UCNV_IBM; myConverter->sharedData->codepage = 1200; icu_memcpy (myConverter->subChar, UTF16BE_subChar, 2); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF16BE_subChar, 2); break; } case UCNV_UTF16_LittleEndian: { myConverter->sharedData->minBytesPerChar = 2; myConverter->sharedData->maxBytesPerChar = 2; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 2; myConverter->subCharLen = 2; myConverter->toUnicodeStatus = 0; myConverter->fromUnicodeStatus = 0; myConverter->sharedData->platform = UCNV_IBM; myConverter->sharedData->codepage = 1200; icu_strcpy(myConverter->sharedData->name, "UTF_16LE"); icu_memcpy (myConverter->subChar, UTF16LE_subChar, 2); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF16LE_subChar, 2); break; } case UCNV_EUC: { myConverter->sharedData->minBytesPerChar = 1; myConverter->sharedData->maxBytesPerChar = 2; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 2; myConverter->subCharLen = 2; myConverter->toUnicodeStatus = 0; icu_memcpy (myConverter->subChar, EUC_subChar, 2); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, EUC_subChar, 2); break; } case UCNV_ISO_2022: { myConverter->charErrorBuffer[0] = 0x1b; myConverter->charErrorBuffer[1] = 0x25; myConverter->charErrorBuffer[2] = 0x42; myConverter->charErrorBufferLength = 3; myConverter->sharedData->minBytesPerChar = 1; myConverter->sharedData->maxBytesPerChar = 3; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 1; myConverter->subCharLen = 1; myConverter->toUnicodeStatus = 0; myConverter->fromUnicodeStatus = 0; /* srl */ myConverter->sharedData->codepage = 2022; icu_strcpy(myConverter->sharedData->name, "ISO_2022"); *(myConverter->subChar) = LATIN1_subChar; *(myConverter->sharedData->defaultConverterValues.subChar) = LATIN1_subChar; myConverter->extraInfo = icu_malloc (sizeof (UConverterDataISO2022)); ((UConverterDataISO2022 *) myConverter->extraInfo)->currentConverter = NULL; ((UConverterDataISO2022 *) myConverter->extraInfo)->escSeq2022Length = 0; break; } case UCNV_GB: { myConverter->sharedData->minBytesPerChar = 2; myConverter->sharedData->maxBytesPerChar = 2; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 2; myConverter->subCharLen = 2; myConverter->toUnicodeStatus = 0; icu_memcpy (myConverter->subChar, GB_subChar, 2); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, GB_subChar, 2); break; } case UCNV_JIS: { myConverter->sharedData->minBytesPerChar = 2; myConverter->sharedData->maxBytesPerChar = 2; myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0; myConverter->sharedData->defaultConverterValues.subCharLen = 2; myConverter->subCharLen = 2; myConverter->toUnicodeStatus = 0; icu_memcpy (myConverter->subChar, JIS_subChar, 2); icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, JIS_subChar, 2); break; } default: break; }; myConverter->toUnicodeStatus = myConverter->sharedData->defaultConverterValues.toUnicodeStatus; } /*This function creates an algorithmic converter *Note That even algorithmic converters are shared * (The UConverterSharedData->table == NULL since * there are no tables) *for uniformity of design and control flow */ UConverter * createConverterFromAlgorithmicType (const char *actualName, UErrorCode * err) { int32_t i = 0; UConverter *myConverter = NULL; UConverterSharedData *mySharedData = NULL; UConverterType myType = getAlgorithmicTypeFromName (actualName); if (U_FAILURE (*err)) return NULL; myConverter = (UConverter *) icu_malloc (sizeof (UConverter)); if (myConverter == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; return NULL; } myConverter->sharedData = NULL; mySharedData = (UConverterSharedData *) icu_malloc (sizeof (UConverterSharedData)); if (mySharedData == NULL) { *err = U_MEMORY_ALLOCATION_ERROR; icu_free (myConverter); return NULL; } mySharedData->table = NULL; icu_strcpy (mySharedData->name, actualName); /*Initializes the referenceCounter to 1 */ mySharedData->referenceCounter = 1; mySharedData->platform = UCNV_UNKNOWN; mySharedData->codepage = 0; mySharedData->conversionType = myType; myConverter->sharedData = mySharedData; initializeAlgorithmicConverter (myConverter); return myConverter; }