Home | History | Annotate | Download | only in common
      1 /*
      2  **********************************************************************
      3  *   Copyright (C) 1997-2010, International Business Machines
      4  *   Corporation and others.  All Rights Reserved.
      5  **********************************************************************
      6 *
      7 * File locid.cpp
      8 *
      9 * Created by: Richard Gillam
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   02/11/97    aliu        Changed gLocPath to fgDataDirectory and added
     15 *                           methods to get and set it.
     16 *   04/02/97    aliu        Made operator!= inline; fixed return value
     17 *                           of getName().
     18 *   04/15/97    aliu        Cleanup for AIX/Win32.
     19 *   04/24/97    aliu        Numerous changes per code review.
     20 *   08/18/98    stephen     Changed getDisplayName()
     21 *                           Added SIMPLIFIED_CHINESE, TRADITIONAL_CHINESE
     22 *                           Added getISOCountries(), getISOLanguages(),
     23 *                           getLanguagesForCountry()
     24 *   03/16/99    bertrand    rehaul.
     25 *   07/21/99    stephen     Added U_CFUNC setDefault
     26 *   11/09/99    weiv        Added const char * getName() const;
     27 *   04/12/00    srl         removing unicodestring api's and cached hash code
     28 *   08/10/01    grhoten     Change the static Locales to accessor functions
     29 ******************************************************************************
     30 */
     31 
     32 
     33 #include "unicode/locid.h"
     34 #include "unicode/uloc.h"
     35 #include "umutex.h"
     36 #include "uassert.h"
     37 #include "cmemory.h"
     38 #include "cstring.h"
     39 #include "uhash.h"
     40 #include "ucln_cmn.h"
     41 
     42 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
     43 
     44 typedef enum ELocalePos {
     45     eENGLISH,
     46     eFRENCH,
     47     eGERMAN,
     48     eITALIAN,
     49     eJAPANESE,
     50     eKOREAN,
     51     eCHINESE,
     52 
     53     eFRANCE,
     54     eGERMANY,
     55     eITALY,
     56     eJAPAN,
     57     eKOREA,
     58     eCHINA,      /* Alias for PRC */
     59     eTAIWAN,
     60     eUK,
     61     eUS,
     62     eCANADA,
     63     eCANADA_FRENCH,
     64     eROOT,
     65 
     66 
     67     //eDEFAULT,
     68     eMAX_LOCALES
     69 } ELocalePos;
     70 
     71 U_CFUNC int32_t locale_getKeywords(const char *localeID,
     72             char prev,
     73             char *keywords, int32_t keywordCapacity,
     74             char *values, int32_t valuesCapacity, int32_t *valLen,
     75             UBool valuesToo,
     76             UErrorCode *status);
     77 
     78 static U_NAMESPACE_QUALIFIER Locale *gLocaleCache         = NULL;
     79 static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale       = NULL;
     80 static UHashtable                   *gDefaultLocalesHashT = NULL;
     81 
     82 U_CDECL_BEGIN
     83 //
     84 // Deleter function for Locales owned by the default Locale hash table/
     85 //
     86 static void U_CALLCONV
     87 deleteLocale(void *obj) {
     88     delete (U_NAMESPACE_QUALIFIER Locale *) obj;
     89 }
     90 
     91 static UBool U_CALLCONV locale_cleanup(void)
     92 {
     93     U_NAMESPACE_USE
     94 
     95     if (gLocaleCache) {
     96         delete [] gLocaleCache;
     97         gLocaleCache = NULL;
     98     }
     99 
    100     if (gDefaultLocalesHashT) {
    101         uhash_close(gDefaultLocalesHashT);   // Automatically deletes all elements, using deleter func.
    102         gDefaultLocalesHashT = NULL;
    103     }
    104     else if (gDefaultLocale) {
    105         // The cache wasn't created, and only one default locale was created.
    106         delete gDefaultLocale;
    107     }
    108     gDefaultLocale = NULL;
    109 
    110     return TRUE;
    111 }
    112 U_CDECL_END
    113 
    114 U_NAMESPACE_BEGIN
    115 //
    116 //  locale_set_default_internal.
    117 //
    118 void locale_set_default_internal(const char *id)
    119 {
    120     UErrorCode   status = U_ZERO_ERROR;
    121     UBool canonicalize = FALSE;
    122 
    123     // If given a NULL string for the locale id, grab the default
    124     //   name from the system.
    125     //   (Different from most other locale APIs, where a null name means use
    126     //    the current ICU default locale.)
    127     if (id == NULL) {
    128         umtx_lock(NULL);
    129         id = uprv_getDefaultLocaleID();
    130         umtx_unlock(NULL);
    131         canonicalize = TRUE; // always canonicalize host ID
    132     }
    133 
    134     // put the locale id into a canonical form,
    135     //   in preparation for looking up this locale in the hash table of
    136     //   already-created locale objects.
    137     //
    138     status = U_ZERO_ERROR;
    139     char localeNameBuf[512];
    140 
    141     if (canonicalize) {
    142         uloc_canonicalize(id, localeNameBuf, sizeof(localeNameBuf)-1, &status);
    143     } else {
    144         uloc_getName(id, localeNameBuf, sizeof(localeNameBuf)-1, &status);
    145     }
    146     localeNameBuf[sizeof(localeNameBuf)-1] = 0;  // Force null termination in event of
    147                                                  //   a long name filling the buffer.
    148                                                  //   (long names are truncated.)
    149 
    150     // Lazy creation of the hash table itself, if needed.
    151     UBool isOnlyLocale;
    152     UMTX_CHECK(NULL, (gDefaultLocale == NULL), isOnlyLocale);
    153     if (isOnlyLocale) {
    154         // We haven't seen this locale id before.
    155         // Create a new Locale object for it.
    156         Locale *newFirstDefault = new Locale(Locale::eBOGUS);
    157         if (newFirstDefault == NULL) {
    158             // No way to report errors from here.
    159             return;
    160         }
    161         newFirstDefault->init(localeNameBuf, FALSE);
    162         umtx_lock(NULL);
    163         if (gDefaultLocale == NULL) {
    164             gDefaultLocale = newFirstDefault;  // Assignment to gDefaultLocale must happen inside mutex
    165             newFirstDefault = NULL;
    166             ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
    167         }
    168         // Else some other thread raced us through here, and set the new Locale.
    169         // Use the hash table next.
    170         umtx_unlock(NULL);
    171         if (newFirstDefault == NULL) {
    172             // We were successful in setting the locale, and we were the first one to set it.
    173             return;
    174         }
    175         // else start using the hash table.
    176     }
    177 
    178     // Lazy creation of the hash table itself, if needed.
    179     UBool hashTableNeedsInit;
    180     UMTX_CHECK(NULL, (gDefaultLocalesHashT == NULL), hashTableNeedsInit);
    181     if (hashTableNeedsInit) {
    182         status = U_ZERO_ERROR;
    183         UHashtable *tHashTable = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
    184         if (U_FAILURE(status)) {
    185             return;
    186         }
    187         uhash_setValueDeleter(tHashTable, deleteLocale);
    188         umtx_lock(NULL);
    189         if (gDefaultLocalesHashT == NULL) {
    190             gDefaultLocalesHashT = tHashTable;
    191             ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
    192         } else {
    193             uhash_close(tHashTable);
    194             hashTableNeedsInit = FALSE;
    195         }
    196         umtx_unlock(NULL);
    197     }
    198 
    199     // Hash table lookup, key is the locale full name
    200     umtx_lock(NULL);
    201     Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf);
    202     if (newDefault != NULL) {
    203         // We have the requested locale in the hash table already.
    204         // Just set it as default.  Inside the mutex lock, for those troublesome processors.
    205         gDefaultLocale = newDefault;
    206         umtx_unlock(NULL);
    207     } else {
    208         umtx_unlock(NULL);
    209         // We haven't seen this locale id before.
    210         // Create a new Locale object for it.
    211         newDefault = new Locale(Locale::eBOGUS);
    212         if (newDefault == NULL) {
    213             // No way to report errors from here.
    214             return;
    215         }
    216         newDefault->init(localeNameBuf, FALSE);
    217 
    218         // Add newly created Locale to the hash table of default Locales
    219         const char *key = newDefault->getName();
    220         U_ASSERT(uprv_strcmp(key, localeNameBuf) == 0);
    221         umtx_lock(NULL);
    222         Locale *hashTableVal = (Locale *)uhash_get(gDefaultLocalesHashT, key);
    223         if (hashTableVal == NULL) {
    224             if (hashTableNeedsInit) {
    225                 // This is the second request to set the locale.
    226                 // Cache the first one.
    227                 uhash_put(gDefaultLocalesHashT, (void *)gDefaultLocale->getName(), gDefaultLocale, &status);
    228             }
    229             uhash_put(gDefaultLocalesHashT, (void *)key, newDefault, &status);
    230             gDefaultLocale = newDefault;
    231             // ignore errors from hash table insert.  (Couldn't do anything anyway)
    232             // We can still set the default Locale,
    233             //  it just wont be cached, and will eventually leak.
    234         } else {
    235             // Some other thread raced us through here, and got the new Locale
    236             //   into the hash table before us.  Use that one.
    237             gDefaultLocale = hashTableVal;  // Assignment to gDefaultLocale must happen inside mutex
    238             delete newDefault;
    239         }
    240         umtx_unlock(NULL);
    241     }
    242 }
    243 U_NAMESPACE_END
    244 
    245 /* sfb 07/21/99 */
    246 U_CFUNC void
    247 locale_set_default(const char *id)
    248 {
    249     U_NAMESPACE_USE
    250     locale_set_default_internal(id);
    251 }
    252 /* end */
    253 
    254 U_CFUNC const char *
    255 locale_get_default(void)
    256 {
    257     U_NAMESPACE_USE
    258 
    259     return Locale::getDefault().getName();
    260 }
    261 
    262 
    263 U_NAMESPACE_BEGIN
    264 
    265 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale)
    266 
    267 /*Character separating the posix id fields*/
    268 // '_'
    269 // In the platform codepage.
    270 #define SEP_CHAR '_'
    271 
    272 Locale::~Locale()
    273 {
    274     /*if fullName is on the heap, we free it*/
    275     if (fullName != fullNameBuffer)
    276     {
    277         uprv_free(fullName);
    278         fullName = NULL;
    279     }
    280     if (baseName && baseName != baseNameBuffer) {
    281         uprv_free(baseName);
    282         baseName = NULL;
    283     }
    284 }
    285 
    286 Locale::Locale()
    287     : UObject(), fullName(fullNameBuffer), baseName(NULL)
    288 {
    289     init(NULL, FALSE);
    290 }
    291 
    292 /*
    293  * Internal constructor to allow construction of a locale object with
    294  *   NO side effects.   (Default constructor tries to get
    295  *   the default locale.)
    296  */
    297 Locale::Locale(Locale::ELocaleType)
    298     : UObject(), fullName(fullNameBuffer), baseName(NULL)
    299 {
    300     setToBogus();
    301 }
    302 
    303 
    304 Locale::Locale( const   char * newLanguage,
    305                 const   char * newCountry,
    306                 const   char * newVariant,
    307                 const   char * newKeywords)
    308     : UObject(), fullName(fullNameBuffer), baseName(NULL)
    309 {
    310     if( (newLanguage==NULL) && (newCountry == NULL) && (newVariant == NULL) )
    311     {
    312         init(NULL, FALSE); /* shortcut */
    313     }
    314     else
    315     {
    316         MaybeStackArray<char, ULOC_FULLNAME_CAPACITY> togo;
    317         int32_t size = 0;
    318         int32_t lsize = 0;
    319         int32_t csize = 0;
    320         int32_t vsize = 0;
    321         int32_t ksize = 0;
    322         char    *p;
    323 
    324         // Calculate the size of the resulting string.
    325 
    326         // Language
    327         if ( newLanguage != NULL )
    328         {
    329             lsize = (int32_t)uprv_strlen(newLanguage);
    330             size = lsize;
    331         }
    332 
    333         // _Country
    334         if ( newCountry != NULL )
    335         {
    336             csize = (int32_t)uprv_strlen(newCountry);
    337             size += csize;
    338         }
    339 
    340         // _Variant
    341         if ( newVariant != NULL )
    342         {
    343             // remove leading _'s
    344             while(newVariant[0] == SEP_CHAR)
    345             {
    346                 newVariant++;
    347             }
    348 
    349             // remove trailing _'s
    350             vsize = (int32_t)uprv_strlen(newVariant);
    351             while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) )
    352             {
    353                 vsize--;
    354             }
    355         }
    356 
    357         if( vsize > 0 )
    358         {
    359             size += vsize;
    360         }
    361 
    362         // Separator rules:
    363         if ( vsize > 0 )
    364         {
    365             size += 2;  // at least: __v
    366         }
    367         else if ( csize > 0 )
    368         {
    369             size += 1;  // at least: _v
    370         }
    371 
    372         if ( newKeywords != NULL)
    373         {
    374             ksize = (int32_t)uprv_strlen(newKeywords);
    375             size += ksize + 1;
    376         }
    377 
    378 
    379         //  NOW we have the full locale string..
    380 
    381         /*if the whole string is longer than our internal limit, we need
    382         to go to the heap for temporary buffers*/
    383         if (size >= togo.getCapacity())
    384         {
    385             // If togo_heap could not be created, initialize with default settings.
    386             if (togo.resize(size+1) == NULL) {
    387                 init(NULL, FALSE);
    388             }
    389         }
    390 
    391         togo[0] = 0;
    392 
    393         // Now, copy it back.
    394         p = togo.getAlias();
    395         if ( lsize != 0 )
    396         {
    397             uprv_strcpy(p, newLanguage);
    398             p += lsize;
    399         }
    400 
    401         if ( ( vsize != 0 ) || (csize != 0) )  // at least:  __v
    402         {                                      //            ^
    403             *p++ = SEP_CHAR;
    404         }
    405 
    406         if ( csize != 0 )
    407         {
    408             uprv_strcpy(p, newCountry);
    409             p += csize;
    410         }
    411 
    412         if ( vsize != 0)
    413         {
    414             *p++ = SEP_CHAR; // at least: __v
    415 
    416             uprv_strncpy(p, newVariant, vsize);  // Must use strncpy because
    417             p += vsize;                          // of trimming (above).
    418             *p = 0; // terminate
    419         }
    420 
    421         if ( ksize != 0)
    422         {
    423             if (uprv_strchr(newKeywords, '=')) {
    424                 *p++ = '@'; /* keyword parsing */
    425             }
    426             else {
    427                 *p++ = '_'; /* Variant parsing with a script */
    428                 if ( vsize == 0) {
    429                     *p++ = '_'; /* No country found */
    430                 }
    431             }
    432             uprv_strcpy(p, newKeywords);
    433             p += ksize;
    434         }
    435 
    436         // Parse it, because for example 'language' might really be a complete
    437         // string.
    438         init(togo.getAlias(), FALSE);
    439     }
    440 }
    441 
    442 Locale::Locale(const Locale &other)
    443     : UObject(other), fullName(fullNameBuffer), baseName(NULL)
    444 {
    445     *this = other;
    446 }
    447 
    448 Locale &Locale::operator=(const Locale &other)
    449 {
    450     if (this == &other) {
    451         return *this;
    452     }
    453 
    454     if (&other == NULL) {
    455         this->setToBogus();
    456         return *this;
    457     }
    458 
    459     /* Free our current storage */
    460     if(fullName != fullNameBuffer) {
    461         uprv_free(fullName);
    462         fullName = fullNameBuffer;
    463     }
    464 
    465     /* Allocate the full name if necessary */
    466     if(other.fullName != other.fullNameBuffer) {
    467         fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)+1));
    468         if (fullName == NULL) {
    469             return *this;
    470         }
    471     }
    472     /* Copy the full name */
    473     uprv_strcpy(fullName, other.fullName);
    474 
    475     /* baseName is the cached result of getBaseName.  if 'other' has a
    476        baseName and it fits in baseNameBuffer, then copy it. otherwise set
    477        it to NULL, and let the user lazy-create it (in getBaseName) if they
    478        want it. */
    479     if(baseName && baseName != baseNameBuffer) {
    480         uprv_free(baseName);
    481     }
    482     baseName = NULL;
    483 
    484     if(other.baseName == other.baseNameBuffer) {
    485         uprv_strcpy(baseNameBuffer, other.baseNameBuffer);
    486         baseName = baseNameBuffer;
    487     }
    488 
    489     /* Copy the language and country fields */
    490     uprv_strcpy(language, other.language);
    491     uprv_strcpy(script, other.script);
    492     uprv_strcpy(country, other.country);
    493 
    494     /* The variantBegin is an offset, just copy it */
    495     variantBegin = other.variantBegin;
    496     fIsBogus = other.fIsBogus;
    497     return *this;
    498 }
    499 
    500 Locale *
    501 Locale::clone() const {
    502     return new Locale(*this);
    503 }
    504 
    505 UBool
    506 Locale::operator==( const   Locale& other) const
    507 {
    508     return (uprv_strcmp(other.fullName, fullName) == 0);
    509 }
    510 
    511 /*This function initializes a Locale from a C locale ID*/
    512 Locale& Locale::init(const char* localeID, UBool canonicalize)
    513 {
    514     fIsBogus = FALSE;
    515     /* Free our current storage */
    516     if(fullName != fullNameBuffer) {
    517         uprv_free(fullName);
    518         fullName = fullNameBuffer;
    519     }
    520 
    521     if(baseName && baseName != baseNameBuffer) {
    522         uprv_free(baseName);
    523         baseName = NULL;
    524     }
    525 
    526     // not a loop:
    527     // just an easy way to have a common error-exit
    528     // without goto and without another function
    529     do {
    530         char *separator;
    531         char *field[5] = {0};
    532         int32_t fieldLen[5] = {0};
    533         int32_t fieldIdx;
    534         int32_t variantField;
    535         int32_t length;
    536         UErrorCode err;
    537 
    538         if(localeID == NULL) {
    539             // not an error, just set the default locale
    540             return *this = getDefault();
    541         }
    542 
    543         /* preset all fields to empty */
    544         language[0] = script[0] = country[0] = 0;
    545 
    546         // "canonicalize" the locale ID to ICU/Java format
    547         err = U_ZERO_ERROR;
    548         length = canonicalize ?
    549             uloc_canonicalize(localeID, fullName, sizeof(fullNameBuffer), &err) :
    550             uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
    551 
    552         if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameBuffer)) {
    553             /*Go to heap for the fullName if necessary*/
    554             fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
    555             if(fullName == 0) {
    556                 fullName = fullNameBuffer;
    557                 break; // error: out of memory
    558             }
    559             err = U_ZERO_ERROR;
    560             length = canonicalize ?
    561                 uloc_canonicalize(localeID, fullName, length+1, &err) :
    562                 uloc_getName(localeID, fullName, length+1, &err);
    563         }
    564         if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
    565             /* should never occur */
    566             break;
    567         }
    568 
    569         variantBegin = length;
    570 
    571         /* after uloc_getName/canonicalize() we know that only '_' are separators */
    572         separator = field[0] = fullName;
    573         fieldIdx = 1;
    574         while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) && fieldIdx < (int32_t)(sizeof(field)/sizeof(field[0]))-1) {
    575             field[fieldIdx] = separator + 1;
    576             fieldLen[fieldIdx-1] = (int32_t)(separator - field[fieldIdx-1]);
    577             fieldIdx++;
    578         }
    579         // variant may contain @foo or .foo POSIX cruft; remove it
    580         separator = uprv_strchr(field[fieldIdx-1], '@');
    581         char* sep2 = uprv_strchr(field[fieldIdx-1], '.');
    582         if (separator!=NULL || sep2!=NULL) {
    583             if (separator==NULL || (sep2!=NULL && separator > sep2)) {
    584                 separator = sep2;
    585             }
    586             fieldLen[fieldIdx-1] = (int32_t)(separator - field[fieldIdx-1]);
    587         } else {
    588             fieldLen[fieldIdx-1] = length - (int32_t)(field[fieldIdx-1] - fullName);
    589         }
    590 
    591         if (fieldLen[0] >= (int32_t)(sizeof(language))
    592             || (fieldLen[1] == 4 && fieldLen[2] >= (int32_t)(sizeof(country)))
    593             || (fieldLen[1] != 4 && fieldLen[1] >= (int32_t)(sizeof(country))))
    594         {
    595             break; // error: one of the fields is too long
    596         }
    597 
    598         variantField = 2; /* Usually the 2nd one, except when a script is used. */
    599         if (fieldLen[0] > 0) {
    600             /* We have a language */
    601             uprv_memcpy(language, fullName, fieldLen[0]);
    602             language[fieldLen[0]] = 0;
    603         }
    604         if (fieldLen[1] == 4) {
    605             /* We have at least a script */
    606             uprv_memcpy(script, field[1], fieldLen[1]);
    607             script[fieldLen[1]] = 0;
    608             variantField = 3;
    609             if (fieldLen[2] > 0) {
    610                 /* We have a country */
    611                 uprv_memcpy(country, field[2], fieldLen[2]);
    612                 country[fieldLen[2]] = 0;
    613             }
    614         }
    615         else if (fieldLen[1] > 0) {
    616             /* We have a country and no script */
    617             uprv_memcpy(country, field[1], fieldLen[1]);
    618             country[fieldLen[1]] = 0;
    619         }
    620         if (variantField > 0 && fieldLen[variantField] > 0) {
    621             /* We have a variant */
    622             variantBegin = (int32_t)(field[variantField] - fullName);
    623         }
    624 
    625         // successful end of init()
    626         return *this;
    627     } while(0); /*loop doesn't iterate*/
    628 
    629     // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
    630     setToBogus();
    631 
    632     return *this;
    633 }
    634 
    635 int32_t
    636 Locale::hashCode() const
    637 {
    638     UHashTok hashKey;
    639     hashKey.pointer = fullName;
    640     return uhash_hashChars(hashKey);
    641 }
    642 
    643 void
    644 Locale::setToBogus() {
    645     /* Free our current storage */
    646     if(fullName != fullNameBuffer) {
    647         uprv_free(fullName);
    648         fullName = fullNameBuffer;
    649     }
    650     if(baseName && baseName != baseNameBuffer) {
    651         uprv_free(baseName);
    652         baseName = NULL;
    653     }
    654     *fullNameBuffer = 0;
    655     *language = 0;
    656     *script = 0;
    657     *country = 0;
    658     fIsBogus = TRUE;
    659 }
    660 
    661 const Locale& U_EXPORT2
    662 Locale::getDefault()
    663 {
    664     const Locale *retLocale;
    665     UMTX_CHECK(NULL, gDefaultLocale, retLocale);
    666     if (retLocale == NULL) {
    667         locale_set_default_internal(NULL);
    668         umtx_lock(NULL);
    669         // Need a mutex  in case some other thread set a new
    670         // default inbetween when we set and when we get the new default.  For
    671         // processors with weak memory coherency, we might not otherwise see all
    672         // of the newly created new default locale.
    673         retLocale = gDefaultLocale;
    674         umtx_unlock(NULL);
    675     }
    676     return *retLocale;
    677 }
    678 
    679 
    680 
    681 void U_EXPORT2
    682 Locale::setDefault( const   Locale&     newLocale,
    683                             UErrorCode&  status)
    684 {
    685     if (U_FAILURE(status)) {
    686         return;
    687     }
    688 
    689     /* Set the default from the full name string of the supplied locale.
    690      * This is a convenient way to access the default locale caching mechanisms.
    691      */
    692     const char *localeID = newLocale.getName();
    693     locale_set_default_internal(localeID);
    694 }
    695 
    696 Locale U_EXPORT2
    697 Locale::createFromName (const char *name)
    698 {
    699     if (name) {
    700         Locale l("");
    701         l.init(name, FALSE);
    702         return l;
    703     }
    704     else {
    705         return getDefault();
    706     }
    707 }
    708 
    709 Locale U_EXPORT2
    710 Locale::createCanonical(const char* name) {
    711     Locale loc("");
    712     loc.init(name, TRUE);
    713     return loc;
    714 }
    715 
    716 const char *
    717 Locale::getISO3Language() const
    718 {
    719     return uloc_getISO3Language(fullName);
    720 }
    721 
    722 
    723 const char *
    724 Locale::getISO3Country() const
    725 {
    726     return uloc_getISO3Country(fullName);
    727 }
    728 
    729 /**
    730  * Return the LCID value as specified in the "LocaleID" resource for this
    731  * locale.  The LocaleID must be expressed as a hexadecimal number, from
    732  * one to four digits.  If the LocaleID resource is not present, or is
    733  * in an incorrect format, 0 is returned.  The LocaleID is for use in
    734  * Windows (it is an LCID), but is available on all platforms.
    735  */
    736 uint32_t
    737 Locale::getLCID() const
    738 {
    739     return uloc_getLCID(fullName);
    740 }
    741 
    742 const char* const* U_EXPORT2 Locale::getISOCountries()
    743 {
    744     return uloc_getISOCountries();
    745 }
    746 
    747 const char* const* U_EXPORT2 Locale::getISOLanguages()
    748 {
    749     return uloc_getISOLanguages();
    750 }
    751 
    752 // Set the locale's data based on a posix id.
    753 void Locale::setFromPOSIXID(const char *posixID)
    754 {
    755     init(posixID, TRUE);
    756 }
    757 
    758 const Locale & U_EXPORT2
    759 Locale::getRoot(void)
    760 {
    761     return getLocale(eROOT);
    762 }
    763 
    764 const Locale & U_EXPORT2
    765 Locale::getEnglish(void)
    766 {
    767     return getLocale(eENGLISH);
    768 }
    769 
    770 const Locale & U_EXPORT2
    771 Locale::getFrench(void)
    772 {
    773     return getLocale(eFRENCH);
    774 }
    775 
    776 const Locale & U_EXPORT2
    777 Locale::getGerman(void)
    778 {
    779     return getLocale(eGERMAN);
    780 }
    781 
    782 const Locale & U_EXPORT2
    783 Locale::getItalian(void)
    784 {
    785     return getLocale(eITALIAN);
    786 }
    787 
    788 const Locale & U_EXPORT2
    789 Locale::getJapanese(void)
    790 {
    791     return getLocale(eJAPANESE);
    792 }
    793 
    794 const Locale & U_EXPORT2
    795 Locale::getKorean(void)
    796 {
    797     return getLocale(eKOREAN);
    798 }
    799 
    800 const Locale & U_EXPORT2
    801 Locale::getChinese(void)
    802 {
    803     return getLocale(eCHINESE);
    804 }
    805 
    806 const Locale & U_EXPORT2
    807 Locale::getSimplifiedChinese(void)
    808 {
    809     return getLocale(eCHINA);
    810 }
    811 
    812 const Locale & U_EXPORT2
    813 Locale::getTraditionalChinese(void)
    814 {
    815     return getLocale(eTAIWAN);
    816 }
    817 
    818 
    819 const Locale & U_EXPORT2
    820 Locale::getFrance(void)
    821 {
    822     return getLocale(eFRANCE);
    823 }
    824 
    825 const Locale & U_EXPORT2
    826 Locale::getGermany(void)
    827 {
    828     return getLocale(eGERMANY);
    829 }
    830 
    831 const Locale & U_EXPORT2
    832 Locale::getItaly(void)
    833 {
    834     return getLocale(eITALY);
    835 }
    836 
    837 const Locale & U_EXPORT2
    838 Locale::getJapan(void)
    839 {
    840     return getLocale(eJAPAN);
    841 }
    842 
    843 const Locale & U_EXPORT2
    844 Locale::getKorea(void)
    845 {
    846     return getLocale(eKOREA);
    847 }
    848 
    849 const Locale & U_EXPORT2
    850 Locale::getChina(void)
    851 {
    852     return getLocale(eCHINA);
    853 }
    854 
    855 const Locale & U_EXPORT2
    856 Locale::getPRC(void)
    857 {
    858     return getLocale(eCHINA);
    859 }
    860 
    861 const Locale & U_EXPORT2
    862 Locale::getTaiwan(void)
    863 {
    864     return getLocale(eTAIWAN);
    865 }
    866 
    867 const Locale & U_EXPORT2
    868 Locale::getUK(void)
    869 {
    870     return getLocale(eUK);
    871 }
    872 
    873 const Locale & U_EXPORT2
    874 Locale::getUS(void)
    875 {
    876     return getLocale(eUS);
    877 }
    878 
    879 const Locale & U_EXPORT2
    880 Locale::getCanada(void)
    881 {
    882     return getLocale(eCANADA);
    883 }
    884 
    885 const Locale & U_EXPORT2
    886 Locale::getCanadaFrench(void)
    887 {
    888     return getLocale(eCANADA_FRENCH);
    889 }
    890 
    891 const Locale &
    892 Locale::getLocale(int locid)
    893 {
    894     Locale *localeCache = getLocaleCache();
    895     U_ASSERT((locid < eMAX_LOCALES)&&(locid>=0));
    896     if (localeCache == NULL) {
    897         // Failure allocating the locale cache.
    898         //   The best we can do is return a NULL reference.
    899         locid = 0;
    900     }
    901     return localeCache[locid]; /*operating on NULL*/
    902 }
    903 
    904 /*
    905 This function is defined this way in order to get around static
    906 initialization and static destruction.
    907  */
    908 Locale *
    909 Locale::getLocaleCache(void)
    910 {
    911     umtx_lock(NULL);
    912     UBool needInit = (gLocaleCache == NULL);
    913     umtx_unlock(NULL);
    914 
    915     if (needInit) {
    916         Locale *tLocaleCache = new Locale[(int)eMAX_LOCALES];
    917         if (tLocaleCache == NULL) {
    918             return NULL;
    919         }
    920 	tLocaleCache[eROOT]          = Locale("");
    921         tLocaleCache[eENGLISH]       = Locale("en");
    922         tLocaleCache[eFRENCH]        = Locale("fr");
    923         tLocaleCache[eGERMAN]        = Locale("de");
    924         tLocaleCache[eITALIAN]       = Locale("it");
    925         tLocaleCache[eJAPANESE]      = Locale("ja");
    926         tLocaleCache[eKOREAN]        = Locale("ko");
    927         tLocaleCache[eCHINESE]       = Locale("zh");
    928         tLocaleCache[eFRANCE]        = Locale("fr", "FR");
    929         tLocaleCache[eGERMANY]       = Locale("de", "DE");
    930         tLocaleCache[eITALY]         = Locale("it", "IT");
    931         tLocaleCache[eJAPAN]         = Locale("ja", "JP");
    932         tLocaleCache[eKOREA]         = Locale("ko", "KR");
    933         tLocaleCache[eCHINA]         = Locale("zh", "CN");
    934         tLocaleCache[eTAIWAN]        = Locale("zh", "TW");
    935         tLocaleCache[eUK]            = Locale("en", "GB");
    936         tLocaleCache[eUS]            = Locale("en", "US");
    937         tLocaleCache[eCANADA]        = Locale("en", "CA");
    938         tLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA");
    939 
    940         umtx_lock(NULL);
    941         if (gLocaleCache == NULL) {
    942             gLocaleCache = tLocaleCache;
    943             tLocaleCache = NULL;
    944             ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
    945         }
    946         umtx_unlock(NULL);
    947         if (tLocaleCache) {
    948             delete [] tLocaleCache;  // Fancy array delete will destruct each member.
    949         }
    950     }
    951     return gLocaleCache;
    952 }
    953 
    954 class KeywordEnumeration : public StringEnumeration {
    955 private:
    956     char *keywords;
    957     char *current;
    958     int32_t length;
    959     UnicodeString currUSKey;
    960     static const char fgClassID;/* Warning this is used beyond the typical RTTI usage. */
    961 
    962 public:
    963     static UClassID U_EXPORT2 getStaticClassID(void) { return (UClassID)&fgClassID; }
    964     virtual UClassID getDynamicClassID(void) const { return getStaticClassID(); }
    965 public:
    966     KeywordEnumeration(const char *keys, int32_t keywordLen, int32_t currentIndex, UErrorCode &status)
    967         : keywords((char *)&fgClassID), current((char *)&fgClassID), length(0) {
    968         if(U_SUCCESS(status) && keywordLen != 0) {
    969             if(keys == NULL || keywordLen < 0) {
    970                 status = U_ILLEGAL_ARGUMENT_ERROR;
    971             } else {
    972                 keywords = (char *)uprv_malloc(keywordLen+1);
    973                 if (keywords == NULL) {
    974                     status = U_MEMORY_ALLOCATION_ERROR;
    975                 }
    976                 else {
    977                     uprv_memcpy(keywords, keys, keywordLen);
    978                     keywords[keywordLen] = 0;
    979                     current = keywords + currentIndex;
    980                     length = keywordLen;
    981                 }
    982             }
    983         }
    984     }
    985 
    986     virtual ~KeywordEnumeration() {
    987         uprv_free(keywords);
    988     }
    989 
    990     virtual StringEnumeration * clone() const
    991     {
    992         UErrorCode status = U_ZERO_ERROR;
    993         return new KeywordEnumeration(keywords, length, (int32_t)(current - keywords), status);
    994     }
    995 
    996     virtual int32_t count(UErrorCode &/*status*/) const {
    997         char *kw = keywords;
    998         int32_t result = 0;
    999         while(*kw) {
   1000             result++;
   1001             kw += uprv_strlen(kw)+1;
   1002         }
   1003         return result;
   1004     }
   1005 
   1006     virtual const char* next(int32_t* resultLength, UErrorCode& status) {
   1007         const char* result;
   1008         int32_t len;
   1009         if(U_SUCCESS(status) && *current != 0) {
   1010             result = current;
   1011             len = (int32_t)uprv_strlen(current);
   1012             current += len+1;
   1013             if(resultLength != NULL) {
   1014                 *resultLength = len;
   1015             }
   1016         } else {
   1017             if(resultLength != NULL) {
   1018                 *resultLength = 0;
   1019             }
   1020             result = NULL;
   1021         }
   1022         return result;
   1023     }
   1024 
   1025     virtual const UnicodeString* snext(UErrorCode& status) {
   1026         int32_t resultLength = 0;
   1027         const char *s = next(&resultLength, status);
   1028         return setChars(s, resultLength, status);
   1029     }
   1030 
   1031     virtual void reset(UErrorCode& /*status*/) {
   1032         current = keywords;
   1033     }
   1034 };
   1035 
   1036 const char KeywordEnumeration::fgClassID = '\0';
   1037 
   1038 StringEnumeration *
   1039 Locale::createKeywords(UErrorCode &status) const
   1040 {
   1041     char keywords[256];
   1042     int32_t keywordCapacity = 256;
   1043     StringEnumeration *result = NULL;
   1044 
   1045     const char* variantStart = uprv_strchr(fullName, '@');
   1046     const char* assignment = uprv_strchr(fullName, '=');
   1047     if(variantStart) {
   1048         if(assignment > variantStart) {
   1049             int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status);
   1050             if(keyLen) {
   1051                 result = new KeywordEnumeration(keywords, keyLen, 0, status);
   1052             }
   1053         } else {
   1054             status = U_INVALID_FORMAT_ERROR;
   1055         }
   1056     }
   1057     return result;
   1058 }
   1059 
   1060 int32_t
   1061 Locale::getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, UErrorCode &status) const
   1062 {
   1063     return uloc_getKeywordValue(fullName, keywordName, buffer, bufLen, &status);
   1064 }
   1065 
   1066 void
   1067 Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status)
   1068 {
   1069     uloc_setKeywordValue(keywordName, keywordValue, fullName, ULOC_FULLNAME_CAPACITY, &status);
   1070 }
   1071 
   1072 const char *
   1073 Locale::getBaseName() const
   1074 {
   1075     // lazy init
   1076     UErrorCode status = U_ZERO_ERROR;
   1077     // semantically const
   1078     if(baseName == 0) {
   1079         ((Locale *)this)->baseName = ((Locale *)this)->baseNameBuffer;
   1080         int32_t baseNameSize = uloc_getBaseName(fullName, baseName, ULOC_FULLNAME_CAPACITY, &status);
   1081         if(baseNameSize >= ULOC_FULLNAME_CAPACITY) {
   1082             ((Locale *)this)->baseName = (char *)uprv_malloc(sizeof(char) * baseNameSize + 1);
   1083             if (baseName == NULL) {
   1084                 return baseName;
   1085             }
   1086             uloc_getBaseName(fullName, baseName, baseNameSize+1, &status);
   1087         }
   1088         baseName[baseNameSize] = 0;
   1089 
   1090         // the computation of variantBegin leaves it equal to the length
   1091         // of fullName if there is no variant.  It should instead be
   1092         // the length of the baseName.  Patch around this for now.
   1093         if (variantBegin == (int32_t)uprv_strlen(fullName)) {
   1094           ((Locale*)this)->variantBegin = baseNameSize;
   1095         }
   1096     }
   1097     return baseName;
   1098 }
   1099 
   1100 //eof
   1101 U_NAMESPACE_END
   1102