~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/common/locid.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 **********************************************************************
3
 
 *   Copyright (C) 1997-2001, 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 "mutex.h"
36
 
#include "cmemory.h"
37
 
#include "cstring.h"
38
 
#include "uhash.h"
39
 
#include "ucln_cmn.h"
40
 
 
41
 
U_NAMESPACE_BEGIN
42
 
 
43
 
static Locale*  availableLocaleList = NULL;
44
 
static int32_t  availableLocaleListCount;
45
 
typedef enum ELocalePos {
46
 
    eENGLISH,
47
 
    eFRENCH,
48
 
    eGERMAN,
49
 
    eITALIAN,
50
 
    eJAPANESE,
51
 
    eKOREAN,
52
 
    eCHINESE,
53
 
 
54
 
    eFRANCE,
55
 
    eGERMANY,
56
 
    eITALY,
57
 
    eJAPAN,
58
 
    eKOREA,
59
 
    eCHINA,      /* Alias for PRC */
60
 
    eTAIWAN,
61
 
    eUK,
62
 
    eUS,
63
 
    eCANADA,
64
 
    eCANADA_FRENCH,
65
 
 
66
 
 
67
 
    eDEFAULT,
68
 
    eMAX_LOCALES
69
 
} ELocalePos;
70
 
 
71
 
/* Use void * to make it properly aligned */
72
 
/* Add 1 for rounding */
73
 
static void *gByteLocaleCache[(eMAX_LOCALES + 1) * sizeof(Locale) / sizeof(void*)];
74
 
 
75
 
static Locale *gLocaleCache = NULL;
76
 
 
77
 
U_NAMESPACE_END
78
 
 
79
 
UBool
80
 
locale_cleanup(void)
81
 
{
82
 
    U_NAMESPACE_USE
83
 
 
84
 
    if (availableLocaleList) {
85
 
        delete []availableLocaleList;
86
 
        availableLocaleList = NULL;
87
 
    }
88
 
    availableLocaleListCount = 0;
89
 
    if (gLocaleCache) {
90
 
        gLocaleCache[eDEFAULT].~Locale();
91
 
        gLocaleCache = NULL;
92
 
    }
93
 
    return TRUE;
94
 
}
95
 
 
96
 
U_NAMESPACE_BEGIN
97
 
void locale_set_default_internal(const char *id)
98
 
{
99
 
    U_NAMESPACE_USE
100
 
 
101
 
#ifdef ICU_LOCID_USE_DEPRECATES
102
 
    Locale::fgDefaultLocale.init(id);
103
 
#else
104
 
if (gLocaleCache == NULL) {
105
 
        Locale::initLocaleCache();
106
 
    }
107
 
 
108
 
    {
109
 
        Mutex lock;
110
 
        gLocaleCache[eDEFAULT].init(id);
111
 
    }
112
 
#endif
113
 
}
114
 
U_NAMESPACE_END
115
 
 
116
 
/* sfb 07/21/99 */
117
 
U_CFUNC void
118
 
locale_set_default(const char *id)
119
 
{
120
 
    U_NAMESPACE_USE
121
 
 
122
 
    locale_set_default_internal(id);
123
 
}
124
 
/* end */
125
 
 
126
 
U_CFUNC const char *
127
 
locale_get_default(void)
128
 
{
129
 
    U_NAMESPACE_USE
130
 
 
131
 
    return Locale::getDefault().getName();
132
 
}
133
 
 
134
 
 
135
 
U_NAMESPACE_BEGIN
136
 
 
137
 
/*Character separating the posix id fields*/
138
 
// '_'
139
 
// In the platform codepage.
140
 
#define SEP_CHAR '_'
141
 
 
142
 
/**
143
 
 * static variables
144
 
 */
145
 
#ifdef ICU_LOCID_USE_DEPRECATES
146
 
Locale Locale::fgDefaultLocale;
147
 
 
148
 
/**
149
 
 * Constant definitions
150
 
 */
151
 
const Locale  Locale::ENGLISH("en");
152
 
const Locale  Locale::FRENCH("fr");
153
 
const Locale  Locale::GERMAN("de");
154
 
const Locale  Locale::ITALIAN("it");
155
 
const Locale  Locale::JAPANESE("ja");
156
 
const Locale  Locale::KOREAN("ko");
157
 
