2 **********************************************************************
3 * Copyright (C) 1997-2010, 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 typedef enum ELocalePos
{
58 eCHINA
, /* Alias for PRC */
71 U_CFUNC
int32_t locale_getKeywords(const char *localeID
,
73 char *keywords
, int32_t keywordCapacity
,
74 char *values
, int32_t valuesCapacity
, int32_t *valLen
,
78 static U_NAMESPACE_QUALIFIER Locale
*gLocaleCache
= NULL
;
79 static U_NAMESPACE_QUALIFIER Locale
*gDefaultLocale
= NULL
;
80 static UHashtable
*gDefaultLocalesHashT
= NULL
;
84 // Deleter function for Locales owned by the default Locale hash table/
86 static void U_CALLCONV
87 deleteLocale(void *obj
) {
88 delete (U_NAMESPACE_QUALIFIER Locale
*) obj
;
91 static UBool U_CALLCONV
locale_cleanup(void)
96 delete [] gLocaleCache
;
100 if (gDefaultLocalesHashT
) {
101 uhash_close(gDefaultLocalesHashT
); // Automatically deletes all elements, using deleter func.
102 gDefaultLocalesHashT
= NULL
;
104 else if (gDefaultLocale
) {
105 // The cache wasn't created, and only one default locale was created.
106 delete gDefaultLocale
;
108 gDefaultLocale
= NULL
;
116 // locale_set_default_internal.
118 void locale_set_default_internal(const char *id
)
120 UErrorCode status
= U_ZERO_ERROR
;
121 UBool canonicalize
= FALSE
;
123 // If given a NULL string for the locale id, grab the default
124 // name from the system.
125 // (Different from most other locale APIs, where a null name means use
126 // the current ICU default locale.)
129 id
= uprv_getDefaultLocaleID();
131 canonicalize
= TRUE
; // always canonicalize host ID
134 // put the locale id into a canonical form,
135 // in preparation for looking up this locale in the hash table of
136 // already-created locale objects.
138 status
= U_ZERO_ERROR
;
139 char localeNameBuf
[512];
142 uloc_canonicalize(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
144 uloc_getName(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
146 localeNameBuf
[sizeof(localeNameBuf
)-1] = 0; // Force null termination in event of
147 // a long name filling the buffer.
148 // (long names are truncated.)
150 // Lazy creation of the hash table itself, if needed.
152 UMTX_CHECK(NULL
, (gDefaultLocale
== NULL
), isOnlyLocale
);
154 // We haven't seen this locale id before.
155 // Create a new Locale object for it.
156 Locale
*newFirstDefault
= new Locale(Locale::eBOGUS
);
157 if (newFirstDefault
== NULL
) {
158 // No way to report errors from here.
161 newFirstDefault
->init(localeNameBuf
, FALSE
);
163 if (gDefaultLocale
== NULL
) {
164 gDefaultLocale
= newFirstDefault
; // Assignment to gDefaultLocale must happen inside mutex
165 newFirstDefault
= NULL
;
166 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
168 // We were successful in setting the locale, and we were the first one to set it.
172 // Else some other thread raced us through here, and set the new Locale.
174 delete newFirstDefault
;
179 // Create the hash table next, unless the racing thread is setting the same locale as default.
180 // The new locale might have been set while a racing thread was stuck at the lock
181 // earlier in this function. (For example, see uprv_getDefaultLocaleID above).
183 // Only create the hash table if we need to.
184 if (uprv_strcmp(gDefaultLocale
->getName(), localeNameBuf
) == 0) {
189 // start using the hash table.
192 // Lazy creation of the hash table itself, if needed.
193 UBool hashTableNeedsInit
;
194 UMTX_CHECK(NULL
, (gDefaultLocalesHashT
== NULL
), hashTableNeedsInit
);
195 if (hashTableNeedsInit
) {
196 status
= U_ZERO_ERROR
;
197 UHashtable
*tHashTable
= uhash_open(uhash_hashChars
, uhash_compareChars
, NULL
, &status
);
198 if (U_FAILURE(status
)) {
201 uhash_setValueDeleter(tHashTable
, deleteLocale
);
203 if (gDefaultLocalesHashT
== NULL
) {
204 gDefaultLocalesHashT
= tHashTable
;
205 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
207 uhash_put(gDefaultLocalesHashT
, (void *)gDefaultLocale
->getName(), gDefaultLocale
, &status
);
209 uhash_close(tHashTable
);
214 // Hash table lookup, key is the locale full name
216 Locale
*newDefault
= (Locale
*)uhash_get(gDefaultLocalesHashT
, localeNameBuf
);
217 if (newDefault
!= NULL
) {
218 // We have the requested locale in the hash table already.
219 // Just set it as default. Inside the mutex lock, for those troublesome processors.
220 gDefaultLocale
= newDefault
;
224 // We haven't seen this locale id before.
225 // Create a new Locale object for it.
226 newDefault
= new Locale(Locale::eBOGUS
);
227 if (newDefault
== NULL
) {
228 // No way to report errors from here.
231 newDefault
->init(localeNameBuf
, FALSE
);
233 // Add newly created Locale to the hash table of default Locales
234 const char *key
= newDefault
->getName();
235 U_ASSERT(uprv_strcmp(key
, localeNameBuf
) == 0);
237 Locale
*hashTableVal
= (Locale
*)uhash_get(gDefaultLocalesHashT
, key
);
238 if (hashTableVal
== NULL
) {
239 uhash_put(gDefaultLocalesHashT
, (void *)key
, newDefault
, &status
);
240 gDefaultLocale
= newDefault
;
241 // ignore errors from hash table insert. (Couldn't do anything anyway)
242 // We can still set the default Locale,
243 // it just wont be cached, and will eventually leak.
245 // Some other thread raced us through here, and got the new Locale
246 // into the hash table before us. Use that one.
247 gDefaultLocale
= hashTableVal
; // Assignment to gDefaultLocale must happen inside mutex
257 locale_set_default(const char *id
)
260 locale_set_default_internal(id
);
265 locale_get_default(void)
269 return Locale::getDefault().getName();
275 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale
)
277 /*Character separating the posix id fields*/
279 // In the platform codepage.
284 /*if fullName is on the heap, we free it*/
285 if (fullName
!= fullNameBuffer
)
290 if (baseName
&& baseName
!= baseNameBuffer
) {
297 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
303 * Internal constructor to allow construction of a locale object with
304 * NO side effects. (Default constructor tries to get
305 * the default locale.)
307 Locale::Locale(Locale::ELocaleType
)
308 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
314 Locale::Locale( const char * newLanguage
,
315 const char * newCountry
,
316 const char * newVariant
,
317 const char * newKeywords
)
318 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
320 if( (newLanguage
==NULL
) && (newCountry
== NULL
) && (newVariant
== NULL
) )
322 init(NULL
, FALSE
); /* shortcut */
326 MaybeStackArray
<char, ULOC_FULLNAME_CAPACITY
> togo
;
334 // Calculate the size of the resulting string.
337 if ( newLanguage
!= NULL
)
339 lsize
= (int32_t)uprv_strlen(newLanguage
);
344 if ( newCountry
!= NULL
)
346 csize
= (int32_t)uprv_strlen(newCountry
);
351 if ( newVariant
!= NULL
)
353 // remove leading _'s
354 while(newVariant
[0] == SEP_CHAR
)
359 // remove trailing _'s
360 vsize
= (int32_t)uprv_strlen(newVariant
);
361 while( (vsize
>1) && (newVariant
[vsize
-1] == SEP_CHAR
) )
375 size
+= 2; // at least: __v
377 else if ( csize
> 0 )
379 size
+= 1; // at least: _v
382 if ( newKeywords
!= NULL
)
384 ksize
= (int32_t)uprv_strlen(newKeywords
);
389 // NOW we have the full locale string..
391 /*if the whole string is longer than our internal limit, we need
392 to go to the heap for temporary buffers*/
393 if (size
>= togo
.getCapacity())
395 // If togo_heap could not be created, initialize with default settings.
396 if (togo
.resize(size
+1) == NULL
) {
403 // Now, copy it back.
407 uprv_strcpy(p
, newLanguage
);
411 if ( ( vsize
!= 0 ) || (csize
!= 0) ) // at least: __v
418 uprv_strcpy(p
, newCountry
);
424 *p
++ = SEP_CHAR
; // at least: __v
426 uprv_strncpy(p
, newVariant
, vsize
); // Must use strncpy because
427 p
+= vsize
; // of trimming (above).
433 if (uprv_strchr(newKeywords
, '=')) {
434 *p
++ = '@'; /* keyword parsing */
437 *p
++ = '_'; /* Variant parsing with a script */
439 *p
++ = '_'; /* No country found */
442 uprv_strcpy(p
, newKeywords
);
446 // Parse it, because for example 'language' might really be a complete
448 init(togo
.getAlias(), FALSE
);
452 Locale::Locale(const Locale
&other
)
453 : UObject(other
), fullName(fullNameBuffer
), baseName(NULL
)
458 Locale
&Locale::operator=(const Locale
&other
)
460 if (this == &other
) {
464 if (&other
== NULL
) {
469 /* Free our current storage */
470 if(fullName
!= fullNameBuffer
) {
472 fullName
= fullNameBuffer
;
475 /* Allocate the full name if necessary */
476 if(other
.fullName
!= other
.fullNameBuffer
) {
477 fullName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other
.fullName
)+1));
478 if (fullName
== NULL
) {
482 /* Copy the full name */
483 uprv_strcpy(fullName
, other
.fullName
);
485 /* baseName is the cached result of getBaseName. if 'other' has a
486 baseName and it fits in baseNameBuffer, then copy it. otherwise set
487 it to NULL, and let the user lazy-create it (in getBaseName) if they
489 if(baseName
&& baseName
!= baseNameBuffer
) {
494 if(other
.baseName
== other
.baseNameBuffer
) {
495 uprv_strcpy(baseNameBuffer
, other
.baseNameBuffer
);
496 baseName
= baseNameBuffer
;
499 /* Copy the language and country fields */
500 uprv_strcpy(language
, other
.language
);
501 uprv_strcpy(script
, other
.script
);
502 uprv_strcpy(country
, other
.country
);
504 /* The variantBegin is an offset, just copy it */
505 variantBegin
= other
.variantBegin
;
506 fIsBogus
= other
.fIsBogus
;
511 Locale::clone() const {
512 return new Locale(*this);
516 Locale::operator==( const Locale
& other
) const
518 return (uprv_strcmp(other
.fullName
, fullName
) == 0);
521 /*This function initializes a Locale from a C locale ID*/
522 Locale
& Locale::init(const char* localeID
, UBool canonicalize
)
525 /* Free our current storage */
526 if(fullName
!= fullNameBuffer
) {
528 fullName
= fullNameBuffer
;
531 if(baseName
&& baseName
!= baseNameBuffer
) {
537 // just an easy way to have a common error-exit
538 // without goto and without another function
541 char *field
[5] = {0};
542 int32_t fieldLen
[5] = {0};
544 int32_t variantField
;
548 if(localeID
== NULL
) {
549 // not an error, just set the default locale
550 return *this = getDefault();
553 /* preset all fields to empty */
554 language
[0] = script
[0] = country
[0] = 0;
556 // "canonicalize" the locale ID to ICU/Java format
558 length
= canonicalize
?
559 uloc_canonicalize(localeID
, fullName
, sizeof(fullNameBuffer
), &err
) :
560 uloc_getName(localeID
, fullName
, sizeof(fullNameBuffer
), &err
);
562 if(err
== U_BUFFER_OVERFLOW_ERROR
|| length
>= (int32_t)sizeof(fullNameBuffer
)) {
563 /*Go to heap for the fullName if necessary*/
564 fullName
= (char *)uprv_malloc(sizeof(char)*(length
+ 1));
566 fullName
= fullNameBuffer
;
567 break; // error: out of memory
570 length
= canonicalize
?
571 uloc_canonicalize(localeID
, fullName
, length
+1, &err
) :
572 uloc_getName(localeID
, fullName
, length
+1, &err
);
574 if(U_FAILURE(err
) || err
== U_STRING_NOT_TERMINATED_WARNING
) {
575 /* should never occur */
579 variantBegin
= length
;
581 /* after uloc_getName/canonicalize() we know that only '_' are separators */
582 separator
= field
[0] = fullName
;
584 while ((separator
= uprv_strchr(field
[fieldIdx
-1], SEP_CHAR
)) && fieldIdx
< (int32_t)(sizeof(field
)/sizeof(field
[0]))-1) {
585 field
[fieldIdx
] = separator
+ 1;
586 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
589 // variant may contain @foo or .foo POSIX cruft; remove it
590 separator
= uprv_strchr(field
[fieldIdx
-1], '@');
591 char* sep2
= uprv_strchr(field
[fieldIdx
-1], '.');
592 if (separator
!=NULL
|| sep2
!=NULL
) {
593 if (separator
==NULL
|| (sep2
!=NULL
&& separator
> sep2
)) {
596 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
598 fieldLen
[fieldIdx
-1] = length
- (int32_t)(field
[fieldIdx
-1] - fullName
);
601 if (fieldLen
[0] >= (int32_t)(sizeof(language
))
602 || (fieldLen
[1] == 4 && fieldLen
[2] >= (int32_t)(sizeof(country
)))
603 || (fieldLen
[1] != 4 && fieldLen
[1] >= (int32_t)(sizeof(country
))))
605 break; // error: one of the fields is too long
608 variantField
= 2; /* Usually the 2nd one, except when a script is used. */
609 if (fieldLen
[0] > 0) {
610 /* We have a language */
611 uprv_memcpy(language
, fullName
, fieldLen
[0]);
612 language
[fieldLen
[0]] = 0;
614 if (fieldLen
[1] == 4) {
615 /* We have at least a script */
616 uprv_memcpy(script
, field
[1], fieldLen
[1]);
617 script
[fieldLen
[1]] = 0;
619 if (fieldLen
[2] > 0) {
620 /* We have a country */
621 uprv_memcpy(country
, field
[2], fieldLen
[2]);
622 country
[fieldLen
[2]] = 0;
625 else if (fieldLen
[1] > 0) {
626 /* We have a country and no script */
627 uprv_memcpy(country
, field
[1], fieldLen
[1]);
628 country
[fieldLen
[1]] = 0;
630 if (variantField
> 0 && fieldLen
[variantField
] > 0) {
631 /* We have a variant */
632 variantBegin
= (int32_t)(field
[variantField
] - fullName
);
635 // successful end of init()
637 } while(0); /*loop doesn't iterate*/
639 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
646 Locale::hashCode() const
649 hashKey
.pointer
= fullName
;
650 return uhash_hashChars(hashKey
);
654 Locale::setToBogus() {
655 /* Free our current storage */
656 if(fullName
!= fullNameBuffer
) {
658 fullName
= fullNameBuffer
;
660 if(baseName
&& baseName
!= baseNameBuffer
) {
671 const Locale
& U_EXPORT2
674 const Locale
*retLocale
;
675 UMTX_CHECK(NULL
, gDefaultLocale
, retLocale
);
676 if (retLocale
== NULL
) {
677 locale_set_default_internal(NULL
);
679 // Need a mutex in case some other thread set a new
680 // default inbetween when we set and when we get the new default. For
681 // processors with weak memory coherency, we might not otherwise see all
682 // of the newly created new default locale.
683 retLocale
= gDefaultLocale
;
692 Locale::setDefault( const Locale
& newLocale
,
695 if (U_FAILURE(status
)) {
699 /* Set the default from the full name string of the supplied locale.
700 * This is a convenient way to access the default locale caching mechanisms.
702 const char *localeID
= newLocale
.getName();
703 locale_set_default_internal(localeID
);
707 Locale::createFromName (const char *name
)
720 Locale::createCanonical(const char* name
) {
722 loc
.init(name
, TRUE
);
727 Locale::getISO3Language() const
729 return uloc_getISO3Language(fullName
);
734 Locale::getISO3Country() const
736 return uloc_getISO3Country(fullName
);
740 * Return the LCID value as specified in the "LocaleID" resource for this
741 * locale. The LocaleID must be expressed as a hexadecimal number, from
742 * one to four digits. If the LocaleID resource is not present, or is
743 * in an incorrect format, 0 is returned. The LocaleID is for use in
744 * Windows (it is an LCID), but is available on all platforms.
747 Locale::getLCID() const
749 return uloc_getLCID(fullName
);
752 const char* const* U_EXPORT2
Locale::getISOCountries()
754 return uloc_getISOCountries();
757 const char* const* U_EXPORT2
Locale::getISOLanguages()
759 return uloc_getISOLanguages();
762 // Set the locale's data based on a posix id.
763 void Locale::setFromPOSIXID(const char *posixID
)
768 const Locale
& U_EXPORT2
769 Locale::getRoot(void)
771 return getLocale(eROOT
);
774 const Locale
& U_EXPORT2
775 Locale::getEnglish(void)
777 return getLocale(eENGLISH
);
780 const Locale
& U_EXPORT2
781 Locale::getFrench(void)
783 return getLocale(eFRENCH
);
786 const Locale
& U_EXPORT2
787 Locale::getGerman(void)
789 return getLocale(eGERMAN
);
792 const Locale
& U_EXPORT2
793 Locale::getItalian(void)
795 return getLocale(eITALIAN
);
798 const Locale
& U_EXPORT2
799 Locale::getJapanese(void)
801 return getLocale(eJAPANESE
);
804 const Locale
& U_EXPORT2
805 Locale::getKorean(void)
807 return getLocale(eKOREAN
);
810 const Locale
& U_EXPORT2
811 Locale::getChinese(void)
813 return getLocale(eCHINESE
);
816 const Locale
& U_EXPORT2
817 Locale::getSimplifiedChinese(void)
819 return getLocale(eCHINA
);
822 const Locale
& U_EXPORT2
823 Locale::getTraditionalChinese(void)
825 return getLocale(eTAIWAN
);
829 const Locale
& U_EXPORT2
830 Locale::getFrance(void)
832 return getLocale(eFRANCE
);
835 const Locale
& U_EXPORT2
836 Locale::getGermany(void)
838 return getLocale(eGERMANY
);
841 const Locale
& U_EXPORT2
842 Locale::getItaly(void)
844 return getLocale(eITALY
);
847 const Locale
& U_EXPORT2
848 Locale::getJapan(void)
850 return getLocale(eJAPAN
);
853 const Locale
& U_EXPORT2
854 Locale::getKorea(void)
856 return getLocale(eKOREA
);
859 const Locale
& U_EXPORT2
860 Locale::getChina(void)
862 return getLocale(eCHINA
);
865 const Locale
& U_EXPORT2
868 return getLocale(eCHINA
);
871 const Locale
& U_EXPORT2
872 Locale::getTaiwan(void)
874 return getLocale(eTAIWAN
);
877 const Locale
& U_EXPORT2
880 return getLocale(eUK
);
883 const Locale
& U_EXPORT2
886 return getLocale(eUS
);
889 const Locale
& U_EXPORT2
890 Locale::getCanada(void)
892 return getLocale(eCANADA
);
895 const Locale
& U_EXPORT2
896 Locale::getCanadaFrench(void)
898 return getLocale(eCANADA_FRENCH
);
902 Locale::getLocale(int locid
)
904 Locale
*localeCache
= getLocaleCache();
905 U_ASSERT((locid
< eMAX_LOCALES
)&&(locid
>=0));
906 if (localeCache
== NULL
) {
907 // Failure allocating the locale cache.
908 // The best we can do is return a NULL reference.
911 return localeCache
[locid
]; /*operating on NULL*/
915 This function is defined this way in order to get around static
916 initialization and static destruction.
919 Locale::getLocaleCache(void)
922 UBool needInit
= (gLocaleCache
== NULL
);
926 Locale
*tLocaleCache
= new Locale
[(int)eMAX_LOCALES
];
927 if (tLocaleCache
== NULL
) {
930 tLocaleCache
[eROOT
] = Locale("");
931 tLocaleCache
[eENGLISH
] = Locale("en");
932 tLocaleCache
[eFRENCH
] = Locale("fr");
933 tLocaleCache
[eGERMAN
] = Locale("de");
934 tLocaleCache
[eITALIAN
] = Locale("it");
935 tLocaleCache
[eJAPANESE
] = Locale("ja");
936 tLocaleCache
[eKOREAN
] = Locale("ko");
937 tLocaleCache
[eCHINESE
] = Locale("zh");
938 tLocaleCache
[eFRANCE
] = Locale("fr", "FR");
939 tLocaleCache
[eGERMANY
] = Locale("de", "DE");
940 tLocaleCache
[eITALY
] = Locale("it", "IT");
941 tLocaleCache
[eJAPAN
] = Locale("ja", "JP");
942 tLocaleCache
[eKOREA
] = Locale("ko", "KR");
943 tLocaleCache
[eCHINA
] = Locale("zh", "CN");
944 tLocaleCache
[eTAIWAN
] = Locale("zh", "TW");
945 tLocaleCache
[eUK
] = Locale("en", "GB");
946 tLocaleCache
[eUS
] = Locale("en", "US");
947 tLocaleCache
[eCANADA
] = Locale("en", "CA");
948 tLocaleCache
[eCANADA_FRENCH
] = Locale("fr", "CA");
951 if (gLocaleCache
== NULL
) {
952 gLocaleCache
= tLocaleCache
;
954 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
958 delete [] tLocaleCache
; // Fancy array delete will destruct each member.
964 class KeywordEnumeration
: public StringEnumeration
{
969 UnicodeString currUSKey
;
970 static const char fgClassID
;/* Warning this is used beyond the typical RTTI usage. */
973 static UClassID U_EXPORT2
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
974 virtual UClassID
getDynamicClassID(void) const { return getStaticClassID(); }
976 KeywordEnumeration(const char *keys
, int32_t keywordLen
, int32_t currentIndex
, UErrorCode
&status
)
977 : keywords((char *)&fgClassID
), current((char *)&fgClassID
), length(0) {
978 if(U_SUCCESS(status
) && keywordLen
!= 0) {
979 if(keys
== NULL
|| keywordLen
< 0) {
980 status
= U_ILLEGAL_ARGUMENT_ERROR
;
982 keywords
= (char *)uprv_malloc(keywordLen
+1);
983 if (keywords
== NULL
) {
984 status
= U_MEMORY_ALLOCATION_ERROR
;
987 uprv_memcpy(keywords
, keys
, keywordLen
);
988 keywords
[keywordLen
] = 0;
989 current
= keywords
+ currentIndex
;
996 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';
1049 Locale::createKeywords(UErrorCode
&status
) const
1052 int32_t keywordCapacity
= 256;
1053 StringEnumeration
*result
= NULL
;
1055 const char* variantStart
= uprv_strchr(fullName
, '@');
1056 const char* assignment
= uprv_strchr(fullName
, '=');
1058 if(assignment
> variantStart
) {
1059 int32_t keyLen
= locale_getKeywords(variantStart
+1, '@', keywords
, keywordCapacity
, NULL
, 0, NULL
, FALSE
, &status
);
1061 result
= new KeywordEnumeration(keywords
, keyLen
, 0, status
);
1064 status
= U_INVALID_FORMAT_ERROR
;
1071 Locale::getKeywordValue(const char* keywordName
, char *buffer
, int32_t bufLen
, UErrorCode
&status
) const
1073 return uloc_getKeywordValue(fullName
, keywordName
, buffer
, bufLen
, &status
);
1077 Locale::setKeywordValue(const char* keywordName
, const char* keywordValue
, UErrorCode
&status
)
1079 uloc_setKeywordValue(keywordName
, keywordValue
, fullName
, ULOC_FULLNAME_CAPACITY
, &status
);
1083 Locale::getBaseName() const
1086 UErrorCode status
= U_ZERO_ERROR
;
1087 // semantically const
1089 ((Locale
*)this)->baseName
= ((Locale
*)this)->baseNameBuffer
;
1090 int32_t baseNameSize
= uloc_getBaseName(fullName
, baseName
, ULOC_FULLNAME_CAPACITY
, &status
);
1091 if(baseNameSize
>= ULOC_FULLNAME_CAPACITY
) {
1092 ((Locale
*)this)->baseName
= (char *)uprv_malloc(sizeof(char) * baseNameSize
+ 1);
1093 if (baseName
== NULL
) {
1096 uloc_getBaseName(fullName
, baseName
, baseNameSize
+1, &status
);
1098 baseName
[baseNameSize
] = 0;
1100 // the computation of variantBegin leaves it equal to the length
1101 // of fullName if there is no variant. It should instead be
1102 // the length of the baseName. Patch around this for now.
1103 if (variantBegin
== (int32_t)uprv_strlen(fullName
)) {
1104 ((Locale
*)this)->variantBegin
= baseNameSize
;