home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / locmap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  13.6 KB  |  487 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   IBM Open Class Library                                                    *
  6. *   (C) Copyright Taligent, Inc.,  1996                                       *
  7. *   (C) Copyright International Business Machines Corporation,  1996-1998     *
  8. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  9. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  10. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  11. *                                                                             *
  12. *******************************************************************************
  13. */
  14. // $Revision: 1.3 $
  15. //
  16. // Provides functionality for mapping between
  17. // LCID and Posix IDs.
  18. //
  19. // Note: All classes and code in this file are
  20. //       intended for internal use only.
  21. //
  22. // Methods of interest:
  23. //   void initializeMapRegions();
  24. //   unsigned long convertToLCID(const int8_t*);
  25. //   const int8_t* convertToPosix(unsigned long);
  26. //
  27. // Kathleen Wilson, 4/30/96
  28. //
  29. //  Date        Name        Description
  30. //  3/11/97     aliu        Fixed off-by-one bug in assignment operator.  Added
  31. //                          setId() method and safety check against 
  32. //                          MAX_ID_LENGTH.
  33. // 04/23/99     stephen     Added C wrapper for convertToPosix.
  34.  
  35.  
  36. #include <math.h>
  37.  
  38. #include "locmap.h"
  39. #include "locid.h"
  40. #include "mutex.h"
  41. #include "cmemory.h"
  42. #include "cstring.h"
  43.  
  44. int32_t        IGlobalLocales::fgLocaleCount = 0;
  45. uint32_t       IGlobalLocales::fgStdLang = 0x0400;
  46. const uint32_t IGlobalLocales::kMapSize = 40;
  47. ILcidPosixMap* IGlobalLocales::fgPosixIDmap = 0;
  48.  
  49. ////////////////////////////////////////////
  50. //
  51. // Create the table of LCID to POSIX Mapping
  52. //
  53. ////////////////////////////////////////////
  54.  
  55.  
  56. void
  57. IGlobalLocales::initializeMapRegions()
  58. {
  59.  
  60.   if (fgPosixIDmap != 0)  // already mapped
  61.         return;
  62.  
  63.   
  64.   ILcidPosixMap *newPosixIDmap = new ILcidPosixMap[40];
  65.   newPosixIDmap[0].initialize(0x0436,  "af_ZA");       // 0
  66.   newPosixIDmap[1].initialize(0x01,    "ar",     16);  // 1
  67.   newPosixIDmap[2].initialize(0x0423,  "be_BY");       // 2
  68.   newPosixIDmap[3].initialize(0x0402,  "bg_BG");       // 3
  69.   newPosixIDmap[4].initialize(0x0403,  "ca_ES");       // 4
  70.   newPosixIDmap[5].initialize(0x0405,  "cs_CS");       // 5
  71.   newPosixIDmap[6].initialize(0x0406,  "da_DK");       // 6
  72.   newPosixIDmap[7].initialize(0x07,    "de",     5);   // 7
  73.   newPosixIDmap[8].initialize(0x0408,  "el_GR");       // 8
  74.   newPosixIDmap[9].initialize(0x09,    "en",     9);   // 9
  75.   newPosixIDmap[10].initialize(0x0a,   "es",     16);  // 10
  76.   newPosixIDmap[11].initialize(0x0425, "et_EE");       // 11
  77.   newPosixIDmap[12].initialize(0x042d, "eu_ES");       // 12
  78.   newPosixIDmap[13].initialize(0x0429, "fa_IR");       // 13
  79.   newPosixIDmap[14].initialize(0x040b, "fi_FI");       // 14
  80.   newPosixIDmap[15].initialize(0x0c,   "fr",     5);   // 15
  81.   newPosixIDmap[16].initialize(0x041a, "hr_HR");       // 16
  82.   newPosixIDmap[17].initialize(0x040e, "hu_HU");       // 17
  83.   newPosixIDmap[18].initialize(0x0421, "in_ID");       // 18
  84.   newPosixIDmap[19].initialize(0x040f, "is_IS");       // 19
  85.   newPosixIDmap[20].initialize(0x10,   "it",     2);   // 20
  86.   newPosixIDmap[21].initialize(0x040d, "iw_IL");       // 21
  87.   newPosixIDmap[22].initialize(0x0411, "ja_JP");       // 22
  88.   newPosixIDmap[23].initialize(0x12,   "ko",     2);   // 23
  89.   newPosixIDmap[24].initialize(0x0427, "lt_LT");       // 24
  90.   newPosixIDmap[25].initialize(0x0426, "lv_LV");       // 25
  91.   newPosixIDmap[26].initialize(0x13,   "nl",     2);   // 26
  92.   newPosixIDmap[27].initialize(0x14,   "no",     2);   // 27
  93.   newPosixIDmap[28].initialize(0x0415, "pl_PL");       // 28
  94.   newPosixIDmap[29].initialize(0x16,   "pt",     2);   // 29
  95.   newPosixIDmap[30].initialize(0x0418, "ro_RO");       // 30
  96.   newPosixIDmap[31].initialize(0x0419, "ru_RU");       // 31
  97.   newPosixIDmap[32].initialize(0x041b, "sk_SK");       // 32
  98.   newPosixIDmap[33].initialize(0x0424, "sl_SI");       // 33
  99.   newPosixIDmap[34].initialize(0x041c, "sq_AL");       // 34
  100.   newPosixIDmap[35].initialize(0x041d, "sv_SE");       // 35
  101.   newPosixIDmap[36].initialize(0x041e, "th_TH");       // 36
  102.   newPosixIDmap[37].initialize(0x041f, "tr_TR");       // 37
  103.   newPosixIDmap[38].initialize(0x0422, "uk_UA");       // 38
  104.   newPosixIDmap[39].initialize(0x04,   "zh",     4);   // 39
  105.   newPosixIDmap[1].addRegion(0x3801, "ar_AE");
  106.   newPosixIDmap[1].addRegion(0x3c01, "ar_BH");
  107.   newPosixIDmap[1].addRegion(0x1401, "ar_DZ");
  108.   newPosixIDmap[1].addRegion(0x0c01, "ar_EG");
  109.   newPosixIDmap[1].addRegion(0x0801, "ar_IQ");
  110.   newPosixIDmap[1].addRegion(0x2c01, "ar_JO");
  111.   newPosixIDmap[1].addRegion(0x3401, "ar_KW");
  112.   newPosixIDmap[1].addRegion(0x3001, "ar_LB");
  113.   newPosixIDmap[1].addRegion(0x1001, "ar_LY");
  114.   newPosixIDmap[1].addRegion(0x1801, "ar_MA");
  115.   newPosixIDmap[1].addRegion(0x2001, "ar_OM");
  116.   newPosixIDmap[1].addRegion(0x4001, "ar_QA");
  117.   newPosixIDmap[1].addRegion(0x0401, "ar_SA");
  118.   newPosixIDmap[1].addRegion(0x2801, "ar_SY");
  119.   newPosixIDmap[1].addRegion(0x1c01, "ar_TN");
  120.   newPosixIDmap[1].addRegion(0x2401, "ar_YE");
  121.  
  122.   newPosixIDmap[7].addRegion(0x0c07, "de_AT");
  123.   newPosixIDmap[7].addRegion(0x0807, "de_CH");
  124.   newPosixIDmap[7].addRegion(0x0407, "de_DE");
  125.   newPosixIDmap[7].addRegion(0x1407, "de_LI");
  126.   newPosixIDmap[7].addRegion(0x1007, "de_LU");
  127.  
  128.   newPosixIDmap[9].addRegion(0x0c09, "en_AU");
  129.   newPosixIDmap[9].addRegion(0x1009, "en_CA");
  130.   newPosixIDmap[9].addRegion(0x0809, "en_GB");
  131.   newPosixIDmap[9].addRegion(0x1809, "en_IE");
  132.   newPosixIDmap[9].addRegion(0x2009, "en_JM");
  133.   newPosixIDmap[9].addRegion(0x1409, "en_NZ");
  134.   newPosixIDmap[9].addRegion(0x0409, "en_US");
  135.   newPosixIDmap[9].addRegion(0x2409, "en_VI");
  136.   newPosixIDmap[9].addRegion(0x1c09, "en_ZA");
  137.  
  138.   newPosixIDmap[10].addRegion(0x2c0a, "es_AR");
  139.   newPosixIDmap[10].addRegion(0x400a, "es_BO");
  140.   newPosixIDmap[10].addRegion(0x340a, "es_CL");
  141.   newPosixIDmap[10].addRegion(0x240a, "es_CO");
  142.   newPosixIDmap[10].addRegion(0x140a, "es_CR");
  143.   newPosixIDmap[10].addRegion(0x1c0a, "es_DO");
  144.   newPosixIDmap[10].addRegion(0x300a, "es_EC");
  145.   newPosixIDmap[10].addRegion(0x0c0a, "es_ES");
  146.   newPosixIDmap[10].addRegion(0x040a, "es_ES_T");
  147.   newPosixIDmap[10].addRegion(0x100a, "es_GT");
  148.   newPosixIDmap[10].addRegion(0x080a, "es_MX");
  149.   newPosixIDmap[10].addRegion(0x180a, "es_PA");
  150.   newPosixIDmap[10].addRegion(0x280a, "es_PE");
  151.   newPosixIDmap[10].addRegion(0x3c0a, "es_PY");
  152.   newPosixIDmap[10].addRegion(0x380a, "es_UY");
  153.   newPosixIDmap[10].addRegion(0x200a, "es_VE");
  154.  
  155.   newPosixIDmap[15].addRegion(0x080c, "fr_BE");
  156.   newPosixIDmap[15].addRegion(0x0c0c, "fr_CA");
  157.   newPosixIDmap[15].addRegion(0x100c, "fr_CH");
  158.   newPosixIDmap[15].addRegion(0x040c, "fr_FR");
  159.   newPosixIDmap[15].addRegion(0x140c, "fr_LU");
  160.  
  161.   newPosixIDmap[20].addRegion(0x0810, "it_CH");
  162.   newPosixIDmap[20].addRegion(0x0410, "it_IT");
  163.  
  164.   newPosixIDmap[23].addRegion(0x0812, "ko_KR");
  165.   newPosixIDmap[23].addRegion(0x0412, "ko_KR");
  166.  
  167.   newPosixIDmap[26].addRegion(0x0813, "nl_BE");
  168.   newPosixIDmap[26].addRegion(0x0413, "nl_NL");
  169.  
  170.   newPosixIDmap[27].addRegion(0x0414, "no_NO");
  171.   newPosixIDmap[27].addRegion(0x0814, "no_NO_NY");
  172.  
  173.   newPosixIDmap[29].addRegion(0x0416, "pt_BR");
  174.   newPosixIDmap[29].addRegion(0x0816, "pt_PT");
  175.  
  176.   newPosixIDmap[39].addRegion(0x0804, "zh_CN");
  177.   newPosixIDmap[39].addRegion(0x0c04, "zh_HK");
  178.   newPosixIDmap[39].addRegion(0x1004, "zh_SG");
  179.   newPosixIDmap[39].addRegion(0x0404, "zh_TW");
  180.  
  181.   {
  182.     Mutex m;
  183.     if(fgPosixIDmap == 0)
  184.     {
  185.       fgPosixIDmap = newPosixIDmap;
  186.       fgLocaleCount = 105;
  187.       newPosixIDmap = 0; // successfully assigned it
  188.     }
  189.   }
  190.  
  191.   delete newPosixIDmap; // If it wasn't assigned. Don't delete these 40 inside a mutex.
  192. }
  193.  
  194. //////////////////////////////////////
  195. //
  196. // LCID --> POSIX
  197. //
  198. /////////////////////////////////////
  199.  
  200. const char*
  201. IGlobalLocales::convertToPosix(uint32_t hostid)
  202. {
  203.   initializeMapRegions();
  204.     
  205.   uint16_t langID = languageLCID(hostid);
  206.   uint32_t index;
  207.   for (index = 0; index < kMapSize; index++)
  208.     {
  209.       if (langID == fgPosixIDmap[index].hostLangID())
  210.         {
  211.           return fgPosixIDmap[index].posixID(hostid);
  212.         }
  213.     }
  214.  
  215.   //no match found
  216.   return ILcidPosixMap::fgWildCard;
  217. }
  218.  
  219. U_CFUNC const char*
  220. T_convertToPosix(int32_t hostid)
  221. {
  222.   return IGlobalLocales::convertToPosix(hostid);
  223. }
  224.  
  225.  
  226. //////////////////////////////////////
  227. //
  228. // POSIX --> LCID
  229. //
  230. /////////////////////////////////////
  231.  
  232. uint32_t
  233. IGlobalLocales::convertToLCID(const char* posixID)
  234. {
  235.   if (!posixID || strlen(posixID) < 2)
  236.     return 0;
  237.   
  238.   initializeMapRegions();
  239.  
  240.   //Binary search for the map entry
  241.  
  242.   uint32_t  low = 0, mid = 0;
  243.   uint32_t  high = kMapSize - 1;
  244.  
  245.   char langID[3];
  246.   langID[0] = posixID[0];
  247.   langID[1] = posixID[1];
  248.   langID[2] = 0;
  249.  
  250.   while (low <= high) {
  251.  
  252.     mid = (low + high) / 2;
  253.  
  254.     int32_t compVal = icu_strcmp(langID, fgPosixIDmap[mid].posixLangID());
  255.  
  256.     if (mid == 0)  // not found
  257.        break;
  258.     if (compVal < 0)
  259.       high = mid - 1;
  260.     else if (compVal > 0)
  261.       low = mid + 1;
  262.     else  // found match!
  263.       return fgPosixIDmap[mid].hostID(posixID);
  264.     }
  265.     // no match found
  266.     return 0;
  267. }
  268.  
  269. uint16_t
  270. IGlobalLocales::languageLCID(uint32_t hostID)
  271. {
  272.     return (uint16_t)(0x00FF & hostID);
  273. }
  274.  
  275. /////////////////////////////////////////////////////
  276. //
  277. // Given a hexadecimal number in decimal notation,
  278. // find the decimal notation for the two lowest bits.
  279. //
  280. // e.g. given 0x3456 return 0x56 in decimal notation.
  281. //
  282. /////////////////////////////////////////////////////
  283.  
  284. ILcidPosixElement::ILcidPosixElement(uint32_t hid,
  285.                                      const char* pid)
  286. {
  287.   fHostID = hid;
  288.   int32_t len = setId(pid);
  289.  
  290.   if (len == 2)
  291.     {
  292.       fPosixID[2] = '_';
  293.       fPosixID[3] = '?';
  294.       fPosixID[4] = '?';
  295.       fPosixID[5] = 0;
  296.     }
  297.  
  298. }
  299.  
  300. int32_t ILcidPosixElement::setId(const char* id)
  301. {
  302.   int32_t len = strlen(id);
  303.   if (len >= MAX_ID_LENGTH) len = MAX_ID_LENGTH - 1;
  304.   int32_t index;
  305.  
  306.   for (index = 0; index < len; index++)
  307.     {
  308.       fPosixID[index] = id[index];
  309.     }
  310.   fPosixID[len] = 0; //null terminate
  311.   return len;
  312. }
  313.  
  314. ILcidPosixElement::ILcidPosixElement()
  315. {
  316.   fHostID = 0;
  317.   fPosixID[0] = 0;
  318. }
  319.  
  320.  
  321. ILcidPosixElement::ILcidPosixElement(const ILcidPosixElement& that)
  322. {
  323.   fHostID = that.fHostID;
  324.   setId(that.fPosixID);
  325. }
  326.  
  327. ILcidPosixElement&
  328. ILcidPosixElement::operator=(const ILcidPosixElement& that)
  329. {
  330.   if (this != &that)
  331.     {
  332.       fHostID = that.fHostID;
  333.       setId(that.fPosixID);
  334.     }
  335.   return *this;
  336. }
  337.  
  338.  
  339. ILcidPosixElement::~ILcidPosixElement()
  340. {
  341. }
  342.  
  343.  
  344. const char*  ILcidPosixMap::fgWildCard = "??_??";
  345.  
  346. void
  347. ILcidPosixMap::initialize (uint32_t hostID,
  348.                            const char* posixID,
  349.                            uint32_t totalRegions)
  350. {
  351.   fHostLangID = IGlobalLocales::languageLCID(hostID);
  352.  
  353.   fPosixLangID[0] = posixID[0]; // don't care about these being called twice. not critical.
  354.   fPosixLangID[1] = posixID[1];
  355.   fPosixLangID[2] = 0;
  356.  
  357.   fMapSize = totalRegions + 1;
  358.    fNumRegions=0;
  359.  
  360.   fRegionMaps = new ILcidPosixElement[fMapSize];
  361.  
  362.   //The first element will always be wild card
  363.   fRegionMaps[0] =
  364.     ILcidPosixElement(fHostLangID, fPosixLangID);
  365.  
  366.   if (totalRegions == 1 && strlen(posixID) >= 5)
  367.     {
  368.       fNumRegions++;
  369.  
  370.       fRegionMaps[1] =
  371.         ILcidPosixElement(hostID, posixID);
  372.     }
  373. }
  374.  
  375. //default constructor is private, cannot be used.
  376. ILcidPosixMap::ILcidPosixMap()
  377. {
  378.   fHostLangID = 0;
  379.   fPosixLangID[0] = '?';
  380.   fPosixLangID[1] = '?';
  381.   fPosixLangID[2] = 0;
  382.  
  383.   fRegionMaps = 0;
  384.   fMapSize = 0;
  385.   fNumRegions = 0;
  386. }
  387.  
  388. //copy constructor is private, cannot be used.
  389. ILcidPosixMap::ILcidPosixMap(const ILcidPosixMap& that)
  390. {
  391.   fHostLangID = that.fHostLangID;
  392.   fPosixLangID[0] = that.fPosixLangID[0];
  393.   fPosixLangID[1] = that.fPosixLangID[1];
  394.   fPosixLangID[2] = 0;
  395.  
  396.   fRegionMaps = 0;
  397.   fMapSize = 0;
  398.   fNumRegions = 0;
  399. }
  400.  
  401. //assignment operator is private, cannot be used.
  402. ILcidPosixMap&
  403. ILcidPosixMap::operator=(const ILcidPosixMap& that)
  404. {
  405.   if (this != &that)
  406.     {
  407.       fHostLangID = that.fHostLangID;
  408.       fPosixLangID[0] = that.fPosixLangID[0];
  409.       fPosixLangID[1] = that.fPosixLangID[1];
  410.       fPosixLangID[2] = 0;
  411.  
  412.       fRegionMaps = 0;
  413.       fMapSize = 0;
  414.       fNumRegions = 0;
  415.     }
  416.   return *this;
  417. }
  418.  
  419. ILcidPosixMap::~ILcidPosixMap()
  420. {
  421.   if (fMapSize)
  422.     delete [] fRegionMaps;
  423. }
  424.  
  425. void ILcidPosixMap::addRegion (uint32_t hostID,
  426.                                const char* posixID)
  427. {
  428.   if (fMapSize && fNumRegions < (fMapSize - 1))
  429.     {
  430.       ILcidPosixElement save(hostID,posixID);
  431.       fNumRegions++;
  432.  
  433.       fRegionMaps[fNumRegions] = save;
  434.     }
  435. }
  436.  
  437.  
  438. //assumes Posix IDs are sorted alphabetically
  439. uint32_t
  440. ILcidPosixMap::hostID(const char* posixID) const
  441. {
  442.   if (!fMapSize || strlen(posixID) < 5) //incomplete id
  443.     return fHostLangID;
  444.  
  445.   //Binary search for the map entry
  446.   //The element at index 0 is always the POSIX wild card,
  447.   //so start search at index 1.
  448.  
  449.   uint32_t  low = 1, mid = 1;
  450.   uint32_t  high = fNumRegions;
  451.  
  452.   while (low <= high) {
  453.  
  454.     mid = (low + high) / 2;
  455.  
  456.     int32_t compVal = icu_strcmp(posixID, fRegionMaps[mid].fPosixID);
  457.  
  458.     if (compVal < 0)
  459.       high = mid - 1;
  460.     else if (compVal > 0)
  461.       low = mid + 1;
  462.     else  // found match!
  463.       return fRegionMaps[mid].fHostID;
  464.   }
  465.  
  466.   //no match found
  467.   return fHostLangID;
  468. }
  469.  
  470. const char*
  471. ILcidPosixMap::posixID(uint32_t hostID) const
  472. {
  473.   uint32_t i;
  474.   for (i = 0; i <= fNumRegions; i++)
  475.     {
  476.       if (fRegionMaps[i].fHostID == hostID)
  477.         {
  478.           return fRegionMaps[i].fPosixID;
  479.         }
  480.     }
  481.  
  482.   //if you get here, then no matching region was found,
  483.   //so return the language id with the wild card region.
  484.   return fRegionMaps[0].fPosixID;
  485. }
  486.  
  487.