const Locale  Locale::CHINESE("zh");
158
 
const Locale  Locale::SIMPLIFIED_CHINESE("zh", "CN");
159
 
const Locale  Locale::TRADITIONAL_CHINESE("zh", "TW");
160
 
 
161
 
// Useful constant for country.
162
 
 
163
 
const Locale  Locale::FRANCE    ("fr", "FR");
164
 
const Locale  Locale::GERMANY   ("de", "DE");
165
 
const Locale  Locale::ITALY     ("it", "IT");
166
 
const Locale  Locale::JAPAN     ("ja", "JP");
167
 
const Locale  Locale::KOREA     ("ko", "KR");
168
 
const Locale  Locale::CHINA     ("zh", "CN");
169
 
const Locale  Locale::PRC       ("zh", "CN");
170
 
const Locale  Locale::TAIWAN    ("zh", "TW");
171
 
const Locale  Locale::UK        ("en", "GB");
172
 
const Locale  Locale::US        ("en", "US");
173
 
const Locale  Locale::CANADA    ("en", "CA");
174
 
const Locale  Locale::CANADA_FRENCH("fr", "CA");
175
 
 
176
 
#else
177
 
const Locale::LocaleProxy Locale::ENGLISH  = {eENGLISH};
178
 
const Locale::LocaleProxy Locale::FRENCH   = {eFRENCH};
179
 
const Locale::LocaleProxy Locale::GERMAN   = {eGERMAN};
180
 
const Locale::LocaleProxy Locale::ITALIAN  = {eITALIAN};
181
 
const Locale::LocaleProxy Locale::JAPANESE = {eJAPANESE};
182
 
const Locale::LocaleProxy Locale::KOREAN   = {eKOREAN};
183
 
const Locale::LocaleProxy Locale::CHINESE  = {eCHINESE};
184
 
const Locale::LocaleProxy Locale::SIMPLIFIED_CHINESE={eCHINA};
185
 
const Locale::LocaleProxy Locale::TRADITIONAL_CHINESE={eTAIWAN};
186
 
 
187
 
const Locale::LocaleProxy Locale::FRANCE   = {eFRANCE};
188
 
const Locale::LocaleProxy Locale::GERMANY  = {eGERMANY};
189
 
const Locale::LocaleProxy Locale::ITALY    = {eITALY};
190
 
const Locale::LocaleProxy Locale::JAPAN    = {eJAPAN};
191
 
const Locale::LocaleProxy Locale::KOREA    = {eKOREA};
192
 
const Locale::LocaleProxy Locale::CHINA    = {eCHINA};
193
 
const Locale::LocaleProxy Locale::PRC      = {eCHINA};
194
 
const Locale::LocaleProxy Locale::TAIWAN   = {eTAIWAN};
195
 
const Locale::LocaleProxy Locale::UK       = {eUK};
196
 
const Locale::LocaleProxy Locale::US       = {eUS};
197
 
const Locale::LocaleProxy Locale::CANADA   = {eCANADA};
198
 
const Locale::LocaleProxy Locale::CANADA_FRENCH={eCANADA_FRENCH};
199
 
 
200
 
Locale::LocaleProxy::operator const Locale&(void) const
201
 
{
202
 
    return Locale::getLocale(magicLocaleNumber);
203
 
}
204
 
 
205
 
#endif
206
 
 
207
 
Locale::~Locale()
208
 
{   
209
 
    /*if fullName is on the heap, we free it*/
210
 
    if (fullName != fullNameBuffer) 
211
 
    {
212
 
        uprv_free(fullName);
213
 
        fullName = NULL;
214
 
    }
215
 
}
216
 
 
217
 
Locale::Locale()
218
 
    : fullName(fullNameBuffer)
219
 
{
220
 
    init(NULL);
221
 
}
222
 
 
223
 
Locale::Locale( const   char * newLanguage, 
224
 
                const   char * newCountry, 
225
 
                const   char * newVariant) 
226
 
    : fullName(fullNameBuffer)
227
 
