2 **********************************************************************
3 * Copyright (C) 1997-2008, 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 U_NAMESPACE_QUALIFIER 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 U_NAMESPACE_QUALIFIER Locale
*gLocaleCache
= NULL
;
80 static U_NAMESPACE_QUALIFIER 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 (U_NAMESPACE_QUALIFIER 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 else if (gDefaultLocale
) {
112 // The cache wasn't created, and only one default locale was created.
113 delete gDefaultLocale
;
115 gDefaultLocale
= NULL
;
123 // locale_set_default_internal.
125 void locale_set_default_internal(const char *id
)
127 UErrorCode status
= U_ZERO_ERROR
;
128 UBool canonicalize
= FALSE
;
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.)
136 id
= uprv_getDefaultLocaleID();
138 canonicalize
= TRUE
; // always canonicalize host ID
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.
145 status
= U_ZERO_ERROR
;
146 char localeNameBuf
[512];
149 uloc_canonicalize(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
151 uloc_getName(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
153 localeNameBuf
[sizeof(localeNameBuf
)-1] = 0; // Force null termination in event of
154 // a long name filling the buffer.
155 // (long names are truncated.)
157 // Lazy creation of the hash table itself, if needed.
159 UMTX_CHECK(NULL
, (gDefaultLocale
== NULL
), 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.
168 newFirstDefault
->init(localeNameBuf
, FALSE
);
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
);
175 // Else some other thread raced us through here, and set the new Locale.
176 // Use the hash table next.
178 if (newFirstDefault
== NULL
) {
179 // We were successful in setting the locale, and we were the first one to set it.
182 // else start using the hash table.
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
)) {
194 uhash_setValueDeleter(tHashTable
, deleteLocale
);
196 if (gDefaultLocalesHashT
== NULL
) {
197 gDefaultLocalesHashT
= tHashTable
;
198 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
200 uhash_close(tHashTable
);
201 hashTableNeedsInit
= FALSE
;
206 // Hash table lookup, key is the locale full name
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
;
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.
223 newDefault
->init(localeNameBuf
, FALSE
);
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);
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
);
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.
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
254 locale_set_default(const char *id
)
257 locale_set_default_internal(id
);
262 locale_get_default(void)
266 return Locale::getDefault().getName();
272 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale
)
274 /*Character separating the posix id fields*/
276 // In the platform codepage.
281 /*if fullName is on the heap, we free it*/
282 if (fullName
!= fullNameBuffer
)
287 if (baseName
&& baseName
!= baseNameBuffer
) {
294 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
300 * Internal constructor to allow construction of a locale object with
301 * NO side effects. (Default constructor tries to get
302 * the default locale.)
304 Locale::Locale(Locale::ELocaleType
)
305 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
311 Locale::Locale( const char * newLanguage
,
312 const char * newCountry
,
313 const char * newVariant
,
314 const char * newKeywords
)
315 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
317 if( (newLanguage
==NULL
) && (newCountry
== NULL
) && (newVariant
== NULL
) )
319 init(NULL
, FALSE
); /* shortcut */
323 char togo_stack
[ULOC_FULLNAME_CAPACITY
];
325 char *togo_heap
= NULL
;
333 // Calculate the size of the resulting string.
336 if ( newLanguage
!= NULL
)
338 lsize
= (int32_t)uprv_strlen(newLanguage
);
343 if ( newCountry
!= NULL
)
345 csize
= (int32_t)uprv_strlen(newCountry
);
350 if ( newVariant
!= NULL
)
352 // remove leading _'s
353 while(newVariant
[0] == SEP_CHAR
)
358 // remove trailing _'s
359 vsize
= (int32_t)uprv_strlen(newVariant
);
360 while( (vsize
>1) && (newVariant
[vsize
-1] == SEP_CHAR
) )
374 size
+= 2; // at least: __v
376 else if ( csize
> 0 )
378 size
+= 1; // at least: _v
381 if ( newKeywords
!= NULL
)
383 ksize
= (int32_t)uprv_strlen(newKeywords
);
388 // NOW we have the full locale string..
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
)
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
) {
408 // Now, copy it back.
412 uprv_strcpy(p
, newLanguage
);
416 if ( ( vsize
!= 0 ) || (csize
!= 0) ) // at least: __v
423 uprv_strcpy(p
, newCountry
);
429 *p
++ = SEP_CHAR
; // at least: __v
431 uprv_strncpy(p
, newVariant
, vsize
); // Must use strncpy because
432 p
+= vsize
; // of trimming (above).
438 if (uprv_strchr(newKeywords
, '=')) {
439 *p
++ = '@'; /* keyword parsing */
442 *p
++ = '_'; /* Variant parsing with a script */
444 *p
++ = '_'; /* No country found */
447 uprv_strcpy(p
, newKeywords
);
451 // Parse it, because for example 'language' might really be a complete
456 uprv_free(togo_heap
);
461 Locale::Locale(const Locale
&other
)
462 : UObject(other
), fullName(fullNameBuffer
), baseName(NULL
)
467 Locale
&Locale::operator=(const Locale
&other
)
469 if (this == &other
) {
473 if (&other
== NULL
) {
478 /* Free our current storage */
479 if(fullName
!= fullNameBuffer
) {
481 fullName
= fullNameBuffer
;
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
) {
491 /* Copy the full name */
492 uprv_strcpy(fullName
, other
.fullName
);
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
498 if(baseName
&& baseName
!= baseNameBuffer
) {
503 if(other
.baseName
== other
.baseNameBuffer
) {
504 uprv_strcpy(baseNameBuffer
, other
.baseNameBuffer
);
505 baseName
= baseNameBuffer
;
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
);
513 /* The variantBegin is an offset into fullName, just copy it */
514 variantBegin
= other
.variantBegin
;
515 fIsBogus
= other
.fIsBogus
;
520 Locale::clone() const {
521 return new Locale(*this);
525 Locale::operator==( const Locale
& other
) const
527 return (uprv_strcmp(other
.fullName
, fullName
) == 0);
530 /*This function initializes a Locale from a C locale ID*/
531 Locale
& Locale::init(const char* localeID
, UBool canonicalize
)
534 /* Free our current storage */
535 if(fullName
!= fullNameBuffer
) {
537 fullName
= fullNameBuffer
;
540 if(baseName
&& baseName
!= baseNameBuffer
) {
546 // just an easy way to have a common error-exit
547 // without goto and without another function
550 char *field
[5] = {0};
551 int32_t fieldLen
[5] = {0};
553 int32_t variantField
;
557 if(localeID
== NULL
) {
558 // not an error, just set the default locale
559 return *this = getDefault();
562 /* preset all fields to empty */
563 language
[0] = script
[0] = country
[0] = 0;
565 // "canonicalize" the locale ID to ICU/Java format
567 length
= canonicalize
?
568 uloc_canonicalize(localeID
, fullName
, sizeof(fullNameBuffer
), &err
) :
569 uloc_getName(localeID
, fullName
, sizeof(fullNameBuffer
), &err
);
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));
575 fullName
= fullNameBuffer
;
576 break; // error: out of memory
579 length
= canonicalize
?
580 uloc_canonicalize(localeID
, fullName
, length
+1, &err
) :
581 uloc_getName(localeID
, fullName
, length
+1, &err
);
583 if(U_FAILURE(err
) || err
== U_STRING_NOT_TERMINATED_WARNING
) {
584 /* should never occur */
588 variantBegin
= length
;
590 /* after uloc_getName/canonicalize() we know that only '_' are separators */
591 separator
= field
[0] = fullName
;
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]);
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
)) {
605 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
607 fieldLen
[fieldIdx
-1] = length
- (int32_t)(field
[fieldIdx
-1] - fullName
);
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
))))
614 break; // error: one of the fields is too long
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;
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;
628 if (fieldLen
[2] > 0) {
629 /* We have a country */
630 uprv_memcpy(country
, field
[2], fieldLen
[2]);
631 country
[fieldLen
[2]] = 0;
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;
639 if (variantField
> 0 && fieldLen
[variantField
] > 0) {
640 /* We have a variant */
641 variantBegin
= (int32_t)(field
[variantField
] - fullName
);
644 // successful end of init()
646 } while(0); /*loop doesn't iterate*/
648 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
655 Locale::hashCode() const
658 hashKey
.pointer
= fullName
;
659 return uhash_hashChars(hashKey
);
663 Locale::setToBogus() {
664 /* Free our current storage */
665 if(fullName
!= fullNameBuffer
) {
667 fullName
= fullNameBuffer
;
676 const Locale
& U_EXPORT2
679 const Locale
*retLocale
;
680 UMTX_CHECK(NULL
, gDefaultLocale
, retLocale
);
681 if (retLocale
== NULL
) {
682 locale_set_default_internal(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
;
697 Locale::setDefault( const Locale
& newLocale
,
700 if (U_FAILURE(status
)) {
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.
707 const char *localeID
= newLocale
.getName();
708 locale_set_default_internal(localeID
);
712 Locale::createFromName (const char *name
)
725 Locale::createCanonical(const char* name
) {
727 loc
.init(name
, TRUE
);
732 Locale::getISO3Language() const
734 return uloc_getISO3Language(fullName
);
739 Locale::getISO3Country() const
741 return uloc_getISO3Country(fullName
);
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.
752 Locale::getLCID() const
754 return uloc_getLCID(fullName
);
758 Locale::getDisplayLanguage(UnicodeString
& dispLang
) const
760 return this->getDisplayLanguage(getDefault(), dispLang
);
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*/
770 Locale::getDisplayLanguage(const Locale
&displayLocale
,
771 UnicodeString
&result
) const {
773 UErrorCode errorCode
=U_ZERO_ERROR
;
776 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
782 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
783 buffer
, result
.getCapacity(),
785 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
787 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
788 buffer
=result
.getBuffer(length
);
793 errorCode
=U_ZERO_ERROR
;
794 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
795 buffer
, result
.getCapacity(),
797 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
804 Locale::getDisplayScript(UnicodeString
& dispScript
) const
806 return this->getDisplayScript(getDefault(), dispScript
);
810 Locale::getDisplayScript(const Locale
&displayLocale
,
811 UnicodeString
&result
) const {
813 UErrorCode errorCode
=U_ZERO_ERROR
;
816 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
822 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
823 buffer
, result
.getCapacity(),
825 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
827 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
828 buffer
=result
.getBuffer(length
);
833 errorCode
=U_ZERO_ERROR
;
834 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
835 buffer
, result
.getCapacity(),
837 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
844 Locale::getDisplayCountry(UnicodeString
& dispCntry
) const
846 return this->getDisplayCountry(getDefault(), dispCntry
);
850 Locale::getDisplayCountry(const Locale
&displayLocale
,
851 UnicodeString
&result
) const {
853 UErrorCode errorCode
=U_ZERO_ERROR
;
856 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
862 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
863 buffer
, result
.getCapacity(),
865 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
867 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
868 buffer
=result
.getBuffer(length
);
873 errorCode
=U_ZERO_ERROR
;
874 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
875 buffer
, result
.getCapacity(),
877 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
884 Locale::getDisplayVariant(UnicodeString
& dispVar
) const
886 return this->getDisplayVariant(getDefault(), dispVar
);
890 Locale::getDisplayVariant(const Locale
&displayLocale
,
891 UnicodeString
&result
) const {
893 UErrorCode errorCode
=U_ZERO_ERROR
;
896 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
902 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
903 buffer
, result
.getCapacity(),
905 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
907 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
908 buffer
=result
.getBuffer(length
);
913 errorCode
=U_ZERO_ERROR
;
914 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
915 buffer
, result
.getCapacity(),
917 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
924 Locale::getDisplayName( UnicodeString
& name
) const
926 return this->getDisplayName(getDefault(), name
);
930 Locale::getDisplayName(const Locale
&displayLocale
,
931 UnicodeString
&result
) const {
933 UErrorCode errorCode
=U_ZERO_ERROR
;
936 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
942 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
943 buffer
, result
.getCapacity(),
945 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
947 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
948 buffer
=result
.getBuffer(length
);
953 errorCode
=U_ZERO_ERROR
;
954 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
955 buffer
, result
.getCapacity(),
957 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
962 const Locale
* U_EXPORT2
963 Locale::getAvailableLocales(int32_t& count
)
965 // for now, there is a hardcoded list, so just walk through that list and set it up.
967 UMTX_CHECK(NULL
, availableLocaleList
== NULL
, needInit
);
970 int32_t locCount
= uloc_countAvailable();
971 Locale
*newLocaleList
= 0;
973 newLocaleList
= new Locale
[locCount
];
975 if (newLocaleList
== NULL
) {
982 while(--locCount
>= 0) {
983 newLocaleList
[locCount
].setFromPOSIXID(uloc_getAvailable(locCount
));
987 if(availableLocaleList
== 0) {
988 availableLocaleListCount
= count
;
989 availableLocaleList
= newLocaleList
;
990 newLocaleList
= NULL
;
991 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
994 delete []newLocaleList
;
996 count
= availableLocaleListCount
;
997 return availableLocaleList
;
1000 const char* const* U_EXPORT2
Locale::getISOCountries()
1002 return uloc_getISOCountries();
1005 const char* const* U_EXPORT2
Locale::getISOLanguages()
1007 return uloc_getISOLanguages();
1010 // Set the locale's data based on a posix id.
1011 void Locale::setFromPOSIXID(const char *posixID
)
1013 init(posixID
, TRUE
);
1016 const Locale
& U_EXPORT2
1017 Locale::getEnglish(void)
1019 return getLocale(eENGLISH
);
1022 const Locale
& U_EXPORT2
1023 Locale::getFrench(void)
1025 return getLocale(eFRENCH
);
1028 const Locale
& U_EXPORT2
1029 Locale::getGerman(void)
1031 return getLocale(eGERMAN
);
1034 const Locale
& U_EXPORT2
1035 Locale::getItalian(void)
1037 return getLocale(eITALIAN
);
1040 const Locale
& U_EXPORT2
1041 Locale::getJapanese(void)
1043 return getLocale(eJAPANESE
);
1046 const Locale
& U_EXPORT2
1047 Locale::getKorean(void)
1049 return getLocale(eKOREAN
);
1052 const Locale
& U_EXPORT2
1053 Locale::getChinese(void)
1055 return getLocale(eCHINESE
);
1058 const Locale
& U_EXPORT2
1059 Locale::getSimplifiedChinese(void)
1061 return getLocale(eCHINA
);
1064 const Locale
& U_EXPORT2
1065 Locale::getTraditionalChinese(void)
1067 return getLocale(eTAIWAN
);
1071 const Locale
& U_EXPORT2
1072 Locale::getFrance(void)
1074 return getLocale(eFRANCE
);
1077 const Locale
& U_EXPORT2
1078 Locale::getGermany(void)
1080 return getLocale(eGERMANY
);
1083 const Locale
& U_EXPORT2
1084 Locale::getItaly(void)
1086 return getLocale(eITALY
);
1089 const Locale
& U_EXPORT2
1090 Locale::getJapan(void)
1092 return getLocale(eJAPAN
);
1095 const Locale
& U_EXPORT2
1096 Locale::getKorea(void)
1098 return getLocale(eKOREA
);
1101 const Locale
& U_EXPORT2
1102 Locale::getChina(void)
1104 return getLocale(eCHINA
);
1107 const Locale
& U_EXPORT2
1108 Locale::getPRC(void)
1110 return getLocale(eCHINA
);
1113 const Locale
& U_EXPORT2
1114 Locale::getTaiwan(void)
1116 return getLocale(eTAIWAN
);
1119 const Locale
& U_EXPORT2
1122 return getLocale(eUK
);
1125 const Locale
& U_EXPORT2
1128 return getLocale(eUS
);
1131 const Locale
& U_EXPORT2
1132 Locale::getCanada(void)
1134 return getLocale(eCANADA
);
1137 const Locale
& U_EXPORT2
1138 Locale::getCanadaFrench(void)
1140 return getLocale(eCANADA_FRENCH
);
1144 Locale::getLocale(int locid
)
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.
1153 return localeCache
[locid
]; /*operating on NULL*/
1157 This function is defined this way in order to get around static
1158 initialization and static destruction.
1161 Locale::getLocaleCache(void)
1164 UBool needInit
= (gLocaleCache
== NULL
);
1168 Locale
*tLocaleCache
= new Locale
[(int)eMAX_LOCALES
];
1169 if (tLocaleCache
== NULL
) {
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");
1192 if (gLocaleCache
== NULL
) {
1193 gLocaleCache
= tLocaleCache
;
1194 tLocaleCache
= NULL
;
1195 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
1199 delete [] tLocaleCache
; // Fancy array delete will destruct each member.
1202 return gLocaleCache
;
1205 class KeywordEnumeration
: public StringEnumeration
{
1210 UnicodeString currUSKey
;
1211 static const char fgClassID
;/* Warning this is used beyond the typical RTTI usage. */
1214 static UClassID U_EXPORT2
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
1215 virtual UClassID
getDynamicClassID(void) const { return getStaticClassID(); }
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
;
1223 keywords
= (char *)uprv_malloc(keywordLen
+1);
1224 if (keywords
== NULL
) {
1225 status
= U_MEMORY_ALLOCATION_ERROR
;
1228 uprv_memcpy(keywords
, keys
, keywordLen
);
1229 keywords
[keywordLen
] = 0;
1230 current
= keywords
+ currentIndex
;
1231 length
= keywordLen
;
1237 virtual ~KeywordEnumeration() {
1238 uprv_free(keywords
);
1241 virtual StringEnumeration
* clone() const
1243 UErrorCode status
= U_ZERO_ERROR
;
1244 return new KeywordEnumeration(keywords
, length
, (int32_t)(current
- keywords
), status
);
1247 virtual int32_t count(UErrorCode
&/*status*/) const {
1248 char *kw
= keywords
;
1252 kw
+= uprv_strlen(kw
)+1;
1257 virtual const char* next(int32_t* resultLength
, UErrorCode
& status
) {
1260 if(U_SUCCESS(status
) && *current
!= 0) {
1262 len
= (int32_t)uprv_strlen(current
);
1264 if(resultLength
!= NULL
) {
1265 *resultLength
= len
;
1268 if(resultLength
!= NULL
) {
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
);
1282 virtual void reset(UErrorCode
& /*status*/) {
1287 const char KeywordEnumeration::fgClassID
= '\0';
1290 Locale::createKeywords(UErrorCode
&status
) const
1293 int32_t keywordCapacity
= 256;
1294 StringEnumeration
*result
= NULL
;
1296 const char* variantStart
= uprv_strchr(fullName
, '@');
1297 const char* assignment
= uprv_strchr(fullName
, '=');
1299 if(assignment
> variantStart
) {
1300 int32_t keyLen
= locale_getKeywords(variantStart
+1, '@', keywords
, keywordCapacity
, NULL
, 0, NULL
, FALSE
, &status
);
1302 result
= new KeywordEnumeration(keywords
, keyLen
, 0, status
);
1305 status
= U_INVALID_FORMAT_ERROR
;
1312 Locale::getKeywordValue(const char* keywordName
, char *buffer
, int32_t bufLen
, UErrorCode
&status
) const
1314 return uloc_getKeywordValue(fullName
, keywordName
, buffer
, bufLen
, &status
);
1318 Locale::getBaseName() const
1321 UErrorCode status
= U_ZERO_ERROR
;
1322 // semantically const
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
) {
1331 uloc_getBaseName(fullName
, baseName
, baseNameSize
+1, &status
);
1333 baseName
[baseNameSize
] = 0;