blob: 121882a08a17e45c463e62046445150e476975bb [file] [log] [blame]
/*
**********************************************************************
* Copyright (C) 1996-1999, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
// $Revision: 1.19 $
//
// Provides functionality for mapping between
// LCID and Posix IDs.
//
// Note: All classes and code in this file are
// intended for internal use only.
//
// Methods of interest:
// unsigned long convertToLCID(const int8_t*);
// const int8_t* convertToPosix(unsigned long);
//
// Kathleen Wilson, 4/30/96
//
// Date Name Description
// 3/11/97 aliu Fixed off-by-one bug in assignment operator. Added
// setId() method and safety check against
// MAX_ID_LENGTH.
// 04/23/99 stephen Added C wrapper for convertToPosix.
// 09/18/00 george Removed the memory leaks.
#ifdef WIN32
/*
* Note:
* This code is used only internally by putil.c/uprv_getDefaultLocaleID().
* This means that this could be much simpler code, and the mapping
* from Win32 locale ID numbers to POSIX locale strings should
* be the faster one.
*/
#include "locmap.h"
#include "unicode/locid.h"
#include "unicode/uloc.h"
#include "mutex.h"
#include "cstring.h"
/////////////////////////////////////////////////
//
// Internal Classes for LCID <--> POSIX Mapping
//
/////////////////////////////////////////////////
struct ILcidPosixElement
{
uint16_t hostID;
const char *posixID;
};
struct ILcidPosixMap
{
const char* posixID(uint32_t fromHostID) const;
/**
* Searches for a Windows LCID
*
* @param posixid the Posix style locale id.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
* no equivalent Windows LCID.
* @return the LCID
*/
uint32_t hostID(const char* fromPosixID) const;
/**
* Do not call this function. It is called by hostID.
* The function is not private because this struct must stay as a C struct,
* and this is an internal class.
*/
uint32_t searchPosixIDmap(const char* posixID, UErrorCode* status) const;
uint32_t numRegions;
const ILcidPosixElement* regionMaps;
};
/////////////////////////////////////////////////
//
// Easy macros to make the LCID <--> POSIX Mapping
//
/////////////////////////////////////////////////
/*
The standard one language/one country mapping for LCID.
The first element must be the language, and the following
elements are the language with the country.
*/
#define ILCID_POSIX_ELEMENT_ARRAY(hostID, languageID, posixID) \
static const ILcidPosixElement languageID[] = { \
{LANGUAGE_LCID(hostID), #languageID}, /* parent locale */ \
{hostID, #posixID}, \
};
/*
Create the map for the posixID. This macro supposes that the language string
name is the same as the global variable name, and that the first element
in the ILcidPosixElement is just the language.
*/
#define ILCID_POSIX_MAP(_posixID) \
{sizeof(_posixID)/sizeof(ILcidPosixElement), _posixID}
////////////////////////////////////////////
//
// Create the table of LCID to POSIX Mapping
// None of it should be dynamically created.
//
////////////////////////////////////////////
ILCID_POSIX_ELEMENT_ARRAY(0x0436, af, af_ZA)
static const ILcidPosixElement ar[] = {
{0x01, "ar"},
{0x3801, "ar_AE"},
{0x3c01, "ar_BH"},
{0x1401, "ar_DZ"},
{0x0c01, "ar_EG"},
{0x0801, "ar_IQ"},
{0x2c01, "ar_JO"},
{0x3401, "ar_KW"},
{0x3001, "ar_LB"},
{0x1001, "ar_LY"},
{0x1801, "ar_MA"},
{0x2001, "ar_OM"},
{0x4001, "ar_QA"},
{0x0401, "ar_SA"},
{0x2801, "ar_SY"},
{0x1c01, "ar_TN"},
{0x2401, "ar_YE"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x044d, as, as_IN) //Todo: Data does not exist
static const ILcidPosixElement az[] = { //Todo: Data does not exist
{0x2c, "az"},
{0x082c, "az_AZ_C"},
{0x042c, "az_AZ_L"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0423, be, be_BY)
ILCID_POSIX_ELEMENT_ARRAY(0x0402, bg, bg_BG)
ILCID_POSIX_ELEMENT_ARRAY(0x0445, bn, bn_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0403, ca, ca_ES)
ILCID_POSIX_ELEMENT_ARRAY(0x0405, cs, cs_CZ)
ILCID_POSIX_ELEMENT_ARRAY(0x0406, da, da_DK)
static const ILcidPosixElement de[] = {
{0x07, "de"},
{0x0c07, "de_AT"},
{0x0807, "de_CH"},
{0x0407, "de_DE"},
{0x1407, "de_LI"}, //Todo: Data does not exist
{0x1007, "de_LU"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0408, el, el_GR)
static const ILcidPosixElement en[] = {
{0x09, "en"},
{0x0c09, "en_AU"},
{0x2809, "en_BZ"}, //Todo: Data does not exist
{0x1009, "en_CA"},
{0x0809, "en_GB"},
{0x1809, "en_IE"},
{0x2009, "en_JM"}, //Todo: Data does not exist
{0x1409, "en_NZ"},
{0x3409, "en_PH"}, //Todo: Data does not exist
{0x2C09, "en_TT"}, //Todo: Data does not exist
{0x0409, "en_US"},
{0x2409, "en_VI"}, //Todo: Data does not exist
{0x1c09, "en_ZA"},
{0x3009, "en_ZW"}
};
static const ILcidPosixElement es[] = {
{0x0a, "es"},
{0x2c0a, "es_AR"},
{0x400a, "es_BO"},
{0x340a, "es_CL"},
{0x240a, "es_CO"},
{0x140a, "es_CR"},
{0x1c0a, "es_DO"},
{0x300a, "es_EC"},
{0x0c0a, "es_ES"}, //Modern sort.
{0x040a, "es_ES_T"}, //Todo: Data does not exist. Traditional sort?
{0x100a, "es_GT"},
{0x480a, "es_HN"},
{0x080a, "es_MX"},
{0x4c0a, "es_NI"},
{0x180a, "es_PA"},
{0x280a, "es_PE"},
{0x500a, "es_PR"},
{0x3c0a, "es_PY"},
{0x440a, "es_SV"},
{0x380a, "es_UY"},
{0x200a, "es_VE"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0425, et, et_EE)
ILCID_POSIX_ELEMENT_ARRAY(0x042d, eu, eu_ES)
ILCID_POSIX_ELEMENT_ARRAY(0x0429, fa, fa_IR)
ILCID_POSIX_ELEMENT_ARRAY(0x040b, fi, fi_FI)
ILCID_POSIX_ELEMENT_ARRAY(0x0438, fo, fo_FO)
static const ILcidPosixElement fr[] = {
{0x0c, "fr"},
{0x080c, "fr_BE"},
{0x0c0c, "fr_CA"},
{0x100c, "fr_CH"},
{0x040c, "fr_FR"},
{0x140c, "fr_LU"},
{0x180c, "fr_MC"} //Todo: Data does not exist
};
ILCID_POSIX_ELEMENT_ARRAY(0x0447, gu, gu_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x040d, he, he_IL)
ILCID_POSIX_ELEMENT_ARRAY(0x0439, hi, hi_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x041a, hr, hr_HR)
ILCID_POSIX_ELEMENT_ARRAY(0x040e, hu, hu_HU)
ILCID_POSIX_ELEMENT_ARRAY(0x042b, hy, hy_AM) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0421, id, id_ID)
//ILCID_POSIX_ELEMENT_ARRAY(0x0421, in, in_ID) //Should really be id_ID
ILCID_POSIX_ELEMENT_ARRAY(0x040f, is, is_IS)
static const ILcidPosixElement it[] = {
{0x10, "it"},
{0x0810, "it_CH"},
{0x0410, "it_IT"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x040d, iw, iw_IL) //Should really be he_IL
ILCID_POSIX_ELEMENT_ARRAY(0x0411, ja, ja_JP)
ILCID_POSIX_ELEMENT_ARRAY(0x0437, ka, ka_GE) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x043f, kk, kk_KZ) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x044b, kn, kn_IN) //Todo: Data does not exist
static const ILcidPosixElement ko[] = {
{0x12, "ko"},
{0x0812, "ko_KP"},
{0x0412, "ko_KR"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0457, kok, kok_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x0460, ks, ks_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0427, lt, lt_LT)
ILCID_POSIX_ELEMENT_ARRAY(0x0426, lv, lv_LV)
ILCID_POSIX_ELEMENT_ARRAY(0x042f, mk, mk_MK)
ILCID_POSIX_ELEMENT_ARRAY(0x044c, ml, ml_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0458, mni, mni_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x044e, mr, mr_IN)
static const ILcidPosixElement ms[] = { //Todo: Data does not exist
{0x3e, "ms"},
{0x083e, "ms_BN"}, // Brunei Darussalam
{0x043e, "ms_MY"} // Malaysia
};
// The MSJDK documentation says this is maltese, but it's not supported.
ILCID_POSIX_ELEMENT_ARRAY(0x043a, mt, mt_MT)
ILCID_POSIX_ELEMENT_ARRAY(0x0414, nb, nb_NO)
static const ILcidPosixElement ne[] = { //Todo: Data does not exist
{0x61, "ne"},
{0x0861, "ne_IN"}, // India
{0x0461, "ne_NP"} // Nepal
};
static const ILcidPosixElement nl[] = {
{0x13, "nl"},
{0x0813, "nl_BE"},
{0x0413, "nl_NL"}
};
static const ILcidPosixElement no[] = {
{0x14, "no"},
{0x0414, "no_NO"},
{0x0814, "nn_NO_NY"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0814, nn, nn_NO)
ILCID_POSIX_ELEMENT_ARRAY(0x0448, or, or_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0446, pa, pa_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0415, pl, pl_PL)
static const ILcidPosixElement pt[] = {
{0x16, "pt"},
{0x0416, "pt_BR"},
{0x0816, "pt_PT"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0418, ro, ro_RO)
static const ILcidPosixElement root[] = {
{0x00, "root"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0419, ru, ru_RU)
ILCID_POSIX_ELEMENT_ARRAY(0x044f, sa, sa_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0459, sd, sd_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x081a, sh, sh_YU)
ILCID_POSIX_ELEMENT_ARRAY(0x041b, sk, sk_SK)
ILCID_POSIX_ELEMENT_ARRAY(0x0424, sl, sl_SI)
ILCID_POSIX_ELEMENT_ARRAY(0x041c, sq, sq_AL)
ILCID_POSIX_ELEMENT_ARRAY(0x0c1a, sr, sr_YU)
static const ILcidPosixElement sv[] = {
{0x1d, "sv"},
{0x081d, "sv_FI"},
{0x041d, "sv_SE"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0441, sw, sw_KE)// The MSJDK documentation says the default country is Kenya.
ILCID_POSIX_ELEMENT_ARRAY(0x0449, ta, ta_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x044a, te, te_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x041e, th, th_TH)
ILCID_POSIX_ELEMENT_ARRAY(0x041f, tr, tr_TR)
ILCID_POSIX_ELEMENT_ARRAY(0x0444, tt, tt_RU) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x0422, uk, uk_UA)
static const ILcidPosixElement ur[] = { //Todo: Data does not exist
{0x20, "ur"},
{0x0820, "ur_IN"},
{0x0420, "ur_PK"}
};
static const ILcidPosixElement uz[] = { //Todo: Data does not exist
{0x43, "uz"},
{0x0843, "uz_UZ_C"},
{0x0443, "uz_UZ_L"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x042a, vi, vi_VN)
static const ILcidPosixElement zh[] = {
{0x04, "zh"},
{0x0804, "zh_CN"},
{0x0c04, "zh_HK"},
{0x1404, "zh_MO"},
{0x1004, "zh_SG"},
{0x0404, "zh_TW"}
};
void
IGlobalLocales::initializeMapRegions()
{
/* This commented out code leaks memory. Use the LCID values as reference only.
These values originally came from winnt.h
*/
/* if (fgPosixIDmap != 0) // already mapped
return;
ILcidPosixMap *newPosixIDmap = new ILcidPosixMap[IGlobalLocales::kMapSize];
newPosixIDmap[0].initialize(0x0436, "af_ZA"); // af Afrikaans 0x36
newPosixIDmap[1].initialize(0x01, "ar", 16); // ar Arabic 0x01
newPosixIDmap[2].initialize(0x044d, "as_IN"); // as Assamese 0x4d
newPosixIDmap[3].initialize(0x2c, "az", 2); // az Azerbaijani 0x2c
newPosixIDmap[4].initialize(0x0423, "be_BY"); // be Byelorussian 0x23
newPosixIDmap[5].initialize(0x0402, "bg_BG"); // bg Bulgarian 0x02
newPosixIDmap[6].initialize(0x0445, "bn_IN"); // bn Bengali; Bangla 0x45
newPosixIDmap[7].initialize(0x0403, "ca_ES"); // ca Catalan 0x03
newPosixIDmap[8].initialize(0x0405, "cs_CZ"); // cs Czech 0x05
newPosixIDmap[9].initialize(0x0406, "da_DK"); // da Danish 0x06
newPosixIDmap[10].initialize(0x07, "de", 5); // de German 0x07
newPosixIDmap[11].initialize(0x0408, "el_GR"); // el Greek 0x08
newPosixIDmap[12].initialize(0x09, "en", 13); // en English 0x09
newPosixIDmap[13].initialize(0x0a, "es", 20); // es Spanish 0x0a
newPosixIDmap[14].initialize(0x0425, "et_EE"); // et Estonian 0x25
newPosixIDmap[15].initialize(0x042d, "eu_ES"); // eu Basque 0x2d
newPosixIDmap[16].initialize(0x0429, "fa_IR"); // fa Farsi 0x29
newPosixIDmap[17].initialize(0x040b, "fi_FI"); // fi Finnish 0x0b
newPosixIDmap[18].initialize(0x0438, "fo_FO"); // fo Faroese 0x38
newPosixIDmap[19].initialize(0x0c, "fr", 6); // fr French 0x0c
newPosixIDmap[20].initialize(0x0447, "gu_IN"); // gu Gujarati 0x47
newPosixIDmap[21].initialize(0x040d, "he_IL"); // he Hebrew (formerly iw) 0x0d
newPosixIDmap[22].initialize(0x0439, "hi_IN"); // hi Hindi 0x39
newPosixIDmap[23].initialize(0x041a, "hr_HR"); // hr Croatian 0x1a
newPosixIDmap[24].initialize(0x040e, "hu_HU"); // hu Hungarian 0x0e
newPosixIDmap[25].initialize(0x042b, "hy_AM"); // hy Armenian 0x2b
newPosixIDmap[26].initialize(0x0421, "id_ID"); // id Indonesian (formerly in) 0x21
newPosixIDmap[27].initialize(0x0421, "in_ID"); // in Indonesian 0x21
newPosixIDmap[28].initialize(0x040f, "is_IS"); // is Icelandic 0x0f
newPosixIDmap[29].initialize(0x10, "it", 2); // it Italian 0x10
newPosixIDmap[30].initialize(0x040d, "iw_IL"); // iw Hebrew 0x0d
newPosixIDmap[31].initialize(0x0411, "ja_JP"); // ja Japanese 0x11
newPosixIDmap[32].initialize(0x0437, "ka_GE"); // ka Georgian 0x37
newPosixIDmap[33].initialize(0x043f, "kk_KZ"); // kk Kazakh 0x3f
newPosixIDmap[34].initialize(0x044b, "kn_IN"); // kn Kannada 0x4b
newPosixIDmap[35].initialize(0x12, "ko", 2); // ko Korean 0x12
newPosixIDmap[36].initialize(0x0457, "kok_IN"); // kok Konkani 0x57
newPosixIDmap[37].initialize(0x0460, "ks_IN"); // ks Kashmiri 0x60
newPosixIDmap[38].initialize(0x0427, "lt_LT"); // lt Lithuanian 0x27
newPosixIDmap[39].initialize(0x0426, "lv_LV"); // lv Latvian, Lettish 0x26
newPosixIDmap[40].initialize(0x042f, "mk_MK"); // mk Macedonian 0x2f
newPosixIDmap[41].initialize(0x044c, "ml_IN"); // ml Malayalam 0x4c
newPosixIDmap[42].initialize(0x0458, "mni_IN"); // mni Manipuri 0x58
newPosixIDmap[43].initialize(0x044e, "mr_IN"); // mr Marathi 0x4e
newPosixIDmap[44].initialize(0x3e, "ms", 2); // ms Malay 0x3e
newPosixIDmap[45].initialize(0x61, "ne", 2); // ne Nepali 0x61
newPosixIDmap[46].initialize(0x13, "nl", 2); // nl Dutch 0x13
newPosixIDmap[47].initialize(0x14, "no", 2); // no Norwegian 0x14
newPosixIDmap[48].initialize(0x0448, "or_IN"); // or Oriya 0x48
newPosixIDmap[49].initialize(0x0446, "pa_IN"); // pa Punjabi 0x46
newPosixIDmap[50].initialize(0x0415, "pl_PL"); // pl Polish 0x15
newPosixIDmap[51].initialize(0x16, "pt", 2); // pt Portuguese 0x16
newPosixIDmap[52].initialize(0x0418, "ro_RO"); // ro Romanian 0x18
newPosixIDmap[53].initialize(0x00, "root"); // root 0x00
newPosixIDmap[54].initialize(0x0419, "ru_RU"); // ru Russian 0x19
newPosixIDmap[55].initialize(0x044f, "sa_IN"); // sa Sanskrit 0x4f
newPosixIDmap[56].initialize(0x0459, "sd_IN"); // sd Sindhi 0x59
newPosixIDmap[57].initialize(0x081a, "sh_YU"); // sh Serbo-Croatian 0x1a
newPosixIDmap[58].initialize(0x041b, "sk_SK"); // sk Slovak 0x1b
newPosixIDmap[59].initialize(0x0424, "sl_SI"); // sl Slovenian 0x24
newPosixIDmap[60].initialize(0x041c, "sq_AL"); // sq Albanian 0x1c
newPosixIDmap[61].initialize(0x0c1a, "sr_YU"); // sr Serbian 0x1a
newPosixIDmap[62].initialize(0x1d, "sv_SE", 2); // sv Swedish 0x1d
newPosixIDmap[63].initialize(0x0441, "sw"); // sw Swahili 0x41
newPosixIDmap[64].initialize(0x0449, "ta_IN"); // ta Tamil 0x49
newPosixIDmap[65].initialize(0x044a, "te_IN"); // te Telugu 0x4a
newPosixIDmap[66].initialize(0x041e, "th_TH"); // th Thai 0x1e
newPosixIDmap[67].initialize(0x041f, "tr_TR"); // tr Turkish 0x1f
newPosixIDmap[68].initialize(0x0444, "tt_RU"); // tt Tatar 0x44
newPosixIDmap[69].initialize(0x0422, "uk_UA"); // uk Ukrainian 0x22
newPosixIDmap[70].initialize(0x20, "ur", 2); // ur Urdu 0x20
newPosixIDmap[71].initialize(0x43, "uz_UZ", 2); // uz Uzbek 0x43
newPosixIDmap[72].initialize(0x042a, "vi_VN"); // vi Vietnamese 0x2a
newPosixIDmap[73].initialize(0x04, "zh", 5); // zh Chinese 0x04
newPosixIDmap[1].addRegion(0x3801, "ar_AE");
newPosixIDmap[1].addRegion(0x3c01, "ar_BH");
newPosixIDmap[1].addRegion(0x1401, "ar_DZ");
newPosixIDmap[1].addRegion(0x0c01, "ar_EG");
newPosixIDmap[1].addRegion(0x0801, "ar_IQ");
newPosixIDmap[1].addRegion(0x2c01, "ar_JO");
newPosixIDmap[1].addRegion(0x3401, "ar_KW");
newPosixIDmap[1].addRegion(0x3001, "ar_LB");
newPosixIDmap[1].addRegion(0x1001, "ar_LY");
newPosixIDmap[1].addRegion(0x1801, "ar_MA");
newPosixIDmap[1].addRegion(0x2001, "ar_OM");
newPosixIDmap[1].addRegion(0x4001, "ar_QA");
newPosixIDmap[1].addRegion(0x0401, "ar_SA");
newPosixIDmap[1].addRegion(0x2801, "ar_SY");
newPosixIDmap[1].addRegion(0x1c01, "ar_TN");
newPosixIDmap[1].addRegion(0x2401, "ar_YE");
newPosixIDmap[3].addRegion(0x082c, "az_AZ_C");
newPosixIDmap[3].addRegion(0x042c, "az_AZ_L");
newPosixIDmap[10].addRegion(0x0c07, "de_AT");
newPosixIDmap[10].addRegion(0x0807, "de_CH");
newPosixIDmap[10].addRegion(0x0407, "de_DE");
newPosixIDmap[10].addRegion(0x1407, "de_LI");
newPosixIDmap[10].addRegion(0x1007, "de_LU");
newPosixIDmap[12].addRegion(0x0c09, "en_AU");
newPosixIDmap[12].addRegion(0x2809, "en_BZ");
newPosixIDmap[12].addRegion(0x1009, "en_CA");
newPosixIDmap[12].addRegion(0x0809, "en_GB");
newPosixIDmap[12].addRegion(0x1809, "en_IE");
newPosixIDmap[12].addRegion(0x2009, "en_JM");
newPosixIDmap[12].addRegion(0x1409, "en_NZ");
newPosixIDmap[12].addRegion(0x3409, "en_PH");
newPosixIDmap[12].addRegion(0x2C09, "en_TT");
newPosixIDmap[12].addRegion(0x0409, "en_US");
newPosixIDmap[12].addRegion(0x2409, "en_VI");
newPosixIDmap[12].addRegion(0x1c09, "en_ZA");
newPosixIDmap[12].addRegion(0x3009, "en_ZW");
newPosixIDmap[13].addRegion(0x2c0a, "es_AR");
newPosixIDmap[13].addRegion(0x400a, "es_BO");
newPosixIDmap[13].addRegion(0x340a, "es_CL");
newPosixIDmap[13].addRegion(0x240a, "es_CO");
newPosixIDmap[13].addRegion(0x140a, "es_CR");
newPosixIDmap[13].addRegion(0x1c0a, "es_DO");
newPosixIDmap[13].addRegion(0x300a, "es_EC");
newPosixIDmap[13].addRegion(0x0c0a, "es_ES");
newPosixIDmap[13].addRegion(0x040a, "es_ES_T");
newPosixIDmap[13].addRegion(0x100a, "es_GT");
newPosixIDmap[13].addRegion(0x480a, "es_HN");
newPosixIDmap[13].addRegion(0x080a, "es_MX");
newPosixIDmap[13].addRegion(0x4c0a, "es_NI");
newPosixIDmap[13].addRegion(0x180a, "es_PA");
newPosixIDmap[13].addRegion(0x280a, "es_PE");
newPosixIDmap[13].addRegion(0x500a, "es_PR");
newPosixIDmap[13].addRegion(0x3c0a, "es_PY");
newPosixIDmap[13].addRegion(0x440a, "es_SV");
newPosixIDmap[13].addRegion(0x380a, "es_UY");
newPosixIDmap[13].addRegion(0x200a, "es_VE");
newPosixIDmap[19].addRegion(0x080c, "fr_BE");
newPosixIDmap[19].addRegion(0x0c0c, "fr_CA");
newPosixIDmap[19].addRegion(0x100c, "fr_CH");
newPosixIDmap[19].addRegion(0x040c, "fr_FR");
newPosixIDmap[19].addRegion(0x140c, "fr_LU");
newPosixIDmap[19].addRegion(0x180c, "fr_MC");
newPosixIDmap[29].addRegion(0x0810, "it_CH");
newPosixIDmap[29].addRegion(0x0410, "it_IT");
newPosixIDmap[35].addRegion(0x0812, "ko_KP");
newPosixIDmap[35].addRegion(0x0412, "ko_KR");
newPosixIDmap[44].addRegion(0x083e, "ms_BN"); // Brunei Darussalam
newPosixIDmap[44].addRegion(0x043e, "ms_MY"); // Malaysia
newPosixIDmap[45].addRegion(0x0861, "ne_IN"); // India
newPosixIDmap[45].addRegion(0x0461, "ne_NP"); // Nepal?
newPosixIDmap[46].addRegion(0x0813, "nl_BE");
newPosixIDmap[46].addRegion(0x0413, "nl_NL");
newPosixIDmap[47].addRegion(0x0414, "no_NO");
newPosixIDmap[47].addRegion(0x0814, "no_NO_NY");
newPosixIDmap[51].addRegion(0x0416, "pt_BR");
newPosixIDmap[51].addRegion(0x0816, "pt_PT");
newPosixIDmap[62].addRegion(0x081d, "sv_FI");
newPosixIDmap[62].addRegion(0x041d, "sv_SE");
newPosixIDmap[70].addRegion(0x0820, "ur_IN");
newPosixIDmap[70].addRegion(0x0420, "ur_PK");
newPosixIDmap[71].addRegion(0x0843, "uz_UZ_C");
newPosixIDmap[71].addRegion(0x0443, "uz_UZ_L");
newPosixIDmap[73].addRegion(0x0804, "zh_CN");
newPosixIDmap[73].addRegion(0x0c04, "zh_HK");
newPosixIDmap[73].addRegion(0x1404, "zh_MO");
newPosixIDmap[73].addRegion(0x1004, "zh_SG");
newPosixIDmap[73].addRegion(0x0404, "zh_TW");*/
// This must be static
static ILcidPosixMap localPosixIDmap[] = {
ILCID_POSIX_MAP(af), // af Afrikaans 0x36
ILCID_POSIX_MAP(ar), // ar Arabic 0x01
ILCID_POSIX_MAP(as), // as Assamese 0x4d
ILCID_POSIX_MAP(az), // az Azerbaijani 0x2c
ILCID_POSIX_MAP(be), // be Byelorussian 0x23
ILCID_POSIX_MAP(bg), // bg Bulgarian 0x02
ILCID_POSIX_MAP(bn), // bn Bengali; Bangla 0x45
ILCID_POSIX_MAP(ca), // ca Catalan 0x03
ILCID_POSIX_MAP(cs), // cs Czech 0x05
ILCID_POSIX_MAP(da), // da Danish 0x06
ILCID_POSIX_MAP(de), // de German 0x07
ILCID_POSIX_MAP(el), // el Greek 0x08
ILCID_POSIX_MAP(en), // en English 0x09
ILCID_POSIX_MAP(es), // es Spanish 0x0a
ILCID_POSIX_MAP(et), // et Estonian 0x25
ILCID_POSIX_MAP(eu), // eu Basque 0x2d
ILCID_POSIX_MAP(fa), // fa Farsi 0x29
ILCID_POSIX_MAP(fi), // fi Finnish 0x0b
ILCID_POSIX_MAP(fo), // fo Faroese 0x38
ILCID_POSIX_MAP(fr), // fr French 0x0c
ILCID_POSIX_MAP(gu), // gu Gujarati 0x47
ILCID_POSIX_MAP(he), // he Hebrew (formerly iw) 0x0d
ILCID_POSIX_MAP(hi), // hi Hindi 0x39
ILCID_POSIX_MAP(hr), // hr Croatian 0x1a
ILCID_POSIX_MAP(hu), // hu Hungarian 0x0e
ILCID_POSIX_MAP(hy), // hy Armenian 0x2b
ILCID_POSIX_MAP(id), // id Indonesian (formerly in) 0x21
// ILCID_POSIX_MAP(in_ID), // in Indonesian 0x21
ILCID_POSIX_MAP(is), // is Icelandic 0x0f
ILCID_POSIX_MAP(it), // it Italian 0x10
ILCID_POSIX_MAP(iw), // iw Hebrew (should be removed)0x0d
ILCID_POSIX_MAP(ja), // ja Japanese 0x11
ILCID_POSIX_MAP(ka), // ka Georgian 0x37
ILCID_POSIX_MAP(kk), // kk Kazakh 0x3f
ILCID_POSIX_MAP(kn), // kn Kannada 0x4b
ILCID_POSIX_MAP(ko), // ko Korean 0x12
ILCID_POSIX_MAP(kok), // kok Konkani 0x57
ILCID_POSIX_MAP(ks), // ks Kashmiri 0x60
ILCID_POSIX_MAP(lt), // lt Lithuanian 0x27
ILCID_POSIX_MAP(lv), // lv Latvian, Lettish 0x26
ILCID_POSIX_MAP(mk), // mk Macedonian 0x2f
ILCID_POSIX_MAP(ml), // ml Malayalam 0x4c
ILCID_POSIX_MAP(mni), // mni Manipuri 0x58
ILCID_POSIX_MAP(mr), // mr Marathi 0x4e
ILCID_POSIX_MAP(ms), // ms Malay 0x3e
ILCID_POSIX_MAP(mt), // mt Maltese 0x3a
ILCID_POSIX_MAP(nb), // no Norwegian 0x14
ILCID_POSIX_MAP(ne), // ne Nepali 0x61
ILCID_POSIX_MAP(nl), // nl Dutch 0x13
ILCID_POSIX_MAP(nn), // no Norwegian 0x14
ILCID_POSIX_MAP(no), // no Norwegian 0x14
ILCID_POSIX_MAP(or), // or Oriya 0x48
ILCID_POSIX_MAP(pa), // pa Punjabi 0x46
ILCID_POSIX_MAP(pl), // pl Polish 0x15
ILCID_POSIX_MAP(pt), // pt Portuguese 0x16
ILCID_POSIX_MAP(ro), // ro Romanian 0x18
ILCID_POSIX_MAP(root), // root 0x00
ILCID_POSIX_MAP(ru), // ru Russian 0x19
ILCID_POSIX_MAP(sa), // sa Sanskrit 0x4f
ILCID_POSIX_MAP(sd), // sd Sindhi 0x59
ILCID_POSIX_MAP(sh), // sh Serbo-Croatian 0x1a
ILCID_POSIX_MAP(sk), // sk Slovak 0x1b
ILCID_POSIX_MAP(sl), // sl Slovenian 0x24
ILCID_POSIX_MAP(sq), // sq Albanian 0x1c
ILCID_POSIX_MAP(sr), // sr Serbian 0x1a
ILCID_POSIX_MAP(sv), // sv Swedish 0x1d
ILCID_POSIX_MAP(sw), // sw Swahili 0x41
ILCID_POSIX_MAP(ta), // ta Tamil 0x49
ILCID_POSIX_MAP(te), // te Telugu 0x4a
ILCID_POSIX_MAP(th), // th Thai 0x1e
ILCID_POSIX_MAP(tr), // tr Turkish 0x1f
ILCID_POSIX_MAP(tt), // tt Tatar 0x44
ILCID_POSIX_MAP(uk), // uk Ukrainian 0x22
ILCID_POSIX_MAP(ur), // ur Urdu 0x20
ILCID_POSIX_MAP(uz), // uz Uzbek 0x43
ILCID_POSIX_MAP(vi), // vi Vietnamese 0x2a
ILCID_POSIX_MAP(zh), // zh Chinese 0x04
};
{
Mutex m;
if (!PosixIDmap)
{
// This assignment is okay because the local variable is static too.
PosixIDmap = localPosixIDmap;
LocaleCount = sizeof(localPosixIDmap)/sizeof(ILcidPosixMap);
WildCard = "??_??";
}
}
}
uint32_t IGlobalLocales::LocaleCount = sizeof(PosixIDmap)/sizeof(ILcidPosixMap);
ILcidPosixMap *IGlobalLocales::PosixIDmap = NULL;
const char *IGlobalLocales::WildCard = "??_??";
//////////////////////////////////////
//
// LCID --> POSIX
//
/////////////////////////////////////
const char*
IGlobalLocales::convertToPosix(uint32_t hostid, UErrorCode *status)
{
uint16_t langID = LANGUAGE_LCID(hostid);
uint32_t index;
initializeMapRegions();
for (index = 0; index < LocaleCount; index++)
{
if (langID == PosixIDmap[index].regionMaps->hostID)
{
return PosixIDmap[index].posixID(hostid);
}
}
//no match found
*status = U_ILLEGAL_ARGUMENT_ERROR;
return WildCard;
}
U_CFUNC const char *
T_convertToPosix(uint32_t hostid, UErrorCode* status)
{
return IGlobalLocales::convertToPosix(hostid, status);
}
//////////////////////////////////////
//
// POSIX --> LCID
//
/////////////////////////////////////
uint32_t
IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
{
initializeMapRegions();
uint32_t low = 0;
uint32_t mid;
uint32_t high = LocaleCount - 1;
int32_t compVal;
char langID[ULOC_FULLNAME_CAPACITY];
// Check for incomplete id.
if (!posixID || uprv_strlen(posixID) < 2)
return 0;
uloc_getLanguage(posixID, langID, sizeof(langID), status);
if (U_FAILURE(*status)) {
return 0;
}
//Binary search for the map entry
while (low <= high) {
mid = (low + high) / 2;
compVal = uprv_strcmp(langID, PosixIDmap[mid].regionMaps->posixID);
if (compVal < 0)
high = mid - 1;
else if (compVal > 0)
low = mid + 1;
else // found match!
return PosixIDmap[mid].hostID(posixID);
if (mid == 0) // not found
break;
}
// no match found
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0; // return international (root)
}
/* Assumes Posix IDs are sorted alphabetically
*/
uint32_t
ILcidPosixMap::hostID(const char* posixID) const
{
UErrorCode status = U_ZERO_ERROR;
char hostID[ULOC_FULLNAME_CAPACITY];
char *hostPtr = hostID;
uint32_t value;
int32_t hostLen = (int32_t)(strlen(posixID));
int32_t size, hostSize;
// Check for incomplete id. All LCIDs have a default country,
// and a 0x0400 in 0xFC00 indicates a default country.
// So Windows may not like hostLangID without a default
// country.
if (!numRegions || hostLen < 5)
return regionMaps->hostID;
if (hostLen >= ULOC_FULLNAME_CAPACITY)
hostLen = ULOC_FULLNAME_CAPACITY - 1;
// We do this because the posixID may have a '-' separator and
// incorrect string case
hostSize = uloc_getLanguage(posixID,
hostID,
ULOC_LANG_CAPACITY + 1,
&status);
if (U_SUCCESS(status))
{
hostPtr += hostSize;
hostPtr[-1] = '_';
size = uloc_getCountry(posixID,
hostPtr,
ULOC_COUNTRY_CAPACITY + 1,
&status);
hostSize += size - 1;
if (U_SUCCESS(status) && hostSize < hostLen)
{
hostPtr += size;
hostPtr[-1] = '_';
uloc_getVariant(posixID, hostPtr, hostLen - size, &status);
}
}
// Try to find it the first time.
value = searchPosixIDmap(hostID, &status);
if (U_SUCCESS(status)) {
return value;
}
// Couldn't find it. Cut off the last part of the locale
while (hostPtr > hostID && *hostPtr != '_')
{
hostPtr--;
}
if (*hostPtr == '_')
{
*hostPtr = 0;
}
// Try it again without the last part of the locale
status = U_ZERO_ERROR;
value = searchPosixIDmap(hostID, &status);
if (U_SUCCESS(status)) {
return value;
}
// No match found. Return the language
return regionMaps->hostID;
}
/**
* Searches for a Windows LCID
*
* @param posixid the Posix style locale id.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
* no equivalent Windows LCID.
* @return the LCID
*/
uint32_t
ILcidPosixMap::searchPosixIDmap(const char* posixID, UErrorCode* status) const
{
uint32_t low = 1;
uint32_t mid;
uint32_t high = numRegions;
int32_t compVal;
// Binary search for the map entry
// The element at index 0 is always the POSIX wild card,
// so start search at index 1.
while (low <= high) {
mid = (low + high) / 2;
compVal = uprv_strcmp(posixID, regionMaps[mid].posixID);
if (compVal < 0)
high = mid - 1;
else if (compVal > 0)
low = mid + 1;
else // found match!
return regionMaps[mid].hostID;
}
//no match found
*status = U_ILLEGAL_ARGUMENT_ERROR;
return regionMaps->hostID;
}
const char*
ILcidPosixMap::posixID(uint32_t hostID) const
{
uint32_t i;
for (i = 0; i <= numRegions; i++)
{
if (regionMaps[i].hostID == hostID)
{
return regionMaps[i].posixID;
}
}
// If you get here, then no matching region was found,
// so return the language id with the wild card region.
return regionMaps[0].posixID;
}
#endif