{
228
 
    if( (newLanguage==NULL) && (newCountry == NULL) && (newVariant == NULL) )
229
 
    {
230
 
        init(NULL); /* shortcut */
231
 
    }
232
 
    else
233
 
    {
234
 
        char togo_stack[ULOC_FULLNAME_CAPACITY];
235
 
        char *togo;
236
 
        char *togo_heap = NULL;
237
 
        int32_t size = 0;
238
 
        int32_t lsize = 0;
239
 
        int32_t csize = 0;
240
 
        int32_t vsize = 0;
241
 
        char    *p;
242
 
 
243
 
        // Calculate the size of the resulting string.
244
 
 
245
 
        // Language
246
 
        if ( newLanguage != NULL )
247
 
        {
248
 
            lsize = (int32_t)uprv_strlen(newLanguage);
249
 
            size = lsize;
250
 
        }
251
 
 
252
 
        // _Country
253
 
        if ( newCountry != NULL )
254
 
        {
255
 
            csize = (int32_t)uprv_strlen(newCountry);
256
 
            size += csize;
257
 
        }
258
 
 
259
 
        // _Variant
260
 
        if ( newVariant != NULL )
261
 
        {
262
 
            // remove leading _'s
263
 
            while(newVariant[0] == SEP_CHAR)
264
 
            {
265
 
                newVariant++;
266
 
            }
267
 
            
268
 
            // remove trailing _'s
269
 
            vsize = (int32_t)uprv_strlen(newVariant);
270
 
            while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) )
271
 
            {
272
 
                vsize--;
273
 
            }
274
 
        }
275
 
 
276
 
        if( vsize > 0 )
277
 
        {
278
 
            size += vsize;
279
 
        }
280
 
 
281
 
        // Separator rules:
282
 
        if ( vsize > 0 )
283
 
        {
284
 
            size += 2;  // at least: __v 
285
 
        }
286
 
        else if ( csize > 0 )
287
 
        {
288
 
            size += 1;  // at least: _v 
289
 
        }
290
 
 
291
 
        //  NOW we have the full locale string..
292
 
 
293
 
        /*if the whole string is longer than our internal limit, we need
294
 
        to go to the heap for temporary buffers*/
295
 
        if (size > ULOC_FULLNAME_CAPACITY)
296
 
        {
297
 
            togo_heap = (char *)uprv_malloc(sizeof(char)*(size+1));
298
 
            togo = togo_heap;
299
 
        }
300
 
        else
301
 
        {
302
 
            togo = togo_stack;
303
 
        }
304
 
 
305
 
        togo[0] = 0;
306
 
 
307
 
        // Now, copy it back.
308
 
        p = togo;
309
 
        if ( lsize != 0 )
310
 
        {
311
 
            uprv_strcpy(p, newLanguage);
312
 
            p += lsize;
313
 
        }
314
 
 
315
 
        if ( ( vsize != 0 ) || (csize != 0) )  // at least:  __v
316
 
        {                                      //            ^
317
 
            *p++ = SEP_CHAR;
318
 
        }
319
 
 
320
 
        if ( csize != 0 )
321
 
        { 
322
 
            uprv_strcpy(p, newCountry);
323
 
            p += csize;
324
 
        }
325
 
 
326
 
        if ( vsize != 0)
327
 
        {
328
 
            *p++ = SEP_CHAR; // at least: __v
329
 
 
330
 
            uprv_strncpy(p, newVariant, vsize);  // Must use strncpy because 
331
 
            p += vsize;                          // of trimming (above).
332
 
            *p = 0; // terminate
333
 
        }
334
 
 
335
 
        // Parse it, because for example 'language' might really be a complete
336
 
        // string.
337
 
        init(togo);
338
 
 
339
 
        if (togo_heap) {
340
 
            uprv_free(togo_heap);
341
 
        }
342
 
    }
343
 
}
344
 
 
345
 
Locale::Locale(const Locale &other)
346
 
    : fullName(fullNameBuffer)
347
 
{
348
 
    *this = other;
349
 
}
350
 
 
351
 
Locale &Locale::operator=(const Locale &other)
352
 
{
353
 
    /* Free our current storage */
354
 
    if(fullName != fullNameBuffer) {
355
 
        uprv_free(fullName);
356
 
        fullName = fullNameBuffer;
357
 
    }
358
 
 
359
 
    /* Allocate the full name if necessary */
360
 
    if(other.fullName != other.fullNameBuffer) {
361
 
        fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)+1));
362
 
    }
363
 
 
364
 
    /* Copy the full name */
