home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / ucnv_bld.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-22  |  26.0 KB  |  896 lines

  1. /*
  2.  ********************************************************************************
  3.  *                                                                              *
  4.  * COPYRIGHT:                                                                   *
  5.  *   (C) Copyright International Business Machines Corporation, 1998            *
  6.  *   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
  7.  *   US Government Users Restricted Rights - Use, duplication, or disclosure    *
  8.  *   restricted by GSA ADP Schedule Contract with IBM Corp.                     *
  9.  *                                                                              *
  10.  ********************************************************************************
  11.  *
  12.  *
  13.  *  uconv_bld.c:
  14.  *
  15.  *  Defines functions that are used in the creation/initialization/deletion
  16.  *  of converters and related structures.
  17.  *  uses uconv_io.h routines to access disk information
  18.  *  is used by ucnv.h to implement public API create/delete/flushCache routines
  19.  */
  20.  
  21.  
  22. #include "ucnv_io.h"
  23. #include "uhash.h"
  24. #include "ucmp16.h"
  25. #include "ucmp8.h"
  26. #include "ucnv_bld.h"
  27. #include "ucnv_err.h"
  28. #include "ucnv_imp.h"
  29. #include "ucnv.h"
  30. #include "umutex.h"
  31. #include "cstring.h"
  32. #include "cmemory.h"
  33. #include "filestrm.h"
  34.  
  35. /*Array used to generate ALGORITHMIC_CONVERTERS_HASHTABLE
  36.  *should ALWAYS BE EMPTY STRING TERMINATED.
  37.  */
  38. static const char *algorithmicConverterNames[] = {
  39.   "LATIN_1",
  40.   "UTF8",
  41.   "UTF16_BigEndian",
  42.   "UTF16_LittleEndian",
  43.   "ISO_2022",
  44.   "JIS",
  45.   "EUC",
  46.   "GB",
  47.   "ISO_2022",
  48.   ""
  49. };
  50.  
  51. /*Takes an alias name gets an actual converter file name
  52.  *goes to disk and opens it.
  53.  *allocates the memory and returns a new UConverter object
  54.  */
  55. static UConverter *createConverterFromFile (const char *converterName, UErrorCode * err);
  56. static UConverter *createConverterFromAlgorithmicType (const char *realName, UErrorCode * err);
  57.  
  58. /*Given a file returns a newly allocated CompactByteArray based on the a serialized one */
  59. static CompactByteArray *createCompactByteArrayFromFile (FileStream * infile, UErrorCode * err);
  60.  
  61. /*Given a file returns a newly allocated CompactShortArray based on the a serialized one */
  62. static CompactShortArray *createCompactShortArrayFromFile (FileStream * infile, UErrorCode * err);
  63.  
  64. /*Currently we have function to take us from a codepage name to
  65.  *a platform type and a codepage number
  66.  *assuming the following
  67.  *codepage name = $PLATFORM-#CODEPAGE
  68.  *e.g. ibm-949 = platform type = UCNV_IBM and codepage # = 949
  69.  *the functions below implement that
  70.  */
  71. static UConverterPlatform getPlatformFromName (char *name);
  72. static int32_t getCodepageNumberFromName (char *name);
  73.  
  74. static UConverterType getAlgorithmicTypeFromName (const char *realName);
  75.  
  76.  
  77. /*these functions initialize the lightweight mutable part of the
  78.  *object to correct values based on the sharedData defaults.
  79.  */
  80. static void initializeDataConverter (UConverter * myConverter);
  81. static void initializeAlgorithmicConverter (UConverter * myConverter);
  82. /**
  83.  *hash function for UConverterSharedData
  84.  */
  85.  
  86. static int32_t uhash_hashSharedData (void *sharedData);
  87.  
  88.  
  89. /*initializes some global variables */
  90. UHashtable *SHARED_DATA_HASHTABLE = NULL;
  91. UHashtable *ALGORITHMIC_CONVERTERS_HASHTABLE = NULL;
  92.  
  93.  
  94.  
  95. CompactShortArray*  createCompactShortArrayFromFile (FileStream * infile, UErrorCode * err)
  96. {
  97.   int32_t i = 0;
  98.   int16_t *myShortArray = NULL;
  99.   uint16_t *myIndexArray = NULL;
  100.   int32_t myValuesCount = 0;
  101.   int32_t myIndexCount = 0;
  102.   int32_t myBlockShift = 0;
  103.  
  104.   if (U_FAILURE (*err))
  105.     return NULL;
  106.  
  107.   /*reads in the lengths of the 2 serialized array */
  108.   T_FileStream_read (infile, &myValuesCount, sizeof (int32_t));
  109.   T_FileStream_read (infile, &myIndexCount, sizeof (int32_t));
  110.   T_FileStream_read (infile, &myBlockShift, sizeof (int32_t));
  111.  
  112.   if (myValuesCount < 0)
  113.     {
  114.       *err = U_INVALID_TABLE_FILE;
  115.       return NULL;
  116.     }
  117.   myShortArray = (int16_t *) icu_malloc (myValuesCount * sizeof (int16_t));
  118.   if (myShortArray == NULL)
  119.     {
  120.       *err = U_MEMORY_ALLOCATION_ERROR;
  121.       return NULL;
  122.     }
  123.   /*reads in the first array */
  124.   T_FileStream_read (infile, myShortArray, myValuesCount * sizeof (int16_t));
  125.  
  126.   if (myIndexCount < 0)
  127.     {
  128.       icu_free (myShortArray);
  129.       *err = U_INVALID_TABLE_FILE;
  130.       return NULL;
  131.     }
  132.  
  133.   myIndexArray = (uint16_t *) icu_malloc (myIndexCount * sizeof (uint16_t));
  134.   if (myIndexArray == NULL)
  135.     {
  136.       icu_free (myShortArray);
  137.       *err = U_MEMORY_ALLOCATION_ERROR;
  138.       return NULL;
  139.     }
  140.  
  141.   /*reads in the second array */
  142.   T_FileStream_read (infile, myIndexArray, myIndexCount * sizeof (uint16_t));
  143.  
  144.   /*create a compact array from the data just read
  145.    *that adopts our newly created arrays
  146.    */
  147.   return ucmp16_openAdoptWithBlockShift (myIndexArray, myShortArray, myValuesCount, 0, myBlockShift);
  148. }
  149.  
  150. CompactByteArray*  createCompactByteArrayFromFile (FileStream * infile,
  151.                            UErrorCode * err)
  152. {
  153.   int32_t i = 0;
  154.   int8_t *myByteArray = NULL;
  155.   uint16_t *myIndexArray = NULL;
  156.   int32_t myValuesCount = 0;
  157.   int32_t myIndexCount = 0;
  158.  
  159.   if (U_FAILURE (*err))
  160.     return NULL;
  161.  
  162.   /*reads in the lengths of the 2 serialized array */
  163.   T_FileStream_read (infile, &myValuesCount, sizeof (int32_t));
  164.   T_FileStream_read (infile, &myIndexCount, sizeof (int32_t));
  165.  
  166.   if (myValuesCount < 0)
  167.     {
  168.       *err = U_INVALID_TABLE_FILE;
  169.       return NULL;
  170.     }
  171.   myByteArray = (int8_t *) icu_malloc (myValuesCount * sizeof (int8_t));
  172.   if (myByteArray == NULL)
  173.     {
  174.       *err = U_MEMORY_ALLOCATION_ERROR;
  175.       return NULL;
  176.     }
  177.   /*reads in the first array */
  178.   T_FileStream_read (infile, myByteArray, myValuesCount * sizeof (int8_t));
  179.  
  180.   if (myIndexCount < 0)
  181.     {
  182.       icu_free (myByteArray);
  183.       *err = U_INVALID_TABLE_FILE;
  184.       return NULL;
  185.     }
  186.   myIndexArray = (uint16_t *) icu_malloc (myIndexCount * sizeof (uint16_t));
  187.   if (myIndexArray == NULL)
  188.     {
  189.       icu_free (myByteArray);
  190.       *err = U_MEMORY_ALLOCATION_ERROR;
  191.       return NULL;
  192.     }
  193.   /*reads in the second array */
  194.   T_FileStream_read (infile, myIndexArray, myIndexCount * sizeof (uint16_t));
  195.  
  196.   /*create a compact array from the data just read
  197.    *that adopts our newly created arrays
  198.    */
  199.   return ucmp8_openAdopt (myIndexArray, myByteArray, myValuesCount);
  200. }
  201.  
  202. UConverter*  createConverterFromFile (const char *fileName, UErrorCode * err)
  203. {
  204.   int32_t i = 0;
  205.   const int8_t *myByteArray = NULL;
  206.   const uint16_t *myIndexArray = NULL;
  207.   int32_t myValuesCount = 0;
  208.   int32_t myIndexCount = 0;
  209.   UConverter *myConverter = NULL;
  210.   int32_t myCheck;
  211.   FileStream *infile = NULL;
  212.   int8_t errorLevel = 0;
  213.   char throwAway[UCNV_COPYRIGHT_STRING_LENGTH];
  214.   if (U_FAILURE (*err))
  215.     return NULL;
  216.  
  217.   infile = openConverterFile (fileName);
  218.   if (infile == NULL)
  219.     {
  220.       *err = U_FILE_ACCESS_ERROR;
  221.       return NULL;
  222.     }
  223.  
  224.   /*Reads the UCNV_FILE_CHECK_MARKER to assess the integrity of the file */
  225.   T_FileStream_read (infile, &myCheck, sizeof (int32_t));
  226.   if (myCheck != UCNV_FILE_CHECK_MARKER)
  227.     {
  228.       T_FileStream_close (infile);
  229.       *err = U_INVALID_TABLE_FILE;
  230.       return NULL;
  231.     }
  232.  
  233.   /*Skips the copyright*/
  234.   T_FileStream_read(infile , throwAway, UCNV_COPYRIGHT_STRING_LENGTH);
  235.   
  236.   myConverter = (UConverter *) icu_malloc (sizeof (UConverter));
  237.   if (myConverter == NULL)
  238.     {
  239.       T_FileStream_close (infile);
  240.       *err = U_MEMORY_ALLOCATION_ERROR;
  241.       return NULL;
  242.     }
  243.  
  244.   myConverter->sharedData =
  245.     (UConverterSharedData *) icu_malloc (sizeof (UConverterSharedData));
  246.   if (myConverter->sharedData == NULL)
  247.     {
  248.       T_FileStream_close (infile);
  249.       icu_free (myConverter);
  250.       *err = U_MEMORY_ALLOCATION_ERROR;
  251.       return NULL;
  252.     }
  253.  
  254.   /*Reads in the UConverterSharedData object straight from file */
  255.   T_FileStream_read (infile, myConverter->sharedData, sizeof (UConverterSharedData));
  256.  
  257.   /*switches over the types of conversions
  258.    *allocates appropriate amounts of memory for the table
  259.    *and calls functions to read in the CompactArrays
  260.    */
  261.   switch (myConverter->sharedData->conversionType)
  262.     {
  263.     case UCNV_SBCS:
  264.       {
  265.     myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterSBCSTable));
  266.     if (myConverter->sharedData->table == NULL)
  267.       {
  268.         icu_free (myConverter->sharedData);
  269.         icu_free (myConverter);
  270.         *err = U_MEMORY_ALLOCATION_ERROR;
  271.         break;
  272.       }
  273.     T_FileStream_read (infile, myConverter->sharedData->table->sbcs.toUnicode, 256 * sizeof (UChar));
  274.     myConverter->sharedData->table->sbcs.fromUnicode = createCompactByteArrayFromFile (infile, err);
  275.       }
  276.       break;
  277.  
  278.     case UCNV_DBCS:
  279.     case UCNV_EBCDIC_STATEFUL:
  280.       {
  281.     myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterDBCSTable));
  282.     if (myConverter->sharedData->table == NULL)
  283.       {
  284.         icu_free (myConverter->sharedData);
  285.         icu_free (myConverter);
  286.         *err = U_MEMORY_ALLOCATION_ERROR;
  287.         break;
  288.       }
  289.     myConverter->sharedData->table->dbcs.toUnicode = createCompactShortArrayFromFile (infile, err);
  290.     myConverter->sharedData->table->dbcs.fromUnicode = createCompactShortArrayFromFile (infile, err);
  291.       }
  292.       break;
  293.  
  294.     case UCNV_MBCS:
  295.       {
  296.     myConverter->sharedData->table = (UConverterTable *) icu_malloc (sizeof (UConverterMBCSTable));
  297.     if (myConverter->sharedData->table == NULL)
  298.       {
  299.         icu_free (myConverter->sharedData);
  300.         icu_free (myConverter);
  301.         *err = U_MEMORY_ALLOCATION_ERROR;
  302.         break;
  303.       }
  304.     T_FileStream_read (infile, myConverter->sharedData->table->mbcs.starters, 256 * sizeof (bool_t));
  305.     myConverter->sharedData->table->mbcs.toUnicode = createCompactShortArrayFromFile (infile, err);
  306.     myConverter->sharedData->table->mbcs.fromUnicode = createCompactShortArrayFromFile (infile, err);
  307.       }
  308.       break;
  309.  
  310.     default:
  311.       {
  312.     /*If it isn't any of the above, the file is invalid */
  313.     *err = U_INVALID_TABLE_FILE;
  314.     icu_free (myConverter->sharedData);
  315.     icu_free (myConverter);
  316.       }
  317.     };
  318.  
  319.   /*there could be a U_FAILURE on the createCompact{Short,Byte}ArrayFromFile
  320.    *calls, if so we don't want to initialize
  321.    */
  322.  
  323.   T_FileStream_close (infile);
  324.   if (U_SUCCESS (*err))
  325.     {
  326.       initializeDataConverter (myConverter);
  327.     }
  328.  
  329.   return myConverter;
  330.  
  331.  
  332. }
  333.  
  334.  
  335. void 
  336.   copyPlatformString (char *platformString, UConverterPlatform pltfrm)
  337. {
  338.   switch (pltfrm)
  339.     {
  340.     case UCNV_IBM:
  341.       {
  342.     icu_strcpy (platformString, "ibm");
  343.     break;
  344.       }
  345.     default:
  346.       {
  347.     icu_strcpy (platformString, "");
  348.     break;
  349.       }
  350.     };
  351.  
  352.   return;
  353. }
  354.  
  355. /*returns a converter type from a string
  356.  */
  357. UConverterType 
  358.   getAlgorithmicTypeFromName (const char *realName)
  359. {
  360.   if (icu_strcmp (realName, "UTF8") == 0)
  361.     return UCNV_UTF8;
  362.   else if (icu_strcmp (realName, "UTF16_BigEndian") == 0)
  363.     return UCNV_UTF16_BigEndian;
  364.   else if (icu_strcmp (realName, "UTF16_LittleEndian") == 0)
  365.     return UCNV_UTF16_LittleEndian;
  366.   else if (icu_strcmp (realName, "LATIN_1") == 0)
  367.     return UCNV_LATIN_1;
  368.   else if (icu_strcmp (realName, "JIS") == 0)
  369.     return UCNV_JIS;
  370.   else if (icu_strcmp (realName, "EUC") == 0)
  371.     return UCNV_EUC;
  372.   else if (icu_strcmp (realName, "GB") == 0)
  373.     return UCNV_GB;
  374.   else if (icu_strcmp (realName, "ISO_2022") == 0)
  375.     return UCNV_ISO_2022;
  376.   else
  377.     return UCNV_UNSUPPORTED_CONVERTER;
  378. }
  379.  
  380.  
  381. UConverterPlatform 
  382.   getPlatformFromName (char *name)
  383. {
  384.   char myPlatform[10];
  385.   char mySeparators[2] = {'-', '\0'};
  386.  
  387.   getToken (myPlatform, name, mySeparators);
  388.   strtoupper (myPlatform);
  389.  
  390.   if (icu_strcmp (myPlatform, "IBM") == 0)
  391.     return UCNV_IBM;
  392.   else
  393.     return UCNV_UNKNOWN;
  394. }
  395.  
  396. int32_t 
  397.   getCodepageNumberFromName (char *name)
  398. {
  399.   char myNumber[10];
  400.   char mySeparators[2] = {'-', '\0'};
  401.   char *line = NULL;
  402.  
  403.   line = getToken (myNumber, name, mySeparators);
  404.   getToken (myNumber, line, mySeparators);
  405.  
  406.   return T_CString_stringToInteger (myNumber, 10);
  407. }
  408.  
  409. int32_t uhash_hashSharedData (void *sharedData)
  410. {
  411.   return uhash_hashIString(((UConverterSharedData *) sharedData)->name);
  412. }
  413.  
  414. /*Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */
  415. void   shareConverterData (UConverterSharedData * data)
  416. {
  417.   UErrorCode err = U_ZERO_ERROR;
  418.   /*Lazy evaluates the Hashtable itself */
  419.  
  420.   if (SHARED_DATA_HASHTABLE == NULL)
  421.     {
  422.       UHashtable* myHT = uhash_openSize ((UHashFunction) uhash_hashSharedData, 
  423.                      AVAILABLE_CONVERTERS,
  424.                      &err);
  425.       if (U_FAILURE (err)) return;
  426.       umtx_lock (NULL);
  427.       if (SHARED_DATA_HASHTABLE == NULL) SHARED_DATA_HASHTABLE = myHT;
  428.       else uhash_close(myHT);
  429.       umtx_unlock (NULL);
  430.       
  431.     }
  432.   umtx_lock (NULL);
  433.   uhash_put(SHARED_DATA_HASHTABLE,
  434.         data,
  435.         &err);
  436.   umtx_unlock (NULL);
  437.  
  438.   return;
  439. }
  440.  
  441. UConverterSharedData *getSharedConverterData (const char *name)
  442. {
  443.   /*special case when no Table has yet been created we return NULL */
  444.   if (SHARED_DATA_HASHTABLE == NULL)    return NULL;
  445.   else
  446.     /*    return (UConverterSharedData *) uhash_get (SHARED_DATA_HASHTABLE, uhash_hashString (name));*/
  447.     {
  448.       UConverterSharedData *i = (UConverterSharedData*)uhash_get (SHARED_DATA_HASHTABLE, uhash_hashIString (name));
  449.       return i;
  450.     }
  451. }
  452.  
  453. /*frees the string of memory blocks associates with a sharedConverter
  454.  *if and only if the referenceCounter == 0
  455.  */
  456. bool_t   deleteSharedConverterData (UConverterSharedData * deadSharedData)
  457. {
  458.   if (deadSharedData->referenceCounter > 0)
  459.     return FALSE;
  460.  
  461.   switch (deadSharedData->conversionType)
  462.     {
  463.  
  464.     case UCNV_SBCS:
  465.       {
  466.     ucmp8_close (deadSharedData->table->sbcs.fromUnicode);
  467.     icu_free (deadSharedData->table);
  468.     icu_free (deadSharedData);
  469.       };
  470.       break;
  471.  
  472.     case UCNV_MBCS:
  473.       {
  474.     ucmp16_close (deadSharedData->table->mbcs.fromUnicode);
  475.     ucmp16_close (deadSharedData->table->mbcs.toUnicode);
  476.     icu_free (deadSharedData->table);
  477.     icu_free (deadSharedData);
  478.       };
  479.       break;
  480.  
  481.     case UCNV_DBCS:
  482.     case UCNV_EBCDIC_STATEFUL:
  483.       {
  484.     ucmp16_close (deadSharedData->table->dbcs.fromUnicode);
  485.     ucmp16_close (deadSharedData->table->dbcs.toUnicode);
  486.     icu_free (deadSharedData->table);
  487.     icu_free (deadSharedData);
  488.       };
  489.       break;
  490.  
  491.     default:
  492.       icu_free (deadSharedData);
  493.     };
  494.  
  495.   return TRUE;
  496. }
  497.  
  498. int32_t uhash_hashIString(const void* name)
  499. {
  500.   char myName[UCNV_MAX_CONVERTER_NAME_LENGTH];
  501.   icu_strcpy(myName, (char*)name);
  502.   strtoupper(myName);
  503.  
  504.   return uhash_hashString(myName);
  505. }
  506. bool_t   isDataBasedConverter (const char *name)
  507. {
  508.   int32_t i = 0;
  509.   bool_t result = FALSE;
  510.   UErrorCode err = U_ZERO_ERROR;
  511.  
  512.   /*Lazy evaluates the hashtable */
  513.   if (ALGORITHMIC_CONVERTERS_HASHTABLE == NULL)
  514.     {
  515.       UHashtable* myHT;
  516.       
  517.       {
  518.       myHT = uhash_open (uhash_hashIString, &err);
  519.       
  520.       if (U_FAILURE (err)) return FALSE;
  521.       while (algorithmicConverterNames[i][0] != '\0')
  522.         {
  523.           /*Stores in the hashtable a pointer to the statically init'ed array containing
  524.            *the names
  525.            */
  526.           
  527.           uhash_put (myHT,
  528.              (void *) algorithmicConverterNames[i],
  529.              &err);
  530.           i++;            /*Some Compilers (Solaris WSpro and MSVC-Release Mode
  531.                      *don't differentiate between i++ and ++i
  532.                      *so we have to increment in a line by itself
  533.                      */
  534.         }
  535.       }
  536.       
  537.       umtx_lock (NULL);
  538.       if (ALGORITHMIC_CONVERTERS_HASHTABLE == NULL) ALGORITHMIC_CONVERTERS_HASHTABLE = myHT;
  539.       else uhash_close(myHT);      
  540.       umtx_unlock (NULL);
  541.       
  542.       
  543.     }
  544.     
  545.   
  546.   if (uhash_get (ALGORITHMIC_CONVERTERS_HASHTABLE,
  547.          uhash_hashIString (name)) == NULL)
  548.     {
  549.       result = TRUE;
  550.     }
  551.   
  552.  
  553.   return result;
  554. }
  555. /*Logic determines if the converter is Algorithmic AND/OR cached
  556.  *depending on that:
  557.  * -we either go to get data from disk and cache it (Data=TRUE, Cached=False)
  558.  * -Get it from a Hashtable (Data=X, Cached=TRUE)
  559.  * -Call dataConverter initializer (Data=TRUE, Cached=TRUE)
  560.  * -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
  561.  */
  562. UConverter *
  563.   createConverter (const char *converterName, UErrorCode * err)
  564. {
  565.   char realName[UCNV_MAX_CONVERTER_NAME_LENGTH];
  566.   UConverter *myUConverter = NULL;
  567.   UConverterSharedData *mySharedConverterData = NULL;
  568.  
  569.   if (U_FAILURE (*err))
  570.     return NULL;
  571.  
  572.   if (resolveName (realName, converterName) == FALSE)
  573.     {
  574.       *err = U_INVALID_TABLE_FILE;
  575.       return NULL;
  576.     }
  577.  
  578.  
  579.   if (isDataBasedConverter (realName))
  580.     {
  581.       mySharedConverterData = getSharedConverterData (realName);
  582.  
  583.       if (mySharedConverterData == NULL)
  584.     {
  585.       /*Not cached, we need to stream it in from file */
  586.       myUConverter = createConverterFromFile (converterName, err);
  587.  
  588.       if (U_FAILURE (*err) || (myUConverter == NULL))
  589.         {
  590.           return myUConverter;
  591.         }
  592.       else
  593.         {
  594.           /*shared it with other library clients */
  595.  
  596.  
  597.           shareConverterData (myUConverter->sharedData);
  598.           return myUConverter;
  599.         }
  600.     }
  601.       else
  602.     {
  603.       /*Is already cached, point to an existing one */
  604.       myUConverter = (UConverter *) icu_malloc (sizeof (UConverter));
  605.       if (myUConverter == NULL)
  606.         {
  607.           *err = U_MEMORY_ALLOCATION_ERROR;
  608.           return NULL;
  609.         }
  610.  
  611.       /*update the reference counter: one more client */
  612.       umtx_lock (NULL);
  613.       mySharedConverterData->referenceCounter++;
  614.       umtx_unlock (NULL);
  615.  
  616.       myUConverter->sharedData = mySharedConverterData;
  617.       initializeDataConverter (myUConverter);
  618.  
  619.       return myUConverter;
  620.     }
  621.     }
  622.   else
  623.     {
  624.       /*with have an algorithmic converter */
  625.       mySharedConverterData = getSharedConverterData (realName);
  626.  
  627.       /*Non cached */
  628.       if (mySharedConverterData == NULL)
  629.     {
  630.       myUConverter = createConverterFromAlgorithmicType (realName, err);
  631.       if (U_FAILURE (*err) || (myUConverter == NULL))
  632.         {
  633.           icu_free (myUConverter);
  634.           return NULL;
  635.         }
  636.       else
  637.         {
  638.           /* put the shared object in shared table */
  639.           shareConverterData (myUConverter->sharedData);
  640.           return myUConverter;
  641.         }
  642.     }
  643.       else
  644.     {
  645.       myUConverter = (UConverter *) icu_malloc (sizeof (UConverter));
  646.       if (myUConverter == NULL)
  647.         {
  648.           *err = U_MEMORY_ALLOCATION_ERROR;
  649.           return NULL;
  650.         }
  651.  
  652.       /*Increase the reference counter */
  653.       umtx_lock (NULL);
  654.       mySharedConverterData->referenceCounter++;
  655.       umtx_unlock (NULL);
  656.  
  657.       /*initializes the converter */
  658.       myUConverter->sharedData = mySharedConverterData;
  659.       initializeAlgorithmicConverter (myUConverter);
  660.       return myUConverter;
  661.     }
  662.  
  663.       return myUConverter;
  664.     }
  665.  
  666.   return NULL;
  667. }
  668.  
  669. /*Initializes the mutable lightweight portion of the object
  670.  *By copying data from UConverter->sharedData->defaultConverter
  671.  */
  672. void   initializeDataConverter (UConverter * myUConverter)
  673. {
  674.  
  675.   myUConverter->mode = UCNV_SI;
  676.   myUConverter->UCharErrorBufferLength = 0;
  677.   myUConverter->charErrorBufferLength = 0;
  678.   myUConverter->subCharLen = myUConverter->sharedData->defaultConverterValues.subCharLen;
  679.   icu_memcpy (myUConverter->subChar,
  680.           myUConverter->sharedData->defaultConverterValues.subChar,
  681.           myUConverter->subCharLen);
  682.   myUConverter->toUnicodeStatus = 0x00;
  683.   myUConverter->fromUnicodeStatus = 0x00;
  684.   myUConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0x00;
  685.  
  686.   myUConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE;
  687.   myUConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE;
  688.   myUConverter->extraInfo = NULL;
  689.  
  690.   return;
  691. }
  692.  
  693. /* This function initializes algorithmic converters
  694.  * based on there type
  695.  */
  696. void 
  697.   initializeAlgorithmicConverter (UConverter * myConverter)
  698. {
  699.   char UTF8_subChar[] = {(char) 0xFF, (char) 0xFF, (char) 0xFF};
  700.   char UTF16BE_subChar[] = {(char) 0xFF, (char) 0xFD};
  701.   char UTF16LE_subChar[] = {(char) 0xFD, (char) 0xFF};
  702.   char EUC_subChar[] = {(char) 0xAF, (char) 0xFE};
  703.   char GB_subChar[] = {(char) 0xFF, (char) 0xFF};
  704.   char JIS_subChar[] = {(char) 0xFF, (char) 0xFF};
  705.   char LATIN1_subChar = 0x1A;
  706.  
  707.  
  708.  
  709.   myConverter->mode = UCNV_SI;
  710.   myConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE;
  711.   myConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE;
  712.   myConverter->charErrorBufferLength = 0;
  713.   myConverter->UCharErrorBufferLength = 0;
  714.  
  715.   myConverter->extraInfo = NULL;
  716.  
  717.  
  718.   switch (myConverter->sharedData->conversionType)
  719.     {
  720.     case UCNV_UTF8:
  721.       {
  722.     myConverter->sharedData->minBytesPerChar = 1;
  723.     myConverter->sharedData->maxBytesPerChar = 4;
  724.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  725.     myConverter->sharedData->defaultConverterValues.subCharLen = 3;
  726.     myConverter->subCharLen = 3;
  727.     myConverter->toUnicodeStatus = 0;
  728.     myConverter->fromUnicodeStatus = 0; /* srl */ 
  729.     myConverter->sharedData->platform = UCNV_IBM;
  730.     myConverter->sharedData->codepage = 1208;
  731.     icu_strcpy(myConverter->sharedData->name, "UTF8");
  732.     icu_memcpy (myConverter->subChar, UTF8_subChar, 3);
  733.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF8_subChar, 3);
  734.  
  735.     break;
  736.       }
  737.     case UCNV_LATIN_1:
  738.       {
  739.     myConverter->sharedData->minBytesPerChar = 1;
  740.     myConverter->sharedData->maxBytesPerChar = 1;
  741.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  742.     myConverter->sharedData->defaultConverterValues.subCharLen = 1;
  743.     myConverter->subCharLen = 1;
  744.     myConverter->toUnicodeStatus = 0;
  745.     myConverter->sharedData->platform = UCNV_IBM;
  746.     myConverter->sharedData->codepage = 819;
  747.     icu_strcpy(myConverter->sharedData->name, "LATIN_1");
  748.     *(myConverter->subChar) = LATIN1_subChar;
  749.     *(myConverter->sharedData->defaultConverterValues.subChar) = LATIN1_subChar;
  750.     break;
  751.       }
  752.  
  753.     case UCNV_UTF16_BigEndian:
  754.       {
  755.     myConverter->sharedData->minBytesPerChar = 2;
  756.     myConverter->sharedData->maxBytesPerChar = 2;
  757.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  758.     myConverter->sharedData->defaultConverterValues.subCharLen = 2;
  759.     myConverter->subCharLen = 2;
  760.     myConverter->toUnicodeStatus = 0;
  761.     myConverter->fromUnicodeStatus = 0; 
  762.     icu_strcpy(myConverter->sharedData->name, "UTF_16BE");
  763.     myConverter->sharedData->platform = UCNV_IBM;
  764.     myConverter->sharedData->codepage = 1200;
  765.     icu_memcpy (myConverter->subChar, UTF16BE_subChar, 2);
  766.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF16BE_subChar, 2);
  767.  
  768.     break;
  769.       }
  770.     case UCNV_UTF16_LittleEndian:
  771.       {
  772.     myConverter->sharedData->minBytesPerChar = 2;
  773.     myConverter->sharedData->maxBytesPerChar = 2;
  774.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  775.     myConverter->sharedData->defaultConverterValues.subCharLen = 2;
  776.     myConverter->subCharLen = 2;
  777.     myConverter->toUnicodeStatus = 0;
  778.     myConverter->fromUnicodeStatus = 0; 
  779.     myConverter->sharedData->platform = UCNV_IBM;
  780.     myConverter->sharedData->codepage = 1200;
  781.     icu_strcpy(myConverter->sharedData->name, "UTF_16LE");
  782.     icu_memcpy (myConverter->subChar, UTF16LE_subChar, 2);
  783.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, UTF16LE_subChar, 2);
  784.     break;
  785.       }
  786.     case UCNV_EUC:
  787.       {
  788.     myConverter->sharedData->minBytesPerChar = 1;
  789.     myConverter->sharedData->maxBytesPerChar = 2;
  790.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  791.     myConverter->sharedData->defaultConverterValues.subCharLen = 2;
  792.     myConverter->subCharLen = 2;
  793.     myConverter->toUnicodeStatus = 0;
  794.     icu_memcpy (myConverter->subChar, EUC_subChar, 2);
  795.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, EUC_subChar, 2);
  796.     break;
  797.       }
  798.     case UCNV_ISO_2022:
  799.       {
  800.     myConverter->charErrorBuffer[0] = 0x1b;
  801.     myConverter->charErrorBuffer[1] = 0x25;
  802.     myConverter->charErrorBuffer[2] = 0x42;
  803.     myConverter->charErrorBufferLength = 3;
  804.     myConverter->sharedData->minBytesPerChar = 1;
  805.     myConverter->sharedData->maxBytesPerChar = 3;
  806.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  807.     myConverter->sharedData->defaultConverterValues.subCharLen = 1;
  808.     myConverter->subCharLen = 1;
  809.     myConverter->toUnicodeStatus = 0;
  810.     myConverter->fromUnicodeStatus = 0; /* srl */ 
  811.     myConverter->sharedData->codepage = 2022;
  812.     icu_strcpy(myConverter->sharedData->name, "ISO_2022");
  813.     *(myConverter->subChar) = LATIN1_subChar;
  814.     *(myConverter->sharedData->defaultConverterValues.subChar) = LATIN1_subChar;
  815.     myConverter->extraInfo = icu_malloc (sizeof (UConverterDataISO2022));
  816.     ((UConverterDataISO2022 *) myConverter->extraInfo)->currentConverter = NULL;
  817.     ((UConverterDataISO2022 *) myConverter->extraInfo)->escSeq2022Length = 0;
  818.     break;
  819.       }
  820.     case UCNV_GB:
  821.       {
  822.     myConverter->sharedData->minBytesPerChar = 2;
  823.     myConverter->sharedData->maxBytesPerChar = 2;
  824.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  825.     myConverter->sharedData->defaultConverterValues.subCharLen = 2;
  826.     myConverter->subCharLen = 2;
  827.     myConverter->toUnicodeStatus = 0;
  828.     icu_memcpy (myConverter->subChar, GB_subChar, 2);
  829.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, GB_subChar, 2);
  830.     break;
  831.       }
  832.     case UCNV_JIS:
  833.       {
  834.     myConverter->sharedData->minBytesPerChar = 2;
  835.     myConverter->sharedData->maxBytesPerChar = 2;
  836.     myConverter->sharedData->defaultConverterValues.toUnicodeStatus = 0;
  837.     myConverter->sharedData->defaultConverterValues.subCharLen = 2;
  838.     myConverter->subCharLen = 2;
  839.     myConverter->toUnicodeStatus = 0;
  840.     icu_memcpy (myConverter->subChar, JIS_subChar, 2);
  841.     icu_memcpy (myConverter->sharedData->defaultConverterValues.subChar, JIS_subChar, 2);
  842.     break;
  843.       }
  844.     default:
  845.       break;
  846.     };
  847.  
  848.   myConverter->toUnicodeStatus = myConverter->sharedData->defaultConverterValues.toUnicodeStatus;
  849. }
  850.  
  851.  
  852. /*This function creates an algorithmic converter
  853.  *Note That even algorithmic converters are shared
  854.  * (The UConverterSharedData->table == NULL since
  855.  * there are no tables)
  856.  *for uniformity of design and control flow
  857.  */
  858. UConverter *
  859.   createConverterFromAlgorithmicType (const char *actualName, UErrorCode * err)
  860. {
  861.   int32_t i = 0;
  862.   UConverter *myConverter = NULL;
  863.   UConverterSharedData *mySharedData = NULL;
  864.   UConverterType myType = getAlgorithmicTypeFromName (actualName);
  865.  
  866.   if (U_FAILURE (*err))
  867.     return NULL;
  868.  
  869.   myConverter = (UConverter *) icu_malloc (sizeof (UConverter));
  870.   if (myConverter == NULL)
  871.     {
  872.       *err = U_MEMORY_ALLOCATION_ERROR;
  873.       return NULL;
  874.     }
  875.  
  876.   myConverter->sharedData = NULL;
  877.   mySharedData = (UConverterSharedData *) icu_malloc (sizeof (UConverterSharedData));
  878.   if (mySharedData == NULL)
  879.     {
  880.       *err = U_MEMORY_ALLOCATION_ERROR;
  881.       icu_free (myConverter);
  882.       return NULL;
  883.     }
  884.   mySharedData->table = NULL;
  885.   icu_strcpy (mySharedData->name, actualName);
  886.   /*Initializes the referenceCounter to 1 */
  887.   mySharedData->referenceCounter = 1;
  888.   mySharedData->platform = UCNV_UNKNOWN;
  889.   mySharedData->codepage = 0;
  890.   mySharedData->conversionType = myType;
  891.   myConverter->sharedData = mySharedData;
  892.  
  893.   initializeAlgorithmicConverter (myConverter);
  894.   return myConverter;
  895. }
  896.