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