365
 
    uprv_strcpy(fullName, other.fullName);
366
 
 
367
 
    /* Copy the language and country fields */
368
 
    uprv_strcpy(language, other.language);
369
 
    uprv_strcpy(country, other.country);
370
 
 
371
 
    /* The variantBegin is an offset into fullName, just copy it */
372
 
    variantBegin = other.variantBegin;
373
 
    fIsBogus = other.fIsBogus;
374
 
    return *this;
375
 
}
376
 
 
377
 
UBool
378
 
Locale::operator==( const   Locale& other) const
379
 
{
380
 
    return (uprv_strcmp(other.fullName, fullName) == 0);
381
 
}
382
 
 
383
 
/*This function initializes a Locale from a C locale ID*/
384
 
Locale& Locale::init(const char* localeID)
385
 
{
386
 
    fIsBogus = FALSE;
387
 
    /* Free our current storage */
388
 
    if(fullName != fullNameBuffer) {
389
 
        uprv_free(fullName);
390
 
        fullName = fullNameBuffer;
391
 
    }
392
 
 
393
 
    // not a loop:
394
 
    // just an easy way to have a common error-exit
395
 
    // without goto and without another function
396
 
    do {
397
 
        char *separator, *prev;
398
 
        int32_t length;
399
 
        UErrorCode err;
400
 
 
401
 
        if(localeID == NULL) {
402
 
            // not an error, just set the default locale
403
 
            break;
404
 
        }
405
 
 
406
 
        // "canonicalize" the locale ID to ICU/Java format
407
 
        err = U_ZERO_ERROR;
408
 
        length = uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
409
 
        if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
410
 
            /*Go to heap for the fullName if necessary*/
411
 
            fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
412
 
            if(fullName == 0) {
413
 
                fullName = fullNameBuffer;
414
 
                break;
415
 
            }
416
 
            err = U_ZERO_ERROR;
417
 
            length = uloc_getName(localeID, fullName, length + 1, &err);
418
 
        }
419
 
        if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
420
 
            /* should never occur */
421
 
            break;
422
 
        }
423
 
 
424
 
        /* preset all fields to empty */
425
 
        language[0] = country[0] = 0;
426
 
        variantBegin = uprv_strlen(fullName);
427
 
 
428
 
        /* after uloc_getName() we know that only '_' are separators */
429
 
        separator = uprv_strchr(fullName, SEP_CHAR);
430
 
        if(separator != 0) {
431
 
            /* there is a country field */
432
 
            length = separator - fullName;
433
 
            if(length > 0) {
434
 
                if(length >= (int32_t)sizeof(language)) {
435
 
                    break;
436
 
                }
437
 
                uprv_memcpy(language, fullName, length);
438
 
            }
439
 
            language[length] = 0;
440
 
 
441
 
            prev = separator + 1;
442
 
            separator = uprv_strchr(prev, SEP_CHAR);
443
 
            if(separator != 0) {
444
 
                /* there is a variant field */
445
 
                length = separator - prev;
446
 
                if(length > 0) {
447
 
                    if(length >= (int32_t)sizeof(country)) {
448
 
                        break;
449
 
                    }
450
 
                    uprv_memcpy(country, prev, length);
451
 
                }
452
 
                country[length] = 0;
453
 
 
454
 
                variantBegin = (separator + 1) - fullName;
455
 
            } else {
456
 
                /* variantBegin==strlen(fullName), length==strlen(language)==prev-1-fullName */
457
 
                if((variantBegin - length - 1) >= (int32_t)sizeof(country)) {
458
 
                    break;
459
 
                }
460
 
                uprv_strcpy(country, prev);
461
 
            }
462
 
        } else {
463
 
            /* variantBegin==strlen(fullName) */
464
 
            if(variantBegin >= (int32_t)sizeof(language)) {
465
 
                break;
466
 
            }
467
 
            uprv_strcpy(language, fullName);
468
 
        }
469
 
 
470
 
        // successful end of init()
471
 
        return *this;
472
 
    } while(0);
473
 
 
474
 
    if (gLocaleCache) {
475
 
        // when an error occurs, then set the default locale (there is no UErrorCode here)
476
 
        return *this = getLocale(eDEFAULT);
477
 
    }
