2 **********************************************************************
3 * Copyright (C) 1997-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
9 * Created by: Richard Gillam
11 * Modification History:
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
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 ******************************************************************************
33 #include "unicode/locid.h"
34 #include "unicode/uloc.h"
42 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
44 static Locale
* availableLocaleList
= NULL
;
45 static int32_t availableLocaleListCount
;
46 typedef enum ELocalePos
{
60 eCHINA
, /* Alias for PRC */
72 U_CFUNC
int32_t locale_getKeywords(const char *localeID
,
74 char *keywords
, int32_t keywordCapacity
,
75 char *values
, int32_t valuesCapacity
, int32_t *valLen
,
79 static Locale
*gLocaleCache
= NULL
;
80 static const Locale
*gDefaultLocale
= NULL
;
81 static UHashtable
*gDefaultLocalesHashT
= NULL
;
85 // Deleter function for Locales owned by the default Locale hash table/
87 static void U_CALLCONV
88 deleteLocale(void *obj
) {
89 delete (Locale
*) obj
;
92 static UBool U_CALLCONV
locale_cleanup(void)
96 if (availableLocaleList
) {
97 delete []availableLocaleList
;
98 availableLocaleList
= NULL
;
100 availableLocaleListCount
= 0;
103 delete [] gLocaleCache
;
107 if (gDefaultLocalesHashT
) {
108 uhash_close(gDefaultLocalesHashT
); // Automatically deletes all elements, using deleter func.
109 gDefaultLocalesHashT
= NULL
;
111 gDefaultLocale
= NULL
;
118 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale
)
121 // locale_set_default_internal.
123 void locale_set_default_internal(const char *id
)
126 UErrorCode status
= U_ZERO_ERROR
;
127 UBool canonicalize
= FALSE
;
129 // If given a NULL string for the locale id, grab the default
130 // name from the system.
131 // (Different from most other locale APIs, where a null name means use
132 // the current ICU default locale.)
135 id
= uprv_getDefaultLocaleID();
137 canonicalize
= TRUE
; // always canonicalize host ID
140 // put the locale id into a canonical form,
141 // in preparation for looking up this locale in the hash table of
142 // already-created locale objects.
144 status
= U_ZERO_ERROR
;
145 char localeNameBuf
[512];
148 uloc_canonicalize(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
150 uloc_getName(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
152 localeNameBuf
[sizeof(localeNameBuf
)-1] = 0; // Force null termination in event of
153 // a long name filling the buffer.
154 // (long names are truncated.)
156 // Lazy creation of the hash table itself, if needed.
159 UBool hashTableNeedsInit
= (gDefaultLocalesHashT
== NULL
);
161 if (hashTableNeedsInit
) {
162 status
= U_ZERO_ERROR
;
163 UHashtable
*tHashTable
= uhash_open(uhash_hashChars
, uhash_compareChars
, &status
);
164 if (U_FAILURE(status
)) {
167 uhash_setValueDeleter(tHashTable
, deleteLocale
);
169 if (gDefaultLocalesHashT
== NULL
) {
170 gDefaultLocalesHashT
= tHashTable
;
171 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
175 uhash_close(tHashTable
);
179 // Hash table lookup, key is the locale full name
181 Locale
*newDefault
= (Locale
*)uhash_get(gDefaultLocalesHashT
, localeNameBuf
);
182 if (newDefault
!= NULL
) {
183 // We have the requested locale in the hash table already.
184 // Just set it as default. Inside the mutex lock, for those troublesome processors.
185 gDefaultLocale
= newDefault
;
189 // We haven't seen this locale id before.
190 // Create a new Locale object for it.
191 newDefault
= new Locale(Locale::eBOGUS
);
192 if (newDefault
== NULL
) {
193 // No way to report errors from here.
196 newDefault
->init(localeNameBuf
, FALSE
);
198 // Add newly created Locale to the hash table of default Locales
199 const char *key
= newDefault
->getName();
200 U_ASSERT(uprv_strcmp(key
, localeNameBuf
) == 0);
202 const Locale
*hashTableVal
= (const Locale
*)uhash_get(gDefaultLocalesHashT
, key
);
203 if (hashTableVal
== NULL
) {
204 uhash_put(gDefaultLocalesHashT
, (void *)key
, newDefault
, &status
);
205 gDefaultLocale
= newDefault
;
207 // ignore errors from hash table insert. (Couldn't do anything anyway)
208 // We can still set the default Locale,
209 // it just wont be cached, and will eventually leak.
211 // Some other thread raced us through here, and got the new Locale
212 // into the hash table before us. Use that one.
213 gDefaultLocale
= hashTableVal
; // Assignment to gDefaultLocale must happen inside mutex
224 locale_set_default(const char *id
)
227 locale_set_default_internal(id
);
232 locale_get_default(void)
236 return Locale::getDefault().getName();
242 /*Character separating the posix id fields*/
244 // In the platform codepage.
249 /*if fullName is on the heap, we free it*/
250 if (fullName
!= fullNameBuffer
)
255 if (baseName
&& baseName
!= baseNameBuffer
) {
262 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
268 * Internal constructor to allow construction of a locale object with
269 * NO side effects. (Default constructor tries to get
270 * the default locale.)
272 Locale::Locale(Locale::ELocaleType
)
273 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
279 Locale::Locale( const char * newLanguage
,
280 const char * newCountry
,
281 const char * newVariant
,
282 const char * newKeywords
)
283 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
285 if( (newLanguage
==NULL
) && (newCountry
== NULL
) && (newVariant
== NULL
) )
287 init(NULL
, FALSE
); /* shortcut */
291 char togo_stack
[ULOC_FULLNAME_CAPACITY
];
293 char *togo_heap
= NULL
;
301 // Calculate the size of the resulting string.
304 if ( newLanguage
!= NULL
)
306 lsize
= (int32_t)uprv_strlen(newLanguage
);
311 if ( newCountry
!= NULL
)
313 csize
= (int32_t)uprv_strlen(newCountry
);
318 if ( newVariant
!= NULL
)
320 // remove leading _'s
321 while(newVariant
[0] == SEP_CHAR
)
326 // remove trailing _'s
327 vsize
= (int32_t)uprv_strlen(newVariant
);
328 while( (vsize
>1) && (newVariant
[vsize
-1] == SEP_CHAR
) )
342 size
+= 2; // at least: __v
344 else if ( csize
> 0 )
346 size
+= 1; // at least: _v
349 if ( newKeywords
!= NULL
)
351 ksize
= (int32_t)uprv_strlen(newKeywords
);
356 // NOW we have the full locale string..
358 /*if the whole string is longer than our internal limit, we need
359 to go to the heap for temporary buffers*/
360 if (size
> ULOC_FULLNAME_CAPACITY
)
362 togo_heap
= (char *)uprv_malloc(sizeof(char)*(size
+1));
372 // Now, copy it back.
376 uprv_strcpy(p
, newLanguage
);
380 if ( ( vsize
!= 0 ) || (csize
!= 0) ) // at least: __v
387 uprv_strcpy(p
, newCountry
);
393 *p
++ = SEP_CHAR
; // at least: __v
395 uprv_strncpy(p
, newVariant
, vsize
); // Must use strncpy because
396 p
+= vsize
; // of trimming (above).
402 if (uprv_strchr(newKeywords
, '=')) {
403 *p
++ = '@'; /* keyword parsing */
406 *p
++ = '_'; /* Variant parsing with a script */
408 *p
++ = '_'; /* No country found */
411 uprv_strcpy(p
, newKeywords
);
415 // Parse it, because for example 'language' might really be a complete
420 uprv_free(togo_heap
);
425 Locale::Locale(const Locale
&other
)
426 : UObject(other
), fullName(fullNameBuffer
), baseName(NULL
)
431 Locale
&Locale::operator=(const Locale
&other
)
433 if (this == &other
) {
437 if (&other
== NULL
) {
442 /* Free our current storage */
443 if(fullName
!= fullNameBuffer
) {
445 fullName
= fullNameBuffer
;
448 /* Allocate the full name if necessary */
449 if(other
.fullName
!= other
.fullNameBuffer
) {
450 fullName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other
.fullName
)+1));
452 /* Copy the full name */
453 uprv_strcpy(fullName
, other
.fullName
);
455 /* baseName is the cached result of getBaseName. if 'other' has a
456 baseName and it fits in baseNameBuffer, then copy it. otherwise set
457 it to NULL, and let the user lazy-create it (in getBaseName) if they
459 if(baseName
&& baseName
!= baseNameBuffer
) {
464 if(other
.baseName
== other
.baseNameBuffer
) {
465 uprv_strcpy(baseNameBuffer
, other
.baseNameBuffer
);
466 baseName
= baseNameBuffer
;
469 /* Copy the language and country fields */
470 uprv_strcpy(language
, other
.language
);
471 uprv_strcpy(script
, other
.script
);
472 uprv_strcpy(country
, other
.country
);
474 /* The variantBegin is an offset into fullName, just copy it */
475 variantBegin
= other
.variantBegin
;
476 fIsBogus
= other
.fIsBogus
;
481 Locale::clone() const {
482 return new Locale(*this);
486 Locale::operator==( const Locale
& other
) const
488 return (uprv_strcmp(other
.fullName
, fullName
) == 0);
491 /*This function initializes a Locale from a C locale ID*/
492 Locale
& Locale::init(const char* localeID
, UBool canonicalize
)
495 /* Free our current storage */
496 if(fullName
!= fullNameBuffer
) {
498 fullName
= fullNameBuffer
;
501 if(baseName
&& baseName
!= baseNameBuffer
) {
507 // just an easy way to have a common error-exit
508 // without goto and without another function
511 char *field
[5] = {0};
512 int32_t fieldLen
[5] = {0};
514 int32_t variantField
;
518 if(localeID
== NULL
) {
519 // not an error, just set the default locale
520 return *this = getDefault();
523 /* preset all fields to empty */
524 language
[0] = script
[0] = country
[0] = 0;
526 // "canonicalize" the locale ID to ICU/Java format
528 length
= canonicalize
?
529 uloc_canonicalize(localeID
, fullName
, sizeof(fullNameBuffer
), &err
) :
530 uloc_getName(localeID
, fullName
, sizeof(fullNameBuffer
), &err
);
532 if(err
== U_BUFFER_OVERFLOW_ERROR
|| length
>= (int32_t)sizeof(fullNameBuffer
)) {
533 /*Go to heap for the fullName if necessary*/
534 fullName
= (char *)uprv_malloc(sizeof(char)*(length
+ 1));
536 fullName
= fullNameBuffer
;
537 break; // error: out of memory
540 length
= canonicalize
?
541 uloc_canonicalize(localeID
, fullName
, length
+1, &err
) :
542 uloc_getName(localeID
, fullName
, length
+1, &err
);
544 if(U_FAILURE(err
) || err
== U_STRING_NOT_TERMINATED_WARNING
) {
545 /* should never occur */
549 variantBegin
= length
;
551 /* after uloc_getName/canonicalize() we know that only '_' are separators */
552 separator
= field
[0] = fullName
;
554 while ((separator
= uprv_strchr(field
[fieldIdx
-1], SEP_CHAR
)) && fieldIdx
< (int32_t)(sizeof(field
)/sizeof(field
[0]))-1) {
555 field
[fieldIdx
] = separator
+ 1;
556 fieldLen
[fieldIdx
-1] = separator
- field
[fieldIdx
-1];
559 // variant may contain @foo or .foo POSIX cruft; remove it
560 separator
= uprv_strchr(field
[fieldIdx
-1], '@');
561 char* sep2
= uprv_strchr(field
[fieldIdx
-1], '.');
562 if (separator
!=NULL
|| sep2
!=NULL
) {
563 if (separator
==NULL
|| (sep2
!=NULL
&& separator
> sep2
)) {
566 fieldLen
[fieldIdx
-1] = separator
- field
[fieldIdx
-1];
568 fieldLen
[fieldIdx
-1] = length
- (int32_t)(field
[fieldIdx
-1] - fullName
);
571 if (fieldLen
[0] >= (int32_t)(sizeof(language
))
572 || (fieldLen
[1] == 4 && fieldLen
[2] >= (int32_t)(sizeof(country
)))
573 || (fieldLen
[1] != 4 && fieldLen
[1] >= (int32_t)(sizeof(country
))))
575 break; // error: one of the fields is too long
578 variantField
= 2; /* Usually the 2nd one, except when a script is used. */
579 if (fieldLen
[0] > 0) {
580 /* We have a language */
581 uprv_memcpy(language
, fullName
, fieldLen
[0]);
582 language
[fieldLen
[0]] = 0;
584 if (fieldLen
[1] == 4) {
585 /* We have at least a script */
586 uprv_memcpy(script
, field
[1], fieldLen
[1]);
587 script
[fieldLen
[1]] = 0;
589 if (fieldLen
[2] > 0) {
590 /* We have a country */
591 uprv_memcpy(country
, field
[2], fieldLen
[2]);
592 country
[fieldLen
[2]] = 0;
595 else if (fieldLen
[1] > 0) {
596 /* We have a country and no script */
597 uprv_memcpy(country
, field
[1], fieldLen
[1]);
598 country
[fieldLen
[1]] = 0;
600 if (variantField
> 0 && fieldLen
[variantField
] > 0) {
601 /* We have a variant */
602 variantBegin
= (int32_t)(field
[variantField
] - fullName
);
605 // successful end of init()
609 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
616 Locale::hashCode() const
619 hashKey
.pointer
= fullName
;
620 return uhash_hashChars(hashKey
);
624 Locale::setToBogus() {
625 /* Free our current storage */
626 if(fullName
!= fullNameBuffer
) {
628 fullName
= fullNameBuffer
;
637 const Locale
& U_EXPORT2
640 const Locale
*retLocale
;
642 retLocale
= gDefaultLocale
;
644 if (retLocale
== NULL
) {
645 locale_set_default_internal(NULL
);
647 // Need a mutex in case some other thread set a new
648 // default inbetween when we set and when we get the new default. For
649 // processors with weak memory coherency, we might not otherwise see all
650 // of the newly created new default locale.
651 retLocale
= gDefaultLocale
;
660 Locale::setDefault( const Locale
& newLocale
,
663 if (U_FAILURE(status
)) {
667 /* Set the default from the full name string of the supplied locale.
668 * This is a convenient way to access the default locale caching mechanisms.
670 const char *localeID
= newLocale
.getName();
671 locale_set_default_internal(localeID
);
675 Locale::createFromName (const char *name
)
688 Locale::createCanonical(const char* name
) {
690 loc
.init(name
, TRUE
);
695 Locale::getISO3Language() const
697 return uloc_getISO3Language(fullName
);
702 Locale::getISO3Country() const
704 return uloc_getISO3Country(fullName
);
708 * Return the LCID value as specified in the "LocaleID" resource for this
709 * locale. The LocaleID must be expressed as a hexadecimal number, from
710 * one to four digits. If the LocaleID resource is not present, or is
711 * in an incorrect format, 0 is returned. The LocaleID is for use in
712 * Windows (it is an LCID), but is available on all platforms.
715 Locale::getLCID() const
717 return uloc_getLCID(fullName
);
721 Locale::getDisplayLanguage(UnicodeString
& dispLang
) const
723 return this->getDisplayLanguage(getDefault(), dispLang
);
726 /*We cannot make any assumptions on the size of the output display strings
727 * Yet, since we are calling through to a C API, we need to set limits on
728 * buffer size. For all the following getDisplay functions we first attempt
729 * to fill up a stack allocated buffer. If it is to small we heap allocated
730 * the exact buffer we need copy it to the UnicodeString and delete it*/
733 Locale::getDisplayLanguage(const Locale
&displayLocale
,
734 UnicodeString
&result
) const {
736 UErrorCode errorCode
=U_ZERO_ERROR
;
739 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
745 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
746 buffer
, result
.getCapacity(),
748 result
.releaseBuffer(length
);
750 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
751 buffer
=result
.getBuffer(length
);
756 errorCode
=U_ZERO_ERROR
;
757 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
758 buffer
, result
.getCapacity(),
760 result
.releaseBuffer(length
);
763 if(U_FAILURE(errorCode
)) {
771 Locale::getDisplayScript(UnicodeString
& dispScript
) const
773 return this->getDisplayScript(getDefault(), dispScript
);
777 Locale::getDisplayScript(const Locale
&displayLocale
,
778 UnicodeString
&result
) const {
780 UErrorCode errorCode
=U_ZERO_ERROR
;
783 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
789 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
790 buffer
, result
.getCapacity(),
792 result
.releaseBuffer(length
);
794 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
795 buffer
=result
.getBuffer(length
);
800 errorCode
=U_ZERO_ERROR
;
801 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
802 buffer
, result
.getCapacity(),
804 result
.releaseBuffer(length
);
807 if(U_FAILURE(errorCode
)) {
815 Locale::getDisplayCountry(UnicodeString
& dispCntry
) const
817 return this->getDisplayCountry(getDefault(), dispCntry
);
821 Locale::getDisplayCountry(const Locale
&displayLocale
,
822 UnicodeString
&result
) const {
824 UErrorCode errorCode
=U_ZERO_ERROR
;
827 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
833 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
834 buffer
, result
.getCapacity(),
836 result
.releaseBuffer(length
);
838 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
839 buffer
=result
.getBuffer(length
);
844 errorCode
=U_ZERO_ERROR
;
845 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
846 buffer
, result
.getCapacity(),
848 result
.releaseBuffer(length
);
851 if(U_FAILURE(errorCode
)) {
859 Locale::getDisplayVariant(UnicodeString
& dispVar
) const
861 return this->getDisplayVariant(getDefault(), dispVar
);
865 Locale::getDisplayVariant(const Locale
&displayLocale
,
866 UnicodeString
&result
) const {
868 UErrorCode errorCode
=U_ZERO_ERROR
;
871 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
877 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
878 buffer
, result
.getCapacity(),
880 result
.releaseBuffer(length
);
882 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
883 buffer
=result
.getBuffer(length
);
888 errorCode
=U_ZERO_ERROR
;
889 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
890 buffer
, result
.getCapacity(),
892 result
.releaseBuffer(length
);
895 if(U_FAILURE(errorCode
)) {
903 Locale::getDisplayName( UnicodeString
& name
) const
905 return this->getDisplayName(getDefault(), name
);
909 Locale::getDisplayName(const Locale
&displayLocale
,
910 UnicodeString
&result
) const {
912 UErrorCode errorCode
=U_ZERO_ERROR
;
915 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
921 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
922 buffer
, result
.getCapacity(),
924 result
.releaseBuffer(length
);
926 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
927 buffer
=result
.getBuffer(length
);
932 errorCode
=U_ZERO_ERROR
;
933 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
934 buffer
, result
.getCapacity(),
936 result
.releaseBuffer(length
);
939 if(U_FAILURE(errorCode
)) {
945 const Locale
* U_EXPORT2
946 Locale::getAvailableLocales(int32_t& count
)
948 // for now, there is a hardcoded list, so just walk through that list and set it up.
950 UBool needInit
= availableLocaleList
== 0;
954 int32_t locCount
= uloc_countAvailable();
955 Locale
*newLocaleList
= 0;
957 newLocaleList
= new Locale
[locCount
];
959 if (newLocaleList
== NULL
) {
965 while(--locCount
>= 0) {
966 newLocaleList
[locCount
].setFromPOSIXID(uloc_getAvailable(locCount
));
970 if(availableLocaleList
== 0) {
971 availableLocaleListCount
= count
;
972 availableLocaleList
= newLocaleList
;
973 newLocaleList
= NULL
;
974 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
977 delete []newLocaleList
;
979 count
= availableLocaleListCount
;
980 return availableLocaleList
;
983 const char* const* U_EXPORT2
Locale::getISOCountries()
985 return uloc_getISOCountries();
988 const char* const* U_EXPORT2
Locale::getISOLanguages()
990 return uloc_getISOLanguages();
993 // Set the locale's data based on a posix id.
994 void Locale::setFromPOSIXID(const char *posixID
)
999 const Locale
& U_EXPORT2
1000 Locale::getEnglish(void)
1002 return getLocale(eENGLISH
);
1005 const Locale
& U_EXPORT2
1006 Locale::getFrench(void)
1008 return getLocale(eFRENCH
);
1011 const Locale
& U_EXPORT2
1012 Locale::getGerman(void)
1014 return getLocale(eGERMAN
);
1017 const Locale
& U_EXPORT2
1018 Locale::getItalian(void)
1020 return getLocale(eITALIAN
);
1023 const Locale
& U_EXPORT2
1024 Locale::getJapanese(void)
1026 return getLocale(eJAPANESE
);
1029 const Locale
& U_EXPORT2
1030 Locale::getKorean(void)
1032 return getLocale(eKOREAN
);
1035 const Locale
& U_EXPORT2
1036 Locale::getChinese(void)
1038 return getLocale(eCHINESE
);
1041 const Locale
& U_EXPORT2
1042 Locale::getSimplifiedChinese(void)
1044 return getLocale(eCHINA
);
1047 const Locale
& U_EXPORT2
1048 Locale::getTraditionalChinese(void)
1050 return getLocale(eTAIWAN
);
1054 const Locale
& U_EXPORT2
1055 Locale::getFrance(void)
1057 return getLocale(eFRANCE
);
1060 const Locale
& U_EXPORT2
1061 Locale::getGermany(void)
1063 return getLocale(eGERMANY
);
1066 const Locale
& U_EXPORT2
1067 Locale::getItaly(void)
1069 return getLocale(eITALY
);
1072 const Locale
& U_EXPORT2
1073 Locale::getJapan(void)
1075 return getLocale(eJAPAN
);
1078 const Locale
& U_EXPORT2
1079 Locale::getKorea(void)
1081 return getLocale(eKOREA
);
1084 const Locale
& U_EXPORT2
1085 Locale::getChina(void)
1087 return getLocale(eCHINA
);
1090 const Locale
& U_EXPORT2
1091 Locale::getPRC(void)
1093 return getLocale(eCHINA
);
1096 const Locale
& U_EXPORT2
1097 Locale::getTaiwan(void)
1099 return getLocale(eTAIWAN
);
1102 const Locale
& U_EXPORT2
1105 return getLocale(eUK
);
1108 const Locale
& U_EXPORT2
1111 return getLocale(eUS
);
1114 const Locale
& U_EXPORT2
1115 Locale::getCanada(void)
1117 return getLocale(eCANADA
);
1120 const Locale
& U_EXPORT2
1121 Locale::getCanadaFrench(void)
1123 return getLocale(eCANADA_FRENCH
);
1127 Locale::getLocale(int locid
)
1129 Locale
*localeCache
= getLocaleCache();
1130 U_ASSERT(locid
< eMAX_LOCALES
);
1131 if (localeCache
== NULL
) {
1132 // Failure allocating the locale cache.
1133 // The best we can do is return a NULL reference.
1136 return localeCache
[locid
];
1140 This function is defined this way in order to get around static
1141 initialization and static destruction.
1144 Locale::getLocaleCache(void)
1147 UBool needInit
= (gLocaleCache
== NULL
);
1151 Locale
*tLocaleCache
= new Locale
[(int)eMAX_LOCALES
];
1152 if (tLocaleCache
== NULL
) {
1155 tLocaleCache
[eENGLISH
] = Locale("en");
1156 tLocaleCache
[eFRENCH
] = Locale("fr");
1157 tLocaleCache
[eGERMAN
] = Locale("de");
1158 tLocaleCache
[eITALIAN
] = Locale("it");
1159 tLocaleCache
[eJAPANESE
] = Locale("ja");
1160 tLocaleCache
[eKOREAN
] = Locale("ko");
1161 tLocaleCache
[eCHINESE
] = Locale("zh");
1162 tLocaleCache
[eFRANCE
] = Locale("fr", "FR");
1163 tLocaleCache
[eGERMANY
] = Locale("de", "DE");
1164 tLocaleCache
[eITALY
] = Locale("it", "IT");
1165 tLocaleCache
[eJAPAN
] = Locale("ja", "JP");
1166 tLocaleCache
[eKOREA
] = Locale("ko", "KR");
1167 tLocaleCache
[eCHINA
] = Locale("zh", "CN");
1168 tLocaleCache
[eTAIWAN
] = Locale("zh", "TW");
1169 tLocaleCache
[eUK
] = Locale("en", "GB");
1170 tLocaleCache
[eUS
] = Locale("en", "US");
1171 tLocaleCache
[eCANADA
] = Locale("en", "CA");
1172 tLocaleCache
[eCANADA_FRENCH
] = Locale("fr", "CA");
1175 if (gLocaleCache
== NULL
) {
1176 gLocaleCache
= tLocaleCache
;
1177 tLocaleCache
= NULL
;
1178 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
1182 delete [] tLocaleCache
; // Fancy array delete will destruct each member.
1185 return gLocaleCache
;
1188 class KeywordEnumeration
: public StringEnumeration
{
1193 UnicodeString currUSKey
;
1194 static const char fgClassID
;/* Warning this is used beyond the typical RTTI usage. */
1197 static UClassID U_EXPORT2
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
1198 virtual UClassID
getDynamicClassID(void) const { return getStaticClassID(); }
1200 KeywordEnumeration(const char *keys
, int32_t keywordLen
, int32_t currentIndex
, UErrorCode
&status
)
1201 : keywords((char *)&fgClassID
), current((char *)&fgClassID
), length(0) {
1202 if(U_SUCCESS(status
) && keywordLen
!= 0) {
1203 if(keys
== NULL
|| keywordLen
< 0) {
1204 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1206 keywords
= (char *)uprv_malloc(keywordLen
+1);
1207 if (keywords
== NULL
) {
1208 status
= U_MEMORY_ALLOCATION_ERROR
;
1211 uprv_memcpy(keywords
, keys
, keywordLen
);
1212 keywords
[keywordLen
] = 0;
1213 current
= keywords
+ currentIndex
;
1214 length
= keywordLen
;
1220 virtual ~KeywordEnumeration() {
1221 uprv_free(keywords
);
1224 virtual StringEnumeration
* clone() const
1226 UErrorCode status
= U_ZERO_ERROR
;
1227 return new KeywordEnumeration(keywords
, length
, (int32_t)(current
- keywords
), status
);
1230 virtual int32_t count(UErrorCode
&/*status*/) const {
1231 char *kw
= keywords
;
1235 kw
+= uprv_strlen(kw
)+1;
1240 virtual const char* next(int32_t* resultLength
, UErrorCode
& status
) {
1243 if(U_SUCCESS(status
) && *current
!= 0) {
1245 len
= uprv_strlen(current
);
1247 if(resultLength
!= NULL
) {
1248 *resultLength
= len
;
1251 if(resultLength
!= NULL
) {
1259 virtual const UnicodeString
* snext(UErrorCode
& status
) {
1260 int32_t resultLength
= 0;
1261 const char *s
= next(&resultLength
, status
);
1262 return setChars(s
, resultLength
, status
);
1265 virtual void reset(UErrorCode
& /*status*/) {
1270 const char KeywordEnumeration::fgClassID
= '\0';
1273 Locale::createKeywords(UErrorCode
&status
) const
1276 int32_t keywordCapacity
= 256;
1277 StringEnumeration
*result
= NULL
;
1279 const char* variantStart
= uprv_strchr(fullName
, '@');
1280 const char* assignment
= uprv_strchr(fullName
, '=');
1282 if(assignment
> variantStart
) {
1283 int32_t keyLen
= locale_getKeywords(variantStart
+1, '@', keywords
, keywordCapacity
, NULL
, 0, NULL
, FALSE
, &status
);
1285 result
= new KeywordEnumeration(keywords
, keyLen
, 0, status
);
1288 status
= U_INVALID_FORMAT_ERROR
;
1295 Locale::getKeywordValue(const char* keywordName
, char *buffer
, int32_t bufLen
, UErrorCode
&status
) const
1297 return uloc_getKeywordValue(fullName
, keywordName
, buffer
, bufLen
, &status
);
1301 Locale::getBaseName() const
1304 UErrorCode status
= U_ZERO_ERROR
;
1305 // semantically const
1307 ((Locale
*)this)->baseName
= ((Locale
*)this)->baseNameBuffer
;
1308 int32_t baseNameSize
= uloc_getBaseName(fullName
, baseName
, ULOC_FULLNAME_CAPACITY
, &status
);
1309 if(baseNameSize
>= ULOC_FULLNAME_CAPACITY
) {
1310 ((Locale
*)this)->baseName
= (char *)uprv_malloc(sizeof(char) * baseNameSize
+ 1);
1311 uloc_getBaseName(fullName
, baseName
, baseNameSize
+1, &status
);
1313 baseName
[baseNameSize
] = 0;