2 **********************************************************************
3 * Copyright (C) 1997-2016, 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"
47 static UBool U_CALLCONV
locale_cleanup(void);
52 static Locale
*gLocaleCache
= NULL
;
53 static UInitOnce gLocaleCacheInitOnce
= U_INITONCE_INITIALIZER
;
55 // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
56 static UMutex gDefaultLocaleMutex
= U_MUTEX_INITIALIZER
;
57 static UHashtable
*gDefaultLocalesHashT
= NULL
;
58 static Locale
*gDefaultLocale
= NULL
;
62 typedef enum ELocalePos
{
76 eCHINA
, /* Alias for PRC */
89 U_CFUNC
int32_t locale_getKeywords(const char *localeID
,
91 char *keywords
, int32_t keywordCapacity
,
92 char *values
, int32_t valuesCapacity
, int32_t *valLen
,
98 // Deleter function for Locales owned by the default Locale hash table/
100 static void U_CALLCONV
101 deleteLocale(void *obj
) {
102 delete (icu::Locale
*) obj
;
105 static UBool U_CALLCONV
locale_cleanup(void)
109 delete [] gLocaleCache
;
111 gLocaleCacheInitOnce
.reset();
113 if (gDefaultLocalesHashT
) {
114 uhash_close(gDefaultLocalesHashT
); // Automatically deletes all elements, using deleter func.
115 gDefaultLocalesHashT
= NULL
;
117 gDefaultLocale
= NULL
;
122 static void U_CALLCONV
locale_init(UErrorCode
&status
) {
125 U_ASSERT(gLocaleCache
== NULL
);
126 gLocaleCache
= new Locale
[(int)eMAX_LOCALES
];
127 if (gLocaleCache
== NULL
) {
128 status
= U_MEMORY_ALLOCATION_ERROR
;
131 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
132 gLocaleCache
[eROOT
] = Locale("");
133 gLocaleCache
[eENGLISH
] = Locale("en");
134 gLocaleCache
[eFRENCH
] = Locale("fr");
135 gLocaleCache
[eGERMAN
] = Locale("de");
136 gLocaleCache
[eITALIAN
] = Locale("it");
137 gLocaleCache
[eJAPANESE
] = Locale("ja");
138 gLocaleCache
[eKOREAN
] = Locale("ko");
139 gLocaleCache
[eCHINESE
] = Locale("zh");
140 gLocaleCache
[eFRANCE
] = Locale("fr", "FR");
141 gLocaleCache
[eGERMANY
] = Locale("de", "DE");
142 gLocaleCache
[eITALY
] = Locale("it", "IT");
143 gLocaleCache
[eJAPAN
] = Locale("ja", "JP");
144 gLocaleCache
[eKOREA
] = Locale("ko", "KR");
145 gLocaleCache
[eCHINA
] = Locale("zh", "CN");
146 gLocaleCache
[eTAIWAN
] = Locale("zh", "TW");
147 gLocaleCache
[eUK
] = Locale("en", "GB");
148 gLocaleCache
[eUS
] = Locale("en", "US");
149 gLocaleCache
[eCANADA
] = Locale("en", "CA");
150 gLocaleCache
[eCANADA_FRENCH
] = Locale("fr", "CA");
157 Locale
*locale_set_default_internal(const char *id
, UErrorCode
& status
) {
158 // Synchronize this entire function.
159 Mutex
lock(&gDefaultLocaleMutex
);
161 UBool canonicalize
= FALSE
;
163 // If given a NULL string for the locale id, grab the default
164 // name from the system.
165 // (Different from most other locale APIs, where a null name means use
166 // the current ICU default locale.)
168 id
= uprv_getDefaultLocaleID(); // This function not thread safe? TODO: verify.
169 canonicalize
= TRUE
; // always canonicalize host ID
172 char localeNameBuf
[512];
175 uloc_canonicalize(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
177 uloc_getName(id
, localeNameBuf
, sizeof(localeNameBuf
)-1, &status
);
179 localeNameBuf
[sizeof(localeNameBuf
)-1] = 0; // Force null termination in event of
180 // a long name filling the buffer.
181 // (long names are truncated.)
183 if (U_FAILURE(status
)) {
184 return gDefaultLocale
;
187 if (gDefaultLocalesHashT
== NULL
) {
188 gDefaultLocalesHashT
= uhash_open(uhash_hashChars
, uhash_compareChars
, NULL
, &status
);
189 if (U_FAILURE(status
)) {
190 return gDefaultLocale
;
192 uhash_setValueDeleter(gDefaultLocalesHashT
, deleteLocale
);
193 ucln_common_registerCleanup(UCLN_COMMON_LOCALE
, locale_cleanup
);
196 Locale
*newDefault
= (Locale
*)uhash_get(gDefaultLocalesHashT
, localeNameBuf
);
197 if (newDefault
== NULL
) {
198 newDefault
= new Locale(Locale::eBOGUS
);
199 if (newDefault
== NULL
) {
200 status
= U_MEMORY_ALLOCATION_ERROR
;
201 return gDefaultLocale
;
203 newDefault
->init(localeNameBuf
, FALSE
);
204 uhash_put(gDefaultLocalesHashT
, (char*) newDefault
->getName(), newDefault
, &status
);
205 if (U_FAILURE(status
)) {
206 return gDefaultLocale
;
209 gDefaultLocale
= newDefault
;
210 return gDefaultLocale
;
217 locale_set_default(const char *id
)
220 UErrorCode status
= U_ZERO_ERROR
;
221 locale_set_default_internal(id
, status
);
226 locale_get_default(void)
229 return Locale::getDefault().getName();
235 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale
)
237 /*Character separating the posix id fields*/
239 // In the platform codepage.
244 if (baseName
!= fullName
) {
248 /*if fullName is on the heap, we free it*/
249 if (fullName
!= fullNameBuffer
)
257 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
263 * Internal constructor to allow construction of a locale object with
264 * NO side effects. (Default constructor tries to get
265 * the default locale.)
267 Locale::Locale(Locale::ELocaleType
)
268 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
274 Locale::Locale( const char * newLanguage
,
275 const char * newCountry
,
276 const char * newVariant
,
277 const char * newKeywords
)
278 : UObject(), fullName(fullNameBuffer
), baseName(NULL
)
280 if( (newLanguage
==NULL
) && (newCountry
== NULL
) && (newVariant
== NULL
) )
282 init(NULL
, FALSE
); /* shortcut */
286 MaybeStackArray
<char, ULOC_FULLNAME_CAPACITY
> togo
;
294 // Calculate the size of the resulting string.
297 if ( newLanguage
!= NULL
)
299 lsize
= (int32_t)uprv_strlen(newLanguage
);
304 if ( newCountry
!= NULL
)
306 csize
= (int32_t)uprv_strlen(newCountry
);
311 if ( newVariant
!= NULL
)
313 // remove leading _'s
314 while(newVariant
[0] == SEP_CHAR
)
319 // remove trailing _'s
320 vsize
= (int32_t)uprv_strlen(newVariant
);
321 while( (vsize
>1) && (newVariant
[vsize
-1] == SEP_CHAR
) )
335 size
+= 2; // at least: __v
337 else if ( csize
> 0 )
339 size
+= 1; // at least: _v
342 if ( newKeywords
!= NULL
)
344 ksize
= (int32_t)uprv_strlen(newKeywords
);
349 // NOW we have the full locale string..
351 /*if the whole string is longer than our internal limit, we need
352 to go to the heap for temporary buffers*/
353 if (size
>= togo
.getCapacity())
355 // If togo_heap could not be created, initialize with default settings.
356 if (togo
.resize(size
+1) == NULL
) {
363 // Now, copy it back.
367 uprv_strcpy(p
, newLanguage
);
371 if ( ( vsize
!= 0 ) || (csize
!= 0) ) // at least: __v
378 uprv_strcpy(p
, newCountry
);
384 *p
++ = SEP_CHAR
; // at least: __v
386 uprv_strncpy(p
, newVariant
, vsize
); // Must use strncpy because
387 p
+= vsize
; // of trimming (above).
393 if (uprv_strchr(newKeywords
, '=')) {
394 *p
++ = '@'; /* keyword parsing */
397 *p
++ = '_'; /* Variant parsing with a script */
399 *p
++ = '_'; /* No country found */
402 uprv_strcpy(p
, newKeywords
);
406 // Parse it, because for example 'language' might really be a complete
408 init(togo
.getAlias(), FALSE
);
412 Locale::Locale(const Locale
&other
)
413 : UObject(other
), fullName(fullNameBuffer
), baseName(NULL
)
418 Locale
&Locale::operator=(const Locale
&other
)
420 if (this == &other
) {
424 /* Free our current storage */
425 if (baseName
!= fullName
) {
429 if(fullName
!= fullNameBuffer
) {
431 fullName
= fullNameBuffer
;
434 /* Allocate the full name if necessary */
435 if(other
.fullName
!= other
.fullNameBuffer
) {
436 fullName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other
.fullName
)+1));
437 if (fullName
== NULL
) {
441 /* Copy the full name */
442 uprv_strcpy(fullName
, other
.fullName
);
444 /* Copy the baseName if it differs from fullName. */
445 if (other
.baseName
== other
.fullName
) {
448 if (other
.baseName
) {
449 baseName
= uprv_strdup(other
.baseName
);
453 /* Copy the language and country fields */
454 uprv_strcpy(language
, other
.language
);
455 uprv_strcpy(script
, other
.script
);
456 uprv_strcpy(country
, other
.country
);
458 /* The variantBegin is an offset, just copy it */
459 variantBegin
= other
.variantBegin
;
460 fIsBogus
= other
.fIsBogus
;
465 Locale::clone() const {
466 return new Locale(*this);
470 Locale::operator==( const Locale
& other
) const
472 return (uprv_strcmp(other
.fullName
, fullName
) == 0);
475 #define ISASCIIALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
477 /*This function initializes a Locale from a C locale ID*/
478 Locale
& Locale::init(const char* localeID
, UBool canonicalize
)
481 /* Free our current storage */
482 if (baseName
!= fullName
) {
486 if(fullName
!= fullNameBuffer
) {
488 fullName
= fullNameBuffer
;
492 // just an easy way to have a common error-exit
493 // without goto and without another function
496 char *field
[5] = {0};
497 int32_t fieldLen
[5] = {0};
499 int32_t variantField
;
503 if(localeID
== NULL
) {
504 // not an error, just set the default locale
505 return *this = getDefault();
508 /* preset all fields to empty */
509 language
[0] = script
[0] = country
[0] = 0;
511 // "canonicalize" the locale ID to ICU/Java format
513 length
= canonicalize
?
514 uloc_canonicalize(localeID
, fullName
, sizeof(fullNameBuffer
), &err
) :
515 uloc_getName(localeID
, fullName
, sizeof(fullNameBuffer
), &err
);
517 if(err
== U_BUFFER_OVERFLOW_ERROR
|| length
>= (int32_t)sizeof(fullNameBuffer
)) {
518 /*Go to heap for the fullName if necessary*/
519 fullName
= (char *)uprv_malloc(sizeof(char)*(length
+ 1));
521 fullName
= fullNameBuffer
;
522 break; // error: out of memory
525 length
= canonicalize
?
526 uloc_canonicalize(localeID
, fullName
, length
+1, &err
) :
527 uloc_getName(localeID
, fullName
, length
+1, &err
);
529 if(U_FAILURE(err
) || err
== U_STRING_NOT_TERMINATED_WARNING
) {
530 /* should never occur */
534 variantBegin
= length
;
536 /* after uloc_getName/canonicalize() we know that only '_' are separators */
537 separator
= field
[0] = fullName
;
539 while ((separator
= uprv_strchr(field
[fieldIdx
-1], SEP_CHAR
)) && fieldIdx
< UPRV_LENGTHOF(field
)-1) {
540 field
[fieldIdx
] = separator
+ 1;
541 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
544 // variant may contain @foo or .foo POSIX cruft; remove it
545 separator
= uprv_strchr(field
[fieldIdx
-1], '@');
546 char* sep2
= uprv_strchr(field
[fieldIdx
-1], '.');
547 if (separator
!=NULL
|| sep2
!=NULL
) {
548 if (separator
==NULL
|| (sep2
!=NULL
&& separator
> sep2
)) {
551 fieldLen
[fieldIdx
-1] = (int32_t)(separator
- field
[fieldIdx
-1]);
553 fieldLen
[fieldIdx
-1] = length
- (int32_t)(field
[fieldIdx
-1] - fullName
);
556 if (fieldLen
[0] >= (int32_t)(sizeof(language
)))
558 break; // error: the language field is too long
561 variantField
= 1; /* Usually the 2nd one, except when a script or country is also used. */
562 if (fieldLen
[0] > 0) {
563 /* We have a language */
564 uprv_memcpy(language
, fullName
, fieldLen
[0]);
565 language
[fieldLen
[0]] = 0;
567 if (fieldLen
[1] == 4 && ISASCIIALPHA(field
[1][0]) &&
568 ISASCIIALPHA(field
[1][1]) && ISASCIIALPHA(field
[1][2]) &&
569 ISASCIIALPHA(field
[1][3])) {
570 /* We have at least a script */
571 uprv_memcpy(script
, field
[1], fieldLen
[1]);
572 script
[fieldLen
[1]] = 0;
576 if (fieldLen
[variantField
] == 2 || fieldLen
[variantField
] == 3) {
577 /* We have a country */
578 uprv_memcpy(country
, field
[variantField
], fieldLen
[variantField
]);
579 country
[fieldLen
[variantField
]] = 0;
581 } else if (fieldLen
[variantField
] == 0) {
582 variantField
++; /* script or country empty but variant in next field (i.e. en__POSIX) */
585 if (fieldLen
[variantField
] > 0) {
586 /* We have a variant */
587 variantBegin
= (int32_t)(field
[variantField
] - fullName
);
592 if (U_FAILURE(err
)) {
596 // successful end of init()
598 } while(0); /*loop doesn't iterate*/
600 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
607 * Set up the base name.
608 * If there are no key words, it's exactly the full name.
609 * If key words exist, it's the full name truncated at the '@' character.
610 * Need to set up both at init() and after setting a keyword.
613 Locale::initBaseName(UErrorCode
&status
) {
614 if (U_FAILURE(status
)) {
617 U_ASSERT(baseName
==NULL
|| baseName
==fullName
);
618 const char *atPtr
= uprv_strchr(fullName
, '@');
619 const char *eqPtr
= uprv_strchr(fullName
, '=');
620 if (atPtr
&& eqPtr
&& atPtr
< eqPtr
) {
622 int32_t baseNameLength
= (int32_t)(atPtr
- fullName
);
623 baseName
= (char *)uprv_malloc(baseNameLength
+ 1);
624 if (baseName
== NULL
) {
625 status
= U_MEMORY_ALLOCATION_ERROR
;
628 uprv_strncpy(baseName
, fullName
, baseNameLength
);
629 baseName
[baseNameLength
] = 0;
631 // The original computation of variantBegin leaves it equal to the length
632 // of fullName if there is no variant. It should instead be
633 // the length of the baseName.
634 if (variantBegin
> baseNameLength
) {
635 variantBegin
= baseNameLength
;
644 Locale::hashCode() const
646 return ustr_hashCharsN(fullName
, uprv_strlen(fullName
));
650 Locale::setToBogus() {
651 /* Free our current storage */
652 if(baseName
!= fullName
) {
656 if(fullName
!= fullNameBuffer
) {
658 fullName
= fullNameBuffer
;
667 const Locale
& U_EXPORT2
671 Mutex
lock(&gDefaultLocaleMutex
);
672 if (gDefaultLocale
!= NULL
) {
673 return *gDefaultLocale
;
676 UErrorCode status
= U_ZERO_ERROR
;
677 return *locale_set_default_internal(NULL
, status
);
683 Locale::setDefault( const Locale
& newLocale
,
686 if (U_FAILURE(status
)) {
690 /* Set the default from the full name string of the supplied locale.
691 * This is a convenient way to access the default locale caching mechanisms.
693 const char *localeID
= newLocale
.getName();
694 locale_set_default_internal(localeID
, status
);
698 Locale::createFromName (const char *name
)
711 Locale::createCanonical(const char* name
) {
713 loc
.init(name
, TRUE
);
718 Locale::getISO3Language() const
720 return uloc_getISO3Language(fullName
);
725 Locale::getISO3Country() const
727 return uloc_getISO3Country(fullName
);
731 * Return the LCID value as specified in the "LocaleID" resource for this
732 * locale. The LocaleID must be expressed as a hexadecimal number, from
733 * one to four digits. If the LocaleID resource is not present, or is
734 * in an incorrect format, 0 is returned. The LocaleID is for use in
735 * Windows (it is an LCID), but is available on all platforms.
738 Locale::getLCID() const
740 return uloc_getLCID(fullName
);
743 const char* const* U_EXPORT2
Locale::getISOCountries()
745 return uloc_getISOCountries();
748 const char* const* U_EXPORT2
Locale::getISOLanguages()
750 return uloc_getISOLanguages();
753 // Set the locale's data based on a posix id.
754 void Locale::setFromPOSIXID(const char *posixID
)
759 const Locale
& U_EXPORT2
760 Locale::getRoot(void)
762 return getLocale(eROOT
);
765 const Locale
& U_EXPORT2
766 Locale::getEnglish(void)
768 return getLocale(eENGLISH
);
771 const Locale
& U_EXPORT2
772 Locale::getFrench(void)
774 return getLocale(eFRENCH
);
777 const Locale
& U_EXPORT2
778 Locale::getGerman(void)
780 return getLocale(eGERMAN
);
783 const Locale
& U_EXPORT2
784 Locale::getItalian(void)
786 return getLocale(eITALIAN
);
789 const Locale
& U_EXPORT2
790 Locale::getJapanese(void)
792 return getLocale(eJAPANESE
);
795 const Locale
& U_EXPORT2
796 Locale::getKorean(void)
798 return getLocale(eKOREAN
);
801 const Locale
& U_EXPORT2
802 Locale::getChinese(void)
804 return getLocale(eCHINESE
);
807 const Locale
& U_EXPORT2
808 Locale::getSimplifiedChinese(void)
810 return getLocale(eCHINA
);
813 const Locale
& U_EXPORT2
814 Locale::getTraditionalChinese(void)
816 return getLocale(eTAIWAN
);
820 const Locale
& U_EXPORT2
821 Locale::getFrance(void)
823 return getLocale(eFRANCE
);
826 const Locale
& U_EXPORT2
827 Locale::getGermany(void)
829 return getLocale(eGERMANY
);
832 const Locale
& U_EXPORT2
833 Locale::getItaly(void)
835 return getLocale(eITALY
);
838 const Locale
& U_EXPORT2
839 Locale::getJapan(void)
841 return getLocale(eJAPAN
);
844 const Locale
& U_EXPORT2
845 Locale::getKorea(void)
847 return getLocale(eKOREA
);
850 const Locale
& U_EXPORT2
851 Locale::getChina(void)
853 return getLocale(eCHINA
);
856 const Locale
& U_EXPORT2
859 return getLocale(eCHINA
);
862 const Locale
& U_EXPORT2
863 Locale::getTaiwan(void)
865 return getLocale(eTAIWAN
);
868 const Locale
& U_EXPORT2
871 return getLocale(eUK
);
874 const Locale
& U_EXPORT2
877 return getLocale(eUS
);
880 const Locale
& U_EXPORT2
881 Locale::getCanada(void)
883 return getLocale(eCANADA
);
886 const Locale
& U_EXPORT2
887 Locale::getCanadaFrench(void)
889 return getLocale(eCANADA_FRENCH
);
893 Locale::getLocale(int locid
)
895 Locale
*localeCache
= getLocaleCache();
896 U_ASSERT((locid
< eMAX_LOCALES
)&&(locid
>=0));
897 if (localeCache
== NULL
) {
898 // Failure allocating the locale cache.
899 // The best we can do is return a NULL reference.
902 return localeCache
[locid
]; /*operating on NULL*/
906 This function is defined this way in order to get around static
907 initialization and static destruction.
910 Locale::getLocaleCache(void)
912 UErrorCode status
= U_ZERO_ERROR
;
913 umtx_initOnce(gLocaleCacheInitOnce
, locale_init
, status
);
917 class KeywordEnumeration
: public StringEnumeration
{
922 UnicodeString currUSKey
;
923 static const char fgClassID
;/* Warning this is used beyond the typical RTTI usage. */
926 static UClassID U_EXPORT2
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
927 virtual UClassID
getDynamicClassID(void) const { return getStaticClassID(); }
929 KeywordEnumeration(const char *keys
, int32_t keywordLen
, int32_t currentIndex
, UErrorCode
&status
)
930 : keywords((char *)&fgClassID
), current((char *)&fgClassID
), length(0) {
931 if(U_SUCCESS(status
) && keywordLen
!= 0) {
932 if(keys
== NULL
|| keywordLen
< 0) {
933 status
= U_ILLEGAL_ARGUMENT_ERROR
;
935 keywords
= (char *)uprv_malloc(keywordLen
+1);
936 if (keywords
== NULL
) {
937 status
= U_MEMORY_ALLOCATION_ERROR
;
940 uprv_memcpy(keywords
, keys
, keywordLen
);
941 keywords
[keywordLen
] = 0;
942 current
= keywords
+ currentIndex
;
949 virtual ~KeywordEnumeration();
951 virtual StringEnumeration
* clone() const
953 UErrorCode status
= U_ZERO_ERROR
;
954 return new KeywordEnumeration(keywords
, length
, (int32_t)(current
- keywords
), status
);
957 virtual int32_t count(UErrorCode
&/*status*/) const {
962 kw
+= uprv_strlen(kw
)+1;
967 virtual const char* next(int32_t* resultLength
, UErrorCode
& status
) {
970 if(U_SUCCESS(status
) && *current
!= 0) {
972 len
= (int32_t)uprv_strlen(current
);
974 if(resultLength
!= NULL
) {
978 if(resultLength
!= NULL
) {
986 virtual const UnicodeString
* snext(UErrorCode
& status
) {
987 int32_t resultLength
= 0;
988 const char *s
= next(&resultLength
, status
);
989 return setChars(s
, resultLength
, status
);
992 virtual void reset(UErrorCode
& /*status*/) {
997 const char KeywordEnumeration::fgClassID
= '\0';
999 KeywordEnumeration::~KeywordEnumeration() {
1000 uprv_free(keywords
);
1004 Locale::createKeywords(UErrorCode
&status
) const
1007 int32_t keywordCapacity
= 256;
1008 StringEnumeration
*result
= NULL
;
1010 const char* variantStart
= uprv_strchr(fullName
, '@');
1011 const char* assignment
= uprv_strchr(fullName
, '=');
1013 if(assignment
> variantStart
) {
1014 int32_t keyLen
= locale_getKeywords(variantStart
+1, '@', keywords
, keywordCapacity
, NULL
, 0, NULL
, FALSE
, &status
);
1016 result
= new KeywordEnumeration(keywords
, keyLen
, 0, status
);
1019 status
= U_INVALID_FORMAT_ERROR
;
1026 Locale::getKeywordValue(const char* keywordName
, char *buffer
, int32_t bufLen
, UErrorCode
&status
) const
1028 return uloc_getKeywordValue(fullName
, keywordName
, buffer
, bufLen
, &status
);
1032 Locale::setKeywordValue(const char* keywordName
, const char* keywordValue
, UErrorCode
&status
)
1034 uloc_setKeywordValue(keywordName
, keywordValue
, fullName
, ULOC_FULLNAME_CAPACITY
, &status
);
1035 if (U_SUCCESS(status
) && baseName
== fullName
) {
1036 // May have added the first keyword, meaning that the fullName is no longer also the baseName.
1037 initBaseName(status
);
1042 Locale::getBaseName() const {