478
 
    else {
479
 
        // Prevent any possible infinite recursion
480
 
        // for bad default Locale IDs
481
 
        return init("en");
482
 
    }
483
 
}
484
 
 
485
 
int32_t
486
 
Locale::hashCode() const 
487
 
{
488
 
    UHashTok hashKey;
489
 
    hashKey.pointer = fullName;
490
 
    return uhash_hashChars(hashKey);
491
 
}
492
 
 
493
 
void 
494
 
Locale::setToBogus() {
495
 
  /* Free our current storage */
496
 
  if(fullName != fullNameBuffer) {
497
 
      uprv_free(fullName);
498
 
      fullName = fullNameBuffer;
499
 
  }
500
 
  *fullNameBuffer = 0;
501
 
  *language = 0;
502
 
  *country = 0;
503
 
  fIsBogus = TRUE;
504
 
}
505
 
 
506
 
const Locale&
507
 
Locale::getDefault() 
508
 
{
509
 
#ifdef ICU_LOCID_USE_DEPRECATES
510
 
    return fgDefaultLocale;
511
 
#else
512
 
    return getLocale(eDEFAULT);
513
 
#endif
514
 
}
515
 
 
516
 
void 
517
 
Locale::setDefault( const   Locale&     newLocale, 
518
 
                            UErrorCode&  status) 
519
 
{
520
 
    if (U_FAILURE(status))
521
 
        return;
522
 
 
523
 
#ifdef ICU_LOCID_USE_DEPRECATES
524
 
    fgDefaultLocale = newLocale;
525
 
#else
526
 
    if (gLocaleCache == NULL) {
527
 
        initLocaleCache();
528
 
    }
529
 
 
530
 
    {
531
 
        Mutex lock;
532
 
        gLocaleCache[eDEFAULT] = newLocale;
533
 
    }
534
 
#endif
535
 
}
536
 
 
537
 
Locale
538
 
Locale::createFromName (const char *name)
539
 
{
540
 
    if (name) {
541
 
        Locale l;
542
 
        l.init(name);
543
 
        return l;
544
 
    }
545
 
    else {
546
 
        return getDefault();
547
 
    }
548
 
}
549
 
 
550
 
 
551
 
const char *
552
 
Locale::getISO3Language() const
553
 
{
554
 
    return uloc_getISO3Language(fullName);
555
 
}
556
 
 
557
 
 
558
 
const char *
559
 
Locale::getISO3Country() const
560
 
{
561
 
    return uloc_getISO3Country(fullName);
562
 
}
563
 
 
564
 
/**
565
 
 * Return the LCID value as specified in the "LocaleID" resource for this
566
 
 * locale.  The LocaleID must be expressed as a hexadecimal number, from
567
 
 * one to four digits.  If the LocaleID resource is not present, or is
568
 
 * in an incorrect format, 0 is returned.  The LocaleID is for use in
569
 
 * Windows (it is an LCID), but is available on all platforms.
570
 
 */
571
 
uint32_t 
572
 
Locale::getLCID() const
573
 
{
574
 
    return uloc_getLCID(fullName);
575
 
}
576
 
 
577
 
UnicodeString& 
578
 
Locale::getDisplayLanguage(UnicodeString& dispLang) const
579
 
{
580
 
    return this->getDisplayLanguage(getDefault(), dispLang);
581
 
}
582
 
 
583
 
/*We cannot make any assumptions on the size of the output display strings
584
 
* Yet, since we are calling through to a C API, we need to set limits on
585
 
* buffer size. For all the following getDisplay functions we first attempt
586
 
* to fill up a stack allocated buffer. If it is to small we heap allocated
587
 
* the exact buffer we need copy it to the UnicodeString and delete it*/
588
 
 
589
 
UnicodeString&
590
 
Locale::getDisplayLanguage(const Locale &displayLocale,
591
 
                           UnicodeString &result) const {
592
 
    UChar *buffer;
593
 
    UErrorCode errorCode=U_ZERO_ERROR;
594
 
    int32_t length;
595
 
 
596
 
    buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
597
 
    if(buffer==0) {
598
 
        result.truncate(0);
599
 
        return result;
600
 
    }
601
 
 
602
 
    length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
603
 
                                   buffer, result.getCapacity(),
604
 
                                   &errorCode);
605
 
    result.releaseBuffer(length);
