2 **********************************************************************
3 * Copyright (C) 1997-2011, 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"
44 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
46 typedef enum ELocalePos
{
60 eCHINA
, /* Alias for PRC */
73 U_CFUNC
int32_t locale_getKeywords(const char *localeID
,
75 char *keywords
, int32_t keywordCapacity
,
76 char *values
, int32_t valuesCapacity
, int32_t *valLen
,
80 static icu::Locale
*gLocaleCache
= NULL
;
81 static icu::Locale
*gDefaultLocale
= NULL
;
82 static UHashtable
*gDefaultLocalesHashT
= NULL
;
86 // Deleter function for Locales owned by the default Locale hash table/
88 static void U_CALLCONV
89 deleteLocale(void *obj
) {
90 delete (icu::Locale
*) obj
;
93 static UBool U_CALLCONV
locale_cleanup(void)
98 delete [] gLocaleCache
;
102 if (gDefaultLocalesHashT
) {
103 uhash_close(gDefaultLocalesHashT
); // Automatically deletes all elements, using deleter func.
104 gDefaultLocalesHashT
= NULL
;
106 else if (gDefaultLocale
) {
107 // The cache wasn't created, and only one default locale was created.
108 delete gDefaultLocale
;
110 gDefaultLocale
= NULL
;
118 // locale_set_default_internal.
120 void locale_set_default_internal(const char *id
)
122 UErrorCode status
= U_ZERO_ERROR
;
123 UBool canonicalize
= FALSE
;
125 // If given a NULL string for the locale id, grab the default
126 // name from the system.
127 // (Different from most other locale APIs, where a null name means use
128 // the current ICU default locale.)
131 id
= uprv_getDefaultLocaleID();
133 canonicalize
= TRUE
; // always canonicalize host ID
136 // put the locale id into a canonical form,
137 // in preparation for looking up this locale in the hash table of
138 // already-created locale objects.
140 status
= U_ZERO_ERROR
;
141 char localeNameBuf
[512];
144 uloc_canonicalize(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
146 uloc_getName(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
148 localeNameBuf
[sizeof(localeNameBuf
)-1] = 0; // Force null termination in event of
149 // a long name filling the buffer.
150 // (long names are truncated.)
152 // Lazy creation of the hash table itself, if needed.
154 UMTX_CHECK(NULL
, (gDefaultLocale
== NULL
), isOnlyLocale
);
156 // We haven't seen this locale id before.
157 // Create a new Locale object for it.
158 Locale
*newFirstDefault
= new Locale(Locale::eBOGUS
);
159 if (newFirstDefault
== NULL
) {
160 // No way to report errors from here.
163 newFirstDefault
->init(localeNameBuf
, FALSE
);
165 if (gDefaultLocale
== NULL
) {
166 gDefaultLocale
= newFirstDefault
; // Assignment to gDefaultLocale must happen inside mutex
167 newFirstDefault
= NULL
;
168 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
170 // We were successful in setting the locale, and we were the first one to set it.
174 // Else some other thread raced us through here, and set the new Locale.
176 delete newFirstDefault
;
181 // Create the hash table next, unless the racing thread is setting the same locale as default.
182 // The new locale might have been set while a racing thread was stuck at the lock
183 // earlier in this function. (For example, see uprv_getDefaultLocaleID above).
185 // Only create the hash table if we need to.
186 if (uprv_strcmp(gDefaultLocale
->getName(), localeNameBuf
) == 0) {
191 // start using the hash table.
194 // Lazy creation of the hash table itself, if needed.
195 UBool hashTableNeedsInit
;
196 UMTX_CHECK(NULL
, (gDefaultLocalesHashT
== NULL
), hashTableNeedsInit
);
197 if (hashTableNeedsInit
) {
198 status
= U_ZERO_ERROR
;
199 UHashtable
*tHashTable
= uhash_open(uhash_hashChars
, uhash_compareChars
, NULL
, &status
);
200 if (U_FAILURE(status
)) {
203 uhash_setValueDeleter(tHashTable
, deleteLocale
);
205 if (gDefaultLocalesHashT
== NULL
) {
206 gDefaultLocalesHashT
= tHashTable
;
207 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
209 uhash_put(gDefaultLocalesHashT
, (void *)gDefaultLocale
->getName(), gDefaultLocale
, &status
);
211 uhash_close(tHashTable
);
216 // Hash table lookup, key is the locale full name
218 Locale
*newDefault
= (Locale
*)uhash_get(gDefaultLocalesHashT
, localeNameBuf
);
219 if (newDefault
!= NULL
) {
220 // We have the requested locale in the hash table already.
221 // Just set it as default. Inside the mutex lock, for those troublesome processors.
222 gDefaultLocale
= newDefault
;
226 // We haven't seen this locale id before.
227 // Create a new Locale object for it.
228 newDefault
= new Locale(Locale::eBOGUS
);
229 if (newDefault
== NULL
) {
230 // No way to report errors from here.
233 newDefault
->init(localeNameBuf
, FALSE
);
235 // Add newly created Locale to the hash table of default Locales
236 const char *key
= newDefault
->getName();
237 U_ASSERT(uprv_strcmp(key
, localeNameBuf
) == 0);
239 Locale
*hashTableVal
= (Locale
*)uhash_get(gDefaultLocalesHashT
, key
);
240 if (hashTableVal
== NULL
) {
241 uhash_put(gDefaultLocalesHashT
, (void *)key
, newDefault
, &status
);
242 gDefaultLocale
= newDefault
;
243 // ignore errors from hash table insert. (Couldn't do anything anyway)
244 // We can still set the default Locale,
245 // it just wont be cached, and will eventually leak.
247 // Some other thread raced us through here, and got the new Locale
248 // into the hash table before us. Use that one.
249 gDefaultLocale
= hashTableVal
; // Assignment to gDefaultLocale must happen inside mutex
259 locale_set_default(const char *id
)
262 locale_set_default_internal(id
);
267 locale_get_default(void)
271 return Locale::getDefault().getName();
277 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale
)
279 /*Character separating the posix id fields*/
281 // In the platform codepage.
286 /*if fullName is on the heap, we free it*/
287 if (fullName
!= fullNameBuffer
)
292 if (baseName
&& baseName
!= baseNameBuffer
) {
299 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
305 * Internal constructor to allow construction of a locale object with
306 * NO side effects. (Default constructor tries to get
307 * the default locale.)
309 Locale::Locale(Locale::ELocaleType
)
310 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
316 Locale::Locale( const char * newLanguage
,
317 const char * newCountry
,
318 const char * newVariant
,
319 const char * newKeywords
)
320 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
322 if( (newLanguage
==NULL
) && (newCountry
== NULL
) && (newVariant
== NULL
) )
324 init(NULL
, FALSE
); /* shortcut */
328 MaybeStackArray
<char, ULOC_FULLNAME_CAPACITY
> togo
;
336 // Calculate the size of the resulting string.
339 if ( newLanguage
!= NULL
)
341 lsize
= (int32_t)uprv_strlen(newLanguage
);
346 if ( newCountry
!= NULL
)
348 csize
= (int32_t)uprv_strlen(newCountry
);
353 if ( newVariant
!= NULL
)
355 // remove leading _'s
356 while(newVariant
[0] == SEP_CHAR
)
361 // remove trailing _'s
362 vsize
= (int32_t)uprv_strlen(newVariant
);
363 while( (vsize
>1) && (newVariant
[vsize
-1] == SEP_CHAR
) )
377 size
+= 2; // at least: __v
379 else if ( csize
> 0 )
381 size
+= 1; // at least: _v
384 if ( newKeywords
!= NULL
)
386 ksize
= (int32_t)uprv_strlen(newKeywords
);
391 // NOW we have the full locale string..
393 /*if the whole string is longer than our internal limit, we need
394 to go to the heap for temporary buffers*/
395 if (size
>= togo
.getCapacity())
397 // If togo_heap could not be created, initialize with default settings.
398 if (togo
.resize(size
+1) == NULL
) {
405 // Now, copy it back.
409 uprv_strcpy(p
, newLanguage
);
413 if ( ( vsize
!= 0 ) || (csize
!= 0) ) // at least: __v
420 uprv_strcpy(p
, newCountry
);
426 *p
++ = SEP_CHAR
; // at least: __v
428 uprv_strncpy(p
, newVariant
, vsize
); // Must use strncpy because
429 p
+= vsize
; // of trimming (above).
435 if (uprv_strchr(newKeywords
, '=')) {
436 *p
++ = '@'; /* keyword parsing */
439 *p
++ = '_'; /* Variant parsing with a script */
441 *p
++ = '_'; /* No country found */
444 uprv_strcpy(p
, newKeywords
);
448 // Parse it, because for example 'language' might really be a complete
450 init(togo
.getAlias(), FALSE
);
454 Locale::Locale(const Locale
&other
)
455 : UObject(other
), fullName(fullNameBuffer
), baseName(NULL
)
460 Locale
&Locale::operator=(const Locale
&other
)
462 if (this == &other
) {
466 if (&other
== NULL
) {
471 /* Free our current storage */
472 if(fullName
!= fullNameBuffer
) {
474 fullName
= fullNameBuffer
;
477 /* Allocate the full name if necessary */
478 if(other
.fullName
!= other
.fullNameBuffer
) {
479 fullName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other
.fullName
)+1));
480 if (fullName
== NULL
) {
484 /* Copy the full name */
485 uprv_strcpy(fullName
, other
.fullName
);
487 /* baseName is the cached result of getBaseName. if 'other' has a
488 baseName and it fits in baseNameBuffer, then copy it. otherwise set
489 it to NULL, and let the user lazy-create it (in getBaseName) if they
491 if(baseName
&& baseName
!= baseNameBuffer
) {
496 if(other
.baseName
== other
.baseNameBuffer
) {
497 uprv_strcpy(baseNameBuffer
, other
.baseNameBuffer
);
498 baseName
= baseNameBuffer
;
501 /* Copy the language and country fields */
502 uprv_strcpy(language
, other
.language
);
503 uprv_strcpy(script
, other
.script
);
504 uprv_strcpy(country
, other
.country
);
506 /* The variantBegin is an offset, just copy it */
507 variantBegin
= other
.variantBegin
;
508 fIsBogus
= other
.fIsBogus
;
513 Locale::clone() const {
514 return new Locale(*this);
518 Locale::operator==( const Locale
& other
) const
520 return (uprv_strcmp(other
.fullName
, fullName
) == 0);
523 #define ISASCIIALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
525 /*This function initializes a Locale from a C locale ID*/
526 Locale
& Locale::init(const char* localeID
, UBool canonicalize
)
529 /* Free our current storage */
530 if(fullName
!= fullNameBuffer
) {
532 fullName
= fullNameBuffer
;
535 if(baseName
&& baseName
!= baseNameBuffer
) {
541 // just an easy way to have a common error-exit
542 // without goto and without another function
545 char *field
[5] = {0};
546 int32_t fieldLen
[5] = {0};
548 int32_t variantField
;
552 if(localeID
== NULL
) {
553 // not an error, just set the default locale
554 return *this = getDefault();
557 /* preset all fields to empty */
558 language
[0] = script
[0] = country
[0] = 0;
560 // "canonicalize" the locale ID to ICU/Java format
562 length
= canonicalize
?
563 uloc_canonicalize(localeID
, fullName
, sizeof(fullNameBuffer
), &err
) :
564 uloc_getName(localeID
, fullName
, sizeof(fullNameBuffer
), &err
);
566 if(err
== U_BUFFER_OVERFLOW_ERROR
|| length
>= (int32_t)sizeof(fullNameBuffer
)) {
567 /*Go to heap for the fullName if necessary*/
568 fullName
= (char *)uprv_malloc(sizeof(char)*(length
+ 1));
570 fullName
= fullNameBuffer
;
571 break; // error: out of memory
574 length
= canonicalize
?
575 uloc_canonicalize(localeID
, fullName
, length
+1, &err
) :
576 uloc_getName(localeID
, fullName
, length
+1, &err
);
578 if(U_FAILURE(err
) || err
== U_STRING_NOT_TERMINATED_WARNING
) {
579 /* should never occur */
583 variantBegin
= length
;
585 /* after uloc_getName/canonicalize() we know that only '_' are separators */
586 separator
= field
[0] = fullName
;
588 while ((separator
= uprv_strchr(field
[fieldIdx
-1], SEP_CHAR
)) && fieldIdx
< (int32_t)(sizeof(field
)/sizeof(field
[0]))-1) {
589 field
[fieldIdx
] = separator
+ 1;
590 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
593 // variant may contain @foo or .foo POSIX cruft; remove it
594 separator
= uprv_strchr(field
[fieldIdx
-1], '@');
595 char* sep2
= uprv_strchr(field
[fieldIdx
-1], '.');
596 if (separator
!=NULL
|| sep2
!=NULL
) {
597 if (separator
==NULL
|| (sep2
!=NULL
&& separator
> sep2
)) {
600 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
602 fieldLen
[fieldIdx
-1] = length
- (int32_t)(field
[fieldIdx
-1] - fullName
);
605 if (fieldLen
[0] >= (int32_t)(sizeof(language
)))
607 break; // error: the language field is too long
610 variantField
= 1; /* Usually the 2nd one, except when a script or country is also used. */
611 if (fieldLen
[0] > 0) {
612 /* We have a language */
613 uprv_memcpy(language
, fullName
, fieldLen
[0]);
614 language
[fieldLen
[0]] = 0;
616 if (fieldLen
[1] == 4 && ISASCIIALPHA(field
[1][0]) &&
617 ISASCIIALPHA(field
[1][1]) && ISASCIIALPHA(field
[1][2]) &&
618 ISASCIIALPHA(field
[1][3])) {
619 /* We have at least a script */
620 uprv_memcpy(script
, field
[1], fieldLen
[1]);
621 script
[fieldLen
[1]] = 0;
625 if (fieldLen
[variantField
] == 2 || fieldLen
[variantField
] == 3) {
626 /* We have a country */
627 uprv_memcpy(country
, field
[variantField
], fieldLen
[variantField
]);
628 country
[fieldLen
[variantField
]] = 0;
630 } else if (fieldLen
[variantField
] == 0) {
631 variantField
++; /* script or country empty but variant in next field (i.e. en__POSIX) */
634 if (fieldLen
[variantField
] > 0) {
635 /* We have a variant */
636 variantBegin
= (int32_t)(field
[variantField
] - fullName
);
639 // successful end of init()
641 } while(0); /*loop doesn't iterate*/
643 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
650 Locale::hashCode() const
652 return ustr_hashCharsN(fullName
, uprv_strlen(fullName
));
656 Locale::setToBogus() {
657 /* Free our current storage */
658 if(fullName
!= fullNameBuffer
) {
660 fullName
= fullNameBuffer
;
662 if(baseName
&& baseName
!= baseNameBuffer
) {
673 const Locale
& U_EXPORT2
676 const Locale
*retLocale
;
677 UMTX_CHECK(NULL
, gDefaultLocale
, retLocale
);
678 if (retLocale
== NULL
) {
679 locale_set_default_internal(NULL
);
681 // Need a mutex in case some other thread set a new
682 // default inbetween when we set and when we get the new default. For
683 // processors with weak memory coherency, we might not otherwise see all
684 // of the newly created new default locale.
685 retLocale
= gDefaultLocale
;
694 Locale::setDefault( const Locale
& newLocale
,
697 if (U_FAILURE(status
)) {
701 /* Set the default from the full name string of the supplied locale.
702 * This is a convenient way to access the default locale caching mechanisms.
704 const char *localeID
= newLocale
.getName();
705 locale_set_default_internal(localeID
);
709 Locale::createFromName (const char *name
)
722 Locale::createCanonical(const char* name
) {
724 loc
.init(name
, TRUE
);
729 Locale::getISO3Language() const
731 return uloc_getISO3Language(fullName
);
736 Locale::getISO3Country() const
738 return uloc_getISO3Country(fullName
);
742 * Return the LCID value as specified in the "LocaleID" resource for this
743 * locale. The LocaleID must be expressed as a hexadecimal number, from
744 * one to four digits. If the LocaleID resource is not present, or is
745 * in an incorrect format, 0 is returned. The LocaleID is for use in
746 * Windows (it is an LCID), but is available on all platforms.
749 Locale::getLCID() const
751 return uloc_getLCID(fullName
);
754 const char* const* U_EXPORT2
Locale::getISOCountries()
756 return uloc_getISOCountries();
759 const char* const* U_EXPORT2
Locale::getISOLanguages()
761 return uloc_getISOLanguages();
764 // Set the locale's data based on a posix id.
765 void Locale::setFromPOSIXID(const char *posixID
)
770 const Locale
& U_EXPORT2
771 Locale::getRoot(void)
773 return getLocale(eROOT
);
776 const Locale
& U_EXPORT2
777 Locale::getEnglish(void)
779 return getLocale(eENGLISH
);
782 const Locale
& U_EXPORT2
783 Locale::getFrench(void)
785 return getLocale(eFRENCH
);
788 const Locale
& U_EXPORT2
789 Locale::getGerman(void)
791 return getLocale(eGERMAN
);
794 const Locale
& U_EXPORT2
795 Locale::getItalian(void)
797 return getLocale(eITALIAN
);
800 const Locale
& U_EXPORT2
801 Locale::getJapanese(void)
803 return getLocale(eJAPANESE
);
806 const Locale
& U_EXPORT2
807 Locale::getKorean(void)
809 return getLocale(eKOREAN
);
812 const Locale
& U_EXPORT2
813 Locale::getChinese(void)
815 return getLocale(eCHINESE
);
818 const Locale
& U_EXPORT2
819 Locale::getSimplifiedChinese(void)
821 return getLocale(eCHINA
);
824 const Locale
& U_EXPORT2
825 Locale::getTraditionalChinese(void)
827 return getLocale(eTAIWAN
);
831 const Locale
& U_EXPORT2
832 Locale::getFrance(void)
834 return getLocale(eFRANCE
);
837 const Locale
& U_EXPORT2
838 Locale::getGermany(void)
840 return getLocale(eGERMANY
);
843 const Locale
& U_EXPORT2
844 Locale::getItaly(void)
846 return getLocale(eITALY
);
849 const Locale
& U_EXPORT2
850 Locale::getJapan(void)
852 return getLocale(eJAPAN
);
855 const Locale
& U_EXPORT2
856 Locale::getKorea(void)
858 return getLocale(eKOREA
);
861 const Locale
& U_EXPORT2
862 Locale::getChina(void)
864 return getLocale(eCHINA
);
867 const Locale
& U_EXPORT2
870 return getLocale(eCHINA
);
873 const Locale
& U_EXPORT2
874 Locale::getTaiwan(void)
876 return getLocale(eTAIWAN
);
879 const Locale
& U_EXPORT2
882 return getLocale(eUK
);
885 const Locale
& U_EXPORT2
888 return getLocale(eUS
);
891 const Locale
& U_EXPORT2
892 Locale::getCanada(void)
894 return getLocale(eCANADA
);
897 const Locale
& U_EXPORT2
898 Locale::getCanadaFrench(void)
900 return getLocale(eCANADA_FRENCH
);
904 Locale::getLocale(int locid
)
906 Locale
*localeCache
= getLocaleCache();
907 U_ASSERT((locid
< eMAX_LOCALES
)&&(locid
>=0));
908 if (localeCache
== NULL
) {
909 // Failure allocating the locale cache.
910 // The best we can do is return a NULL reference.
913 return localeCache
[locid
]; /*operating on NULL*/
917 This function is defined this way in order to get around static
918 initialization and static destruction.
921 Locale::getLocaleCache(void)
924 UBool needInit
= (gLocaleCache
== NULL
);
928 Locale
*tLocaleCache
= new Locale
[(int)eMAX_LOCALES
];
929 if (tLocaleCache
== NULL
) {
932 tLocaleCache
[eROOT
] = Locale("");
933 tLocaleCache
[eENGLISH
] = Locale("en");
934 tLocaleCache
[eFRENCH
] = Locale("fr");
935 tLocaleCache
[eGERMAN
] = Locale("de");
936 tLocaleCache
[eITALIAN
] = Locale("it");
937 tLocaleCache
[eJAPANESE
] = Locale("ja");
938 tLocaleCache
[eKOREAN
] = Locale("ko");
939 tLocaleCache
[eCHINESE
] = Locale("zh");
940 tLocaleCache
[eFRANCE
] = Locale("fr", "FR");
941 tLocaleCache
[eGERMANY
] = Locale("de", "DE");
942 tLocaleCache
[eITALY
] = Locale("it", "IT");
943 tLocaleCache
[eJAPAN
] = Locale("ja", "JP");
944 tLocaleCache
[eKOREA
] = Locale("ko", "KR");
945 tLocaleCache
[eCHINA
] = Locale("zh", "CN");
946 tLocaleCache
[eTAIWAN
] = Locale("zh", "TW");
947 tLocaleCache
[eUK
] = Locale("en", "GB");
948 tLocaleCache
[eUS
] = Locale("en", "US");
949 tLocaleCache
[eCANADA
] = Locale("en", "CA");
950 tLocaleCache
[eCANADA_FRENCH
] = Locale("fr", "CA");
953 if (gLocaleCache
== NULL
) {
954 gLocaleCache
= tLocaleCache
;
956 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
960 delete [] tLocaleCache
; // Fancy array delete will destruct each member.
966 class KeywordEnumeration
: public StringEnumeration
{
971 UnicodeString currUSKey
;
972 static const char fgClassID
;/* Warning this is used beyond the typical RTTI usage. */
975 static UClassID U_EXPORT2
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
976 virtual UClassID
getDynamicClassID(void) const { return getStaticClassID(); }
978 KeywordEnumeration(const char *keys
, int32_t keywordLen
, int32_t currentIndex
, UErrorCode
&status
)
979 : keywords((char *)&fgClassID
), current((char *)&fgClassID
), length(0) {
980 if(U_SUCCESS(status
) && keywordLen
!= 0) {
981 if(keys
== NULL
|| keywordLen
< 0) {
982 status
= U_ILLEGAL_ARGUMENT_ERROR
;
984 keywords
= (char *)uprv_malloc(keywordLen
+1);
985 if (keywords
== NULL
) {
986 status
= U_MEMORY_ALLOCATION_ERROR
;
989 uprv_memcpy(keywords
, keys
, keywordLen
);
990 keywords
[keywordLen
] = 0;
991 current
= keywords
+ currentIndex
;
998 virtual ~KeywordEnumeration();
1000 virtual StringEnumeration
* clone() const
1002 UErrorCode status
= U_ZERO_ERROR
;
1003 return new KeywordEnumeration(keywords
, length
, (int32_t)(current
- keywords
), status
);
1006 virtual int32_t count(UErrorCode
&/*status*/) const {
1007 char *kw
= keywords
;
1011 kw
+= uprv_strlen(kw
)+1;
1016 virtual const char* next(int32_t* resultLength
, UErrorCode
& status
) {
1019 if(U_SUCCESS(status
) && *current
!= 0) {
1021 len
= (int32_t)uprv_strlen(current
);
1023 if(resultLength
!= NULL
) {
1024 *resultLength
= len
;
1027 if(resultLength
!= NULL
) {
1035 virtual const UnicodeString
* snext(UErrorCode
& status
) {
1036 int32_t resultLength
= 0;
1037 const char *s
= next(&resultLength
, status
);
1038 return setChars(s
, resultLength
, status
);
1041 virtual void reset(UErrorCode
& /*status*/) {
1046 const char KeywordEnumeration::fgClassID
= '\0';
1048 KeywordEnumeration::~KeywordEnumeration() {
1049 uprv_free(keywords
);
1053 Locale::createKeywords(UErrorCode
&status
) const
1056 int32_t keywordCapacity
= 256;
1057 StringEnumeration
*result
= NULL
;
1059 const char* variantStart
= uprv_strchr(fullName
, '@');
1060 const char* assignment
= uprv_strchr(fullName
, '=');
1062 if(assignment
> variantStart
) {
1063 int32_t keyLen
= locale_getKeywords(variantStart
+1, '@', keywords
, keywordCapacity
, NULL
, 0, NULL
, FALSE
, &status
);
1065 result
= new KeywordEnumeration(keywords
, keyLen
, 0, status
);
1068 status
= U_INVALID_FORMAT_ERROR
;
1075 Locale::getKeywordValue(const char* keywordName
, char *buffer
, int32_t bufLen
, UErrorCode
&status
) const
1077 return uloc_getKeywordValue(fullName
, keywordName
, buffer
, bufLen
, &status
);
1081 Locale::setKeywordValue(const char* keywordName
, const char* keywordValue
, UErrorCode
&status
)
1083 uloc_setKeywordValue(keywordName
, keywordValue
, fullName
, ULOC_FULLNAME_CAPACITY
, &status
);
1087 Locale::getBaseName() const
1090 UErrorCode status
= U_ZERO_ERROR
;
1091 // semantically const
1093 ((Locale
*)this)->baseName
= ((Locale
*)this)->baseNameBuffer
;
1094 int32_t baseNameSize
= uloc_getBaseName(fullName
, baseName
, ULOC_FULLNAME_CAPACITY
, &status
);
1095 if(baseNameSize
>= ULOC_FULLNAME_CAPACITY
) {
1096 ((Locale
*)this)->baseName
= (char *)uprv_malloc(sizeof(char) * baseNameSize
+ 1);
1097 if (baseName
== NULL
) {
1100 uloc_getBaseName(fullName
, baseName
, baseNameSize
+1, &status
);
1102 baseName
[baseNameSize
] = 0;
1104 // the computation of variantBegin leaves it equal to the length
1105 // of fullName if there is no variant. It should instead be
1106 // the length of the baseName. Patch around this for now.
1107 if (variantBegin
== (int32_t)uprv_strlen(fullName
)) {
1108 ((Locale
*)this)->variantBegin
= baseNameSize
;