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