606
 
 
607
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
608
 
        buffer=result.getBuffer(length);
609
 
        if(buffer==0) {
610
 
            result.truncate(0);
611
 
            return result;
612
 
        }
613
 
        errorCode=U_ZERO_ERROR;
614
 
        length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
615
 
                                       buffer, result.getCapacity(),
616
 
                                       &errorCode);
617
 
        result.releaseBuffer(length);
618
 
    }
619
 
 
620
 
    if(U_FAILURE(errorCode)) {
621
 
        result.truncate(0);
622
 
    }
623
 
 
624
 
    return result;
625
 
}
626
 
 
627
 
UnicodeString& 
628
 
Locale::getDisplayCountry(UnicodeString& dispCntry) const
629
 
{
630
 
    return this->getDisplayCountry(getDefault(), dispCntry);
631
 
}
632
 
 
633
 
UnicodeString&
634
 
Locale::getDisplayCountry(const Locale &displayLocale,
635
 
                          UnicodeString &result) const {
636
 
    UChar *buffer;
637
 
    UErrorCode errorCode=U_ZERO_ERROR;
638
 
    int32_t length;
639
 
 
640
 
    buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
641
 
    if(buffer==0) {
642
 
        result.truncate(0);
643
 
        return result;
644
 
    }
645
 
 
646
 
    length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
647
 
                                  buffer, result.getCapacity(),
648
 
                                  &errorCode);
649
 
    result.releaseBuffer(length);
650
 
 
651
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
652
 
        buffer=result.getBuffer(length);
653
 
        if(buffer==0) {
654
 
            result.truncate(0);
655
 
            return result;
656
 
        }
657
 
        errorCode=U_ZERO_ERROR;
658
 
        length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
659
 
                                      buffer, result.getCapacity(),
660
 
                                      &errorCode);
661
 
        result.releaseBuffer(length);
662
 
    }
663
 
 
664
 
    if(U_FAILURE(errorCode)) {
665
 
        result.truncate(0);
666
 
    }
667
 
 
668
 
    return result;
669
 
}
670
 
 
671
 
UnicodeString& 
672
 
Locale::getDisplayVariant(UnicodeString& dispVar) const
673
 
{
674
 
    return this->getDisplayVariant(getDefault(), dispVar);
675
 
}
676
 
 
677
 
UnicodeString&
678
 
Locale::getDisplayVariant(const Locale &displayLocale,
679
 
                          UnicodeString &result) const {
680
 
    UChar *buffer;
681
 
    UErrorCode errorCode=U_ZERO_ERROR;
682
 
    int32_t length;
683
 
 
684
 
    buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
685
 
    if(buffer==0) {
686
 
        result.truncate(0);
687
 
        return result;
688
 
    }
689
 
 
690
 
    length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
691
 
                                  buffer, result.getCapacity(),
692
 
                                  &errorCode);
693
 
    result.releaseBuffer(length);
694
 
 
695
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
696
 
        buffer=result.getBuffer(length);
697
 
        if(buffer==0) {
698
 
            result.truncate(0);
699
 
            return result;
700
 
        }
701
 
        errorCode=U_ZERO_ERROR;
702
 
        length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
703
 
                                      buffer, result.getCapacity(),
704
 
                                      &errorCode);
705
 
        result.releaseBuffer(length);
706
 
    }
707
 
 
708
 
    if(U_FAILURE(errorCode)) {
709
 
        result.truncate(0);
710
 
    }
711
 
 
712
 
    return result;
713
 
}
714
 
 
715
 
UnicodeString& 
716
 
Locale::getDisplayName( UnicodeString& name ) const
717
 
{
718
 
    return this->getDisplayName(getDefault(), name);
719
 
}
720
 
 
721
 
UnicodeString&
722
 
