2
**********************************************************************
3
* Copyright (C) 1997-2001, 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"
43
static Locale* availableLocaleList = NULL;
44
static int32_t availableLocaleListCount;
45
typedef enum ELocalePos {
59
eCHINA, /* Alias for PRC */
71
/* Use void * to make it properly aligned */
72
/* Add 1 for rounding */
73
static void *gByteLocaleCache[(eMAX_LOCALES + 1) * sizeof(Locale) / sizeof(void*)];
75
static Locale *gLocaleCache = NULL;
84
if (availableLocaleList) {
85
delete []availableLocaleList;
86
availableLocaleList = NULL;
88
availableLocaleListCount = 0;
90
gLocaleCache[eDEFAULT].~Locale();
97
void locale_set_default_internal(const char *id)
101
#ifdef ICU_LOCID_USE_DEPRECATES
102
Locale::fgDefaultLocale.init(id);
104
if (gLocaleCache == NULL) {
105
Locale::initLocaleCache();
110
gLocaleCache[eDEFAULT].init(id);
118
locale_set_default(const char *id)
122
locale_set_default_internal(id);
127
locale_get_default(void)
131
return Locale::getDefault().getName();
137
/*Character separating the posix id fields*/
139
// In the platform codepage.
145
#ifdef ICU_LOCID_USE_DEPRECATES
146
Locale Locale::fgDefaultLocale;
149
* Constant definitions
151
const Locale Locale::ENGLISH("en");
152
const Locale Locale::FRENCH("fr");
153
const Locale Locale::GERMAN("de");
154
const Locale Locale::ITALIAN("it");
155
const Locale Locale::JAPANESE("ja");
156
const Locale Locale::KOREAN("ko");
157
const Locale Locale::CHINESE("zh");
158
const Locale Locale::SIMPLIFIED_CHINESE("zh", "CN");
159
const Locale Locale::TRADITIONAL_CHINESE("zh", "TW");
161
// Useful constant for country.
163
const Locale Locale::FRANCE ("fr", "FR");
164
const Locale Locale::GERMANY ("de", "DE");
165
const Locale Locale::ITALY ("it", "IT");
166
const Locale Locale::JAPAN ("ja", "JP");
167
const Locale Locale::KOREA ("ko", "KR");
168
const Locale Locale::CHINA ("zh", "CN");
169
const Locale Locale::PRC ("zh", "CN");
170
const Locale Locale::TAIWAN ("zh", "TW");
171
const Locale Locale::UK ("en", "GB");
172
const Locale Locale::US ("en", "US");
173
const Locale Locale::CANADA ("en", "CA");
174
const Locale Locale::CANADA_FRENCH("fr", "CA");
177
const Locale::LocaleProxy Locale::ENGLISH = {eENGLISH};
178
const Locale::LocaleProxy Locale::FRENCH = {eFRENCH};
179
const Locale::LocaleProxy Locale::GERMAN = {eGERMAN};
180
const Locale::LocaleProxy Locale::ITALIAN = {eITALIAN};
181
const Locale::LocaleProxy Locale::JAPANESE = {eJAPANESE};
182
const Locale::LocaleProxy Locale::KOREAN = {eKOREAN};
183
const Locale::LocaleProxy Locale::CHINESE = {eCHINESE};
184
const Locale::LocaleProxy Locale::SIMPLIFIED_CHINESE={eCHINA};
185
const Locale::LocaleProxy Locale::TRADITIONAL_CHINESE={eTAIWAN};
187
const Locale::LocaleProxy Locale::FRANCE = {eFRANCE};
188
const Locale::LocaleProxy Locale::GERMANY = {eGERMANY};
189
const Locale::LocaleProxy Locale::ITALY = {eITALY};
190
const Locale::LocaleProxy Locale::JAPAN = {eJAPAN};
191
const Locale::LocaleProxy Locale::KOREA = {eKOREA};
192
const Locale::LocaleProxy Locale::CHINA = {eCHINA};
193
const Locale::LocaleProxy Locale::PRC = {eCHINA};
194
const Locale::LocaleProxy Locale::TAIWAN = {eTAIWAN};
195
const Locale::LocaleProxy Locale::UK = {eUK};
196
const Locale::LocaleProxy Locale::US = {eUS};
197
const Locale::LocaleProxy Locale::CANADA = {eCANADA};
198
const Locale::LocaleProxy Locale::CANADA_FRENCH={eCANADA_FRENCH};
200
Locale::LocaleProxy::operator const Locale&(void) const
202
return Locale::getLocale(magicLocaleNumber);
209
/*if fullName is on the heap, we free it*/
210
if (fullName != fullNameBuffer)
218
: fullName(fullNameBuffer)
223
Locale::Locale( const char * newLanguage,
224
const char * newCountry,
225
const char * newVariant)
226
: fullName(fullNameBuffer)
228
if( (newLanguage==NULL) && (newCountry == NULL) && (newVariant == NULL) )
230
init(NULL); /* shortcut */
234
char togo_stack[ULOC_FULLNAME_CAPACITY];
236
char *togo_heap = NULL;
243
// Calculate the size of the resulting string.
246
if ( newLanguage != NULL )
248
lsize = (int32_t)uprv_strlen(newLanguage);
253
if ( newCountry != NULL )
255
csize = (int32_t)uprv_strlen(newCountry);
260
if ( newVariant != NULL )
262
// remove leading _'s
263
while(newVariant[0] == SEP_CHAR)
268
// remove trailing _'s
269
vsize = (int32_t)uprv_strlen(newVariant);
270
while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) )
284
size += 2; // at least: __v
286
else if ( csize > 0 )
288
size += 1; // at least: _v
291
// NOW we have the full locale string..
293
/*if the whole string is longer than our internal limit, we need
294
to go to the heap for temporary buffers*/
295
if (size > ULOC_FULLNAME_CAPACITY)
297
togo_heap = (char *)uprv_malloc(sizeof(char)*(size+1));
307
// Now, copy it back.
311
uprv_strcpy(p, newLanguage);
315
if ( ( vsize != 0 ) || (csize != 0) ) // at least: __v
322
uprv_strcpy(p, newCountry);
328
*p++ = SEP_CHAR; // at least: __v
330
uprv_strncpy(p, newVariant, vsize); // Must use strncpy because
331
p += vsize; // of trimming (above).
335
// Parse it, because for example 'language' might really be a complete
340
uprv_free(togo_heap);
345
Locale::Locale(const Locale &other)
346
: fullName(fullNameBuffer)
351
Locale &Locale::operator=(const Locale &other)
353
/* Free our current storage */
354
if(fullName != fullNameBuffer) {
356
fullName = fullNameBuffer;
359
/* Allocate the full name if necessary */
360
if(other.fullName != other.fullNameBuffer) {
361
fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)+1));
364
/* Copy the full name */
365
uprv_strcpy(fullName, other.fullName);
367
/* Copy the language and country fields */
368
uprv_strcpy(language, other.language);
369
uprv_strcpy(country, other.country);
371
/* The variantBegin is an offset into fullName, just copy it */
372
variantBegin = other.variantBegin;
373
fIsBogus = other.fIsBogus;
378
Locale::operator==( const Locale& other) const
380
return (uprv_strcmp(other.fullName, fullName) == 0);
383
/*This function initializes a Locale from a C locale ID*/
384
Locale& Locale::init(const char* localeID)
387
/* Free our current storage */
388
if(fullName != fullNameBuffer) {
390
fullName = fullNameBuffer;
394
// just an easy way to have a common error-exit
395
// without goto and without another function
397
char *separator, *prev;
401
if(localeID == NULL) {
402
// not an error, just set the default locale
406
// "canonicalize" the locale ID to ICU/Java format
408
length = uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
409
if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
410
/*Go to heap for the fullName if necessary*/
411
fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
413
fullName = fullNameBuffer;
417
length = uloc_getName(localeID, fullName, length + 1, &err);
419
if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
420
/* should never occur */
424
/* preset all fields to empty */
425
language[0] = country[0] = 0;
426
variantBegin = uprv_strlen(fullName);
428
/* after uloc_getName() we know that only '_' are separators */
429
separator = uprv_strchr(fullName, SEP_CHAR);
431
/* there is a country field */
432
length = separator - fullName;
434
if(length >= (int32_t)sizeof(language)) {
437
uprv_memcpy(language, fullName, length);
439
language[length] = 0;
441
prev = separator + 1;
442
separator = uprv_strchr(prev, SEP_CHAR);
444
/* there is a variant field */
445
length = separator - prev;
447
if(length >= (int32_t)sizeof(country)) {
450
uprv_memcpy(country, prev, length);
454
variantBegin = (separator + 1) - fullName;
456
/* variantBegin==strlen(fullName), length==strlen(language)==prev-1-fullName */
457
if((variantBegin - length - 1) >= (int32_t)sizeof(country)) {
460
uprv_strcpy(country, prev);
463
/* variantBegin==strlen(fullName) */
464
if(variantBegin >= (int32_t)sizeof(language)) {
467
uprv_strcpy(language, fullName);
470
// successful end of init()
475
// when an error occurs, then set the default locale (there is no UErrorCode here)
476
return *this = getLocale(eDEFAULT);
479
// Prevent any possible infinite recursion
480
// for bad default Locale IDs
486
Locale::hashCode() const
489
hashKey.pointer = fullName;
490
return uhash_hashChars(hashKey);
494
Locale::setToBogus() {
495
/* Free our current storage */
496
if(fullName != fullNameBuffer) {
498
fullName = fullNameBuffer;
509
#ifdef ICU_LOCID_USE_DEPRECATES
510
return fgDefaultLocale;
512
return getLocale(eDEFAULT);
517
Locale::setDefault( const Locale& newLocale,
520
if (U_FAILURE(status))
523
#ifdef ICU_LOCID_USE_DEPRECATES
524
fgDefaultLocale = newLocale;
526
if (gLocaleCache == NULL) {
532
gLocaleCache[eDEFAULT] = newLocale;
538
Locale::createFromName (const char *name)
552
Locale::getISO3Language() const
554
return uloc_getISO3Language(fullName);
559
Locale::getISO3Country() const
561
return uloc_getISO3Country(fullName);
565
* Return the LCID value as specified in the "LocaleID" resource for this
566
* locale. The LocaleID must be expressed as a hexadecimal number, from
567
* one to four digits. If the LocaleID resource is not present, or is
568
* in an incorrect format, 0 is returned. The LocaleID is for use in
569
* Windows (it is an LCID), but is available on all platforms.
572
Locale::getLCID() const
574
return uloc_getLCID(fullName);
578
Locale::getDisplayLanguage(UnicodeString& dispLang) const
580
return this->getDisplayLanguage(getDefault(), dispLang);
583
/*We cannot make any assumptions on the size of the output display strings
584
* Yet, since we are calling through to a C API, we need to set limits on
585
* buffer size. For all the following getDisplay functions we first attempt
586
* to fill up a stack allocated buffer. If it is to small we heap allocated
587
* the exact buffer we need copy it to the UnicodeString and delete it*/
590
Locale::getDisplayLanguage(const Locale &displayLocale,
591
UnicodeString &result) const {
593
UErrorCode errorCode=U_ZERO_ERROR;
596
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
602
length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
603
buffer, result.getCapacity(),
605
result.releaseBuffer(length);
607
if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
608
buffer=result.getBuffer(length);
613
errorCode=U_ZERO_ERROR;
614
length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
615
buffer, result.getCapacity(),
617
result.releaseBuffer(length);
620
if(U_FAILURE(errorCode)) {
628
Locale::getDisplayCountry(UnicodeString& dispCntry) const
630
return this->getDisplayCountry(getDefault(), dispCntry);
634
Locale::getDisplayCountry(const Locale &displayLocale,
635
UnicodeString &result) const {
637
UErrorCode errorCode=U_ZERO_ERROR;
640
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
646
length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
647
buffer, result.getCapacity(),
649
result.releaseBuffer(length);
651
if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
652
buffer=result.getBuffer(length);
657
errorCode=U_ZERO_ERROR;
658
length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
659
buffer, result.getCapacity(),
661
result.releaseBuffer(length);
664
if(U_FAILURE(errorCode)) {
672
Locale::getDisplayVariant(UnicodeString& dispVar) const
674
return this->getDisplayVariant(getDefault(), dispVar);
678
Locale::getDisplayVariant(const Locale &displayLocale,
679
UnicodeString &result) const {
681
UErrorCode errorCode=U_ZERO_ERROR;
684
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
690
length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
691
buffer, result.getCapacity(),
693
result.releaseBuffer(length);
695
if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
696
buffer=result.getBuffer(length);
701
errorCode=U_ZERO_ERROR;
702
length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
703
buffer, result.getCapacity(),
705
result.releaseBuffer(length);
708
if(U_FAILURE(errorCode)) {
716
Locale::getDisplayName( UnicodeString& name ) const
718
return this->getDisplayName(getDefault(), name);
722
Locale::getDisplayName(const Locale &displayLocale,
723
UnicodeString &result) const {
725
UErrorCode errorCode=U_ZERO_ERROR;
728
buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
734
length=uloc_getDisplayName(fullName, displayLocale.fullName,
735
buffer, result.getCapacity(),
737
result.releaseBuffer(length);
739
if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
740
buffer=result.getBuffer(length);
745
errorCode=U_ZERO_ERROR;
746
length=uloc_getDisplayName(fullName, displayLocale.fullName,
747
buffer, result.getCapacity(),
749
result.releaseBuffer(length);
752
if(U_FAILURE(errorCode)) {
759
Locale::getAvailableLocales(int32_t& count)
761
// for now, there is a hardcoded list, so just walk through that list and set it up.
762
if (availableLocaleList == 0) {
763
int32_t locCount = uloc_countAvailable();
764
Locale *newLocaleList = new Locale[locCount];
768
while(--locCount >= 0) {
769
newLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
773
if(availableLocaleList != 0) {
774
delete []newLocaleList;
777
availableLocaleListCount = count;
778
availableLocaleList = newLocaleList;
781
count = availableLocaleListCount;
782
return availableLocaleList;
785
const char* const* Locale::getISOCountries()
787
return uloc_getISOCountries();
790
const char* const* Locale::getISOLanguages()
792
return uloc_getISOLanguages();
795
// Set the locale's data based on a posix id.
796
void Locale::setFromPOSIXID(const char *posixID)
801
#ifndef ICU_LOCID_USE_DEPRECATES
803
Locale::getEnglish(void)
805
return getLocale(eENGLISH);
809
Locale::getFrench(void)
811
return getLocale(eFRENCH);
815
Locale::getGerman(void)
817
return getLocale(eGERMAN);
821
Locale::getItalian(void)
823
return getLocale(eITALIAN);
827
Locale::getJapanese(void)
829
return getLocale(eJAPANESE);
833
Locale::getKorean(void)
835
return getLocale(eKOREAN);
839
Locale::getChinese(void)
841
return getLocale(eCHINESE);
845
Locale::getSimplifiedChinese(void)
847
return getLocale(eCHINA);
851
Locale::getTraditionalChinese(void)
853
return getLocale(eTAIWAN);
858
Locale::getFrance(void)
860
return getLocale(eFRANCE);
864
Locale::getGermany(void)
866
return getLocale(eGERMANY);
870
Locale::getItaly(void)
872
return getLocale(eITALY);
876
Locale::getJapan(void)
878
return getLocale(eJAPAN);
882
Locale::getKorea(void)
884
return getLocale(eKOREA);
888
Locale::getChina(void)
890
return getLocale(eCHINA);
896
return getLocale(eCHINA);
900
Locale::getTaiwan(void)
902
return getLocale(eTAIWAN);
908
return getLocale(eUK);
914
return getLocale(eUS);
918
Locale::getCanada(void)
920
return getLocale(eCANADA);
924
Locale::getCanadaFrench(void)
926
return getLocale(eCANADA_FRENCH);
930
Locale::getLocale(int locid)
933
return gLocaleCache[locid];
938
return gLocaleCache[locid];
942
This function is defined this way in order to get around static
943
initialization and static destruction.
946
Locale::initLocaleCache(void)
948
const char *defaultLocale = uprv_getDefaultLocaleID();
949
// Can't use empty parameters, or we'll call this function again.
950
Locale newLocales[] = {
969
Locale(defaultLocale)
971
Locale *localeCache = (Locale *)(gByteLocaleCache);
975
if (gLocaleCache != NULL) {
978
uprv_memcpy(gByteLocaleCache, newLocales, sizeof(newLocales));
980
for (int idx = 0; idx < eMAX_LOCALES; idx++)
982
if (localeCache[idx].fullName == newLocales[idx].fullNameBuffer)
984
localeCache[idx].fullName = localeCache[idx].fullNameBuffer;
988
// Since we did a memcpy we need to make sure that the local
989
// Locales do not destroy the memory of the permanent locales.
991
// This can be a memory leak for an extra long default locale,
992
// but this code shouldn't normally get executed.
993
localeCache[idx].fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(localeCache[idx].fullNameBuffer) + 1));
994
uprv_strcpy(localeCache[idx].fullName, localeCache[idx].fullNameBuffer);
997
gLocaleCache = localeCache;