home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / ucnv_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-11  |  7.5 KB  |  274 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_io.c:
  14.    *  initializes global variables and defines functions pertaining to file access,
  15.    *  and name resolution aspect of the library.
  16.    ********************************************************************************
  17.  */
  18. #include "utypes.h"
  19. #include "umutex.h"
  20. #include "filestrm.h"
  21. #include "cstring.h"
  22. #include "cmemory.h"
  23. #include "uhash.h"
  24. #include "ucmp8.h"
  25. #include "ucmp16.h"
  26. #include "ucnv_bld.h"
  27. #include "ucnv_io.h"
  28. #include "uloc.h"
  29.  
  30. static void doSetupAliasTableAndAvailableConverters (FileStream * converterFile,
  31.                              UErrorCode * err);
  32.  
  33. static char *_convertDataDirectory = NULL;
  34.  
  35. /*Initializes Global Variables */
  36. static UHashtable *ALIASNAMES_HASHTABLE = NULL;
  37. char **AVAILABLE_CONVERTERS_NAMES = NULL;
  38. int32_t AVAILABLE_CONVERTERS = 0;
  39.  
  40. /* Remove all characters followed by '#'
  41.  */
  42. char *
  43.   removeComments (char *line)
  44. {
  45.   char *pound = icu_strchr (line, '#');
  46.  
  47.   if (pound != NULL)
  48.     *pound = '\0';
  49.   return line;
  50. }
  51.  
  52. /*Returns uppercased string */
  53. char *
  54.   strtoupper (char *name)
  55. {
  56.   int32_t i = 0;
  57.  
  58.   while (name[i] = icu_toupper (name[i]))
  59.     i++;
  60.  
  61.   return name;
  62. }
  63.  
  64. /* Returns true in c is a in set 'setOfChars', false otherwise
  65.  */
  66. bool_t 
  67.   isInSet (char c, const char *setOfChars)
  68. {
  69.   uint8_t i = 0;
  70.  
  71.   while (setOfChars[i] != '\0')
  72.     {
  73.       if (c == setOfChars[i++])
  74.     return TRUE;
  75.     }
  76.  
  77.   return FALSE;
  78. }
  79.  
  80. /* Returns pointer to the next non-whitespace (or non-separator)
  81.  */
  82. int32_t 
  83.   nextTokenOffset (const char *line, const char *separators)
  84. {
  85.   int32_t i = 0;
  86.  
  87.   while (line[i] && isInSet (line[i], separators))
  88.     i++;
  89.  
  90.   return i;
  91. }
  92.  
  93. /* Returns pointer to the next token based on the set of separators
  94.  */
  95. char *
  96.   getToken (char *token, char *line, const char *separators)
  97. {
  98.   int32_t i = nextTokenOffset (line, separators);
  99.   int8_t j = 0;
  100.  
  101.   while (line[i] && (!isInSet (line[i], separators)))
  102.     token[j++] = line[i++];
  103.   token[j] = '\0';
  104.  
  105.   return line + i;
  106. }
  107.  
  108. /* this function is called only   if ((ALIASNAMES_HASHTABLE == NULL) ||
  109.  * (AVAILABLE_CONVERTERS_NAMES == NULL)) it builds a hashtable containing
  110.  * all the "real" table names (filenames), keyed-off of the aliases and
  111.  * the real-names themselves.
  112.  * Also builds an array of char **, that point to the allocated memory
  113.  * for each actual names in the Hashtable.
  114.  * That array is used in T_UnicodeConverter_getAvailableNames.
  115.  */
  116. void 
  117.   setupAliasTableAndAvailableConverters (UErrorCode * err)
  118. {
  119.   char fullFileName[UCNV_MAX_FULL_FILE_NAME_LENGTH];
  120.   FileStream *converterFile = NULL;
  121.  
  122.   if (U_FAILURE (*err))
  123.     return;
  124.  
  125.   icu_strcpy (fullFileName, uloc_getDataDirectory ());
  126.   icu_strcat (fullFileName, CONVERTER_FILE_NAME);
  127.  
  128.   converterFile = T_FileStream_open (fullFileName, "r");
  129.   if (converterFile == NULL)
  130.     {
  131.       *err = U_FILE_ACCESS_ERROR;
  132.     }
  133.   else
  134.     {
  135.       doSetupAliasTableAndAvailableConverters (converterFile, err);
  136.       T_FileStream_close (converterFile);
  137.     }
  138.  
  139.   return;
  140. }
  141.  
  142. /* this function is only to be called by setupAliasTableAndAvailableConverters
  143.  */
  144. void 
  145.   doSetupAliasTableAndAvailableConverters (FileStream * converterFile, UErrorCode * err)
  146. {
  147.   char myLine[UCNV_MAX_LINE_TEXT];
  148.   char *line = myLine;
  149.   char actualNameToken[UCNV_MAX_CONVERTER_NAME_LENGTH];
  150.   char aliasNameToken[UCNV_MAX_CONVERTER_NAME_LENGTH];
  151.   char *toBeHashed = NULL;
  152.   UHashtable *myALIASNAMES_HASHTABLE = NULL;
  153.   char **myAVAILABLE_CONVERTERS_NAMES = NULL;
  154.   int32_t myAVAILABLE_CONVERTERS = 0;
  155.  
  156.   /*We need to do the initial work of setting everything */
  157.   myALIASNAMES_HASHTABLE = uhash_open ((UHashFunction)uhash_hashIString, err);
  158.   if (U_FAILURE (*err))
  159.     return;
  160.  
  161.   if (myALIASNAMES_HASHTABLE == NULL)
  162.     return;
  163.  
  164.   while (T_FileStream_readLine (converterFile, line, UCNV_MAX_LINE_TEXT))
  165.     {
  166.       removeComments (line);
  167.       if (line[nextTokenOffset (line, SPACE_SEPARATORS)] != '\0')    /*Skips Blank lines */
  168.     {
  169.       line = getToken (actualNameToken, line, SPACE_SEPARATORS);
  170.       toBeHashed = (char *) icu_malloc ((icu_strlen (actualNameToken) + 1) * sizeof (char));
  171.       if (toBeHashed == NULL)
  172.         {
  173.           *err = U_MEMORY_ALLOCATION_ERROR;
  174.           return;
  175.         }
  176.       icu_strcpy (toBeHashed, actualNameToken);
  177.       myAVAILABLE_CONVERTERS_NAMES = (char **) icu_realloc (myAVAILABLE_CONVERTERS_NAMES,
  178.                 (myAVAILABLE_CONVERTERS + 1) * sizeof (char *));
  179.       if (myAVAILABLE_CONVERTERS_NAMES == NULL)
  180.         {
  181.           *err = U_MEMORY_ALLOCATION_ERROR;
  182.           return;
  183.         }
  184.       myAVAILABLE_CONVERTERS_NAMES[myAVAILABLE_CONVERTERS++] = toBeHashed;
  185.  
  186.       uhash_put (myALIASNAMES_HASHTABLE, toBeHashed, err);
  187.       while (line[nextTokenOffset (line, SPACE_SEPARATORS)] != '\0')
  188.         {
  189.           line = getToken (aliasNameToken, line, SPACE_SEPARATORS);
  190.           uhash_putKey (myALIASNAMES_HASHTABLE,
  191.                 uhash_hashIString (aliasNameToken),
  192.                 toBeHashed,
  193.                 err);
  194.         }
  195.       if (U_FAILURE (*err))
  196.         return;
  197.     }
  198.  
  199.     }
  200.  
  201.   /*If another thread has already created the hashtable and array, we need to free */
  202.   if ((ALIASNAMES_HASHTABLE != NULL) || (AVAILABLE_CONVERTERS_NAMES != NULL))
  203.     {
  204.       while (myAVAILABLE_CONVERTERS > 0)
  205.     {
  206.       icu_free (myAVAILABLE_CONVERTERS_NAMES[--myAVAILABLE_CONVERTERS]);
  207.     }
  208.       icu_free (myAVAILABLE_CONVERTERS_NAMES);
  209.       uhash_close (myALIASNAMES_HASHTABLE);
  210.     }
  211.   else
  212.     {
  213.       umtx_lock (NULL);
  214.       ALIASNAMES_HASHTABLE = myALIASNAMES_HASHTABLE;
  215.       AVAILABLE_CONVERTERS_NAMES = myAVAILABLE_CONVERTERS_NAMES;
  216.       AVAILABLE_CONVERTERS = myAVAILABLE_CONVERTERS;
  217.       umtx_unlock (NULL);
  218.     }
  219.  
  220.   return;
  221. }
  222.  
  223. /* resolveName takes a table alias name and fills in the actual name used internally.
  224.  * it returns a TRUE if the name was found (table supported) returns FALSE otherwise
  225.  */
  226. bool_t 
  227.   resolveName (char *realName, const char *alias)
  228. {
  229.   int32_t i = 0;
  230.   bool_t found = FALSE;
  231.   char *actualName = NULL;
  232.   UErrorCode err = U_ZERO_ERROR;
  233.  
  234.   /*Lazy evaluates the Alias hashtable */
  235.   if (ALIASNAMES_HASHTABLE == NULL)
  236.     setupAliasTableAndAvailableConverters (&err);
  237.   if (U_FAILURE (err))
  238.     return FALSE;
  239.  
  240.  
  241.   actualName = (char *) uhash_get (ALIASNAMES_HASHTABLE, uhash_hashIString (alias));
  242.  
  243.   if (actualName != NULL)
  244.     {
  245.       icu_strcpy (realName, actualName);
  246.       found = TRUE;
  247.     }
  248.  
  249.   return found;
  250. }
  251.  
  252. /*Higher level function, takes in an alias name
  253.  *and returns a file pointer of the table file
  254.  *Will return NULL if the file isn't found for
  255.  *any given reason (file not there, name not in
  256.  *"convrtrs.txt"
  257.  */
  258. FileStream *
  259.   openConverterFile (const char *name)
  260. {
  261.   char actualFullFilenameName[UCNV_MAX_FULL_FILE_NAME_LENGTH];
  262.   FileStream *tableFile = NULL;
  263.  
  264.   icu_strcpy (actualFullFilenameName, uloc_getDataDirectory ());
  265.  
  266.   if (resolveName (actualFullFilenameName + icu_strlen (actualFullFilenameName), name))
  267.     {
  268.       icu_strcat (actualFullFilenameName, CONVERTER_FILE_EXTENSION);
  269.       tableFile = T_FileStream_open (actualFullFilenameName, "rb");
  270.     }
  271.  
  272.   return tableFile;
  273. }
  274.