Locale::getDisplayName(const Locale &displayLocale,
723
 
                       UnicodeString &result) const {
724
 
    UChar *buffer;
725
 
    UErrorCode errorCode=U_ZERO_ERROR;
726
 
    int32_t length;
727
 
 
728
 
    buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
729
 
    if(buffer==0) {
730
 
        result.truncate(0);
731
 
        return result;
732
 
    }
733
 
 
734
 
    length=uloc_getDisplayName(fullName, displayLocale.fullName,
735
 
                               buffer, result.getCapacity(),
736
 
                               &errorCode);
737
 
    result.releaseBuffer(length);
738
 
 
739
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
740
 
        buffer=result.getBuffer(length);
741
 
        if(buffer==0) {
742
 
            result.truncate(0);
743
 
            return result;
744
 
        }
745
 
        errorCode=U_ZERO_ERROR;
746
 
        length=uloc_getDisplayName(fullName, displayLocale.fullName,
747
 
                                   buffer, result.getCapacity(),
748
 
                                   &errorCode);
749
 
        result.releaseBuffer(length);
750
 
    }
751
 
 
752
 
    if(U_FAILURE(errorCode)) {
753
 
        result.truncate(0);
754
 
    }
755
 
 
756
 
    return result;
757
 
}
758
 
const Locale*
759
 
Locale::getAvailableLocales(int32_t& count) 
760
 
{
761
 
    // for now, there is a hardcoded list, so just walk through that list and set it up.
762
 
    if (availableLocaleList == 0) {
763
 
        int32_t locCount = uloc_countAvailable();
764
 
        Locale *newLocaleList = new Locale[locCount];
765
 
 
766
 
        count = locCount;
767
 
 
768
 
        while(--locCount >= 0) {
769
 
            newLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
770
 
        }
771
 
 
772
 
        Mutex mutex;
773
 
        if(availableLocaleList != 0) {
774
 
            delete []newLocaleList;
775
 
        }
776
 
        else {
777
 
            availableLocaleListCount = count;
778
 
            availableLocaleList = newLocaleList;
779
 
        }
780
 
    }
781
 
    count = availableLocaleListCount;
782
 
    return availableLocaleList;
783
 
}
784
 
 
785
 
const char* const* Locale::getISOCountries()
786
 
{
787
 
    return uloc_getISOCountries();
788
 
}
789
 
 
790
 
const char* const* Locale::getISOLanguages()
791
 
{
792
 
    return uloc_getISOLanguages();
793
 
}
794
 
 
795
 
// Set the locale's data based on a posix id. 
796
 
void Locale::setFromPOSIXID(const char *posixID)
797
 
{
798
 
    init(posixID);
799
 
}
800
 
 
801
 
#ifndef ICU_LOCID_USE_DEPRECATES
802
 
const Locale &
803
 
Locale::getEnglish(void)
804
 
{
805
 
    return getLocale(eENGLISH);
806
 
}
807
 
 
808
 
const Locale &
809
 
Locale::getFrench(void)
810
 
{
811
 
    return getLocale(eFRENCH);
812
 
}
813
 
 
814
 
const Locale &
815
 
Locale::getGerman(void)
816
 
{
817
 
    return getLocale(eGERMAN);
818
 
}
819
 
 
820
 
const Locale &
821
 
Locale::getItalian(void)
822
 
{
823
 
    return getLocale(eITALIAN);
824
 
}
825
 
 
826
 
const Locale &
827
 
Locale::getJapanese(void)
828
 
{
829
 
    return getLocale(eJAPANESE);
830
 
}
831
 
 
832
 
const Locale &
833
 
Locale::getKorean(void)
834
 
{
835
 
    return getLocale(eKOREAN);
836
 
}
837
 
 
838
 
const Locale &
839
 
Locale::getChinese(void)
840
 
{
841
 
    return getLocale(eCHINESE);
842
 
}
843
 
 
844
 
const Locale &
845
 
Locale::getSimplifiedChinese(void)
846
 
{
847
 
    return getLocale(eCHINA);
848
 
}
849
 
 
850
 
const Locale &
851
 
Locale::getTraditionalChinese(void)
852
 
{
853
 
    return getLocale(eTAIWAN);
854
 
}
855
 
 
856
 
 
857
 
const Locale &
858
 
Locale::getFrance(void)
859
 
{
860
 
    return getLocale(eFRANCE);
861
 
}
862
 
 
863
 
const Locale &
864
 
Locale::getGermany(void)
865
 
{
866
 
    return getLocale(eGERMANY);
867
 
}
868
 
 
869
 
const Locale &
870
 
Locale::getItaly(void)
871
 
{
872
 
    return getLocale(eITALY);
873
 
}
874
 
 
875
 
const Locale &
876
 
Locale::getJapan(void)
877
 
{
878
 
    return getLocale(eJAPAN);
879
 
}
880
 
 
881
 
const Locale &
882
 
Locale::getKorea(void)
883
 
{
884
 
    return getLocale(eKOREA);
885
 
}
886
 
 
887
 
const Locale &
888
 
Locale::getChina(void)
889
 
{
890
 
    return getLocale(eCHINA);
891
 
}
892
 
 
893
 
const Locale &
894
 
Locale::getPRC(void)
895
 
{
896
 
    return getLocale(eCHINA);
897
 
}
898
 
 
899
 
const Locale &
900
 
Locale::getTaiwan(void)
901
 
{
902
 
    return getLocale(eTAIWAN);
903
 
}
904
 
 
905
 
const Locale &
906
 
Locale::getUK(void)
907
 
{
908
 
    return getLocale(eUK);
909
 
}
910
 
 
911
 
const Locale &
912
 
Locale::getUS(void)
913
 
{
914
 
    return getLocale(eUS);
915
 
}
916
 
 
917
 
const Locale &
918
 
Locale::getCanada(void)
919
 
{
920
 
    return getLocale(eCANADA);
921
 
}
922
 
 
923
 
const Locale &
924
 
Locale::getCanadaFrench(void)
925
 
{
926
 
    return getLocale(eCANADA_FRENCH);
927
 
}
928
 
 
929
 
const Locale &
930
 
Locale::getLocale(int locid)
931
 
{
932
 
    if (gLocaleCache) {
933
 
        return gLocaleCache[locid];
934
 
    }
935
 
 
936
 
    initLocaleCache();
937
 
 
938
 
    return gLocaleCache[locid];
939
 
}
940
 
 
941
 
/*
942
 
This function is defined this way in order to get around static
943
 
initialization and static destruction.
944
 
 */
945
 
void
946
 
Locale::initLocaleCache(void)
947
 
{
948
 
    const char *defaultLocale = uprv_getDefaultLocaleID();
949
 
    // Can't use empty parameters, or we'll call this function again.
950
 
    Locale newLocales[] = {
951
 
        Locale("en"),
952
 
        Locale("fr"),
953
 
        Locale("de"),
954
 
        Locale("it"),
955
 
        Locale("ja"),
956
 
        Locale("ko"),
957
 
        Locale("zh"),
958
 
        Locale("fr", "FR"),
959
 
        Locale("de", "DE"),
960
 
        Locale("it", "IT"),
961
 
        Locale("ja", "JP"),
962
 
        Locale("ko", "KR"),
963
 
        Locale("zh", "CN"),
964
 
        Locale("zh", "TW"),
965
 
        Locale("en", "GB"),
966
 
        Locale("en", "US"),
967
 
        Locale("en", "CA"),
968
 
        Locale("fr", "CA"),
969
 
        Locale(defaultLocale)
970
 
    };
971
 
    Locale *localeCache = (Locale *)(gByteLocaleCache);
972
 
 
973
 
    {
974
 
        Mutex lock;
975
 
        if (gLocaleCache != NULL) {
976
 
            return;
977
 
        }
978
 
        uprv_memcpy(gByteLocaleCache, newLocales, sizeof(newLocales));
979
 
 
980
 
        for (int idx = 0; idx < eMAX_LOCALES; idx++)
981
 
        {
982
 
            if (localeCache[idx].fullName == newLocales[idx].fullNameBuffer)
983
 
            {
984
 
                localeCache[idx].fullName = localeCache[idx].fullNameBuffer;
985
 
            }
986
 
            else
987
 
            {
988
 
                // Since we did a memcpy we need to make sure that the local
989
 
                // Locales do not destroy the memory of the permanent locales.
990
 
                //
991
 
                // This can be a memory leak for an extra long default locale,
992
 
                // but this code shouldn't normally get executed.
993
 
                localeCache[idx].fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(localeCache[idx].fullNameBuffer) + 1));
994
 
                uprv_strcpy(localeCache[idx].fullName, localeCache[idx].fullNameBuffer);
995
 
            }
996
 
        }
997
 
        gLocaleCache = localeCache;
998
 
    }
999
 
}
1000
 
 
1001
 
#endif
1002
 
 
1003
 
//eof
1004
 
U_NAMESPACE_END