]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/locid.cpp
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / common / locid.cpp
1 /*
2 **********************************************************************
3 * Copyright (C) 1997-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
6 *
7 * File locid.cpp
8 *
9 * Created by: Richard Gillam
10 *
11 * Modification History:
12 *
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
17 * of getName().
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 ******************************************************************************
30 */
31
32
33 #include "unicode/locid.h"
34 #include "unicode/uloc.h"
35 #include "umutex.h"
36 #include "uassert.h"
37 #include "cmemory.h"
38 #include "cstring.h"
39 #include "uhash.h"
40 #include "ucln_cmn.h"
41
42 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
43
44 static Locale* availableLocaleList = NULL;
45 static int32_t availableLocaleListCount;
46 typedef enum ELocalePos {
47 eENGLISH,
48 eFRENCH,
49 eGERMAN,
50 eITALIAN,
51 eJAPANESE,
52 eKOREAN,
53 eCHINESE,
54
55 eFRANCE,
56 eGERMANY,
57 eITALY,
58 eJAPAN,
59 eKOREA,
60 eCHINA, /* Alias for PRC */
61 eTAIWAN,
62 eUK,
63 eUS,
64 eCANADA,
65 eCANADA_FRENCH,
66
67
68 //eDEFAULT,
69 eMAX_LOCALES
70 } ELocalePos;
71
72 U_CFUNC int32_t locale_getKeywords(const char *localeID,
73 char prev,
74 char *keywords, int32_t keywordCapacity,
75 char *values, int32_t valuesCapacity, int32_t *valLen,
76 UBool valuesToo,
77 UErrorCode *status);
78
79 static Locale *gLocaleCache = NULL;
80 static const Locale *gDefaultLocale = NULL;
81 static UHashtable *gDefaultLocalesHashT = NULL;
82
83 U_CDECL_BEGIN
84 //
85 // Deleter function for Locales owned by the default Locale hash table/
86 //
87 static void U_CALLCONV
88 deleteLocale(void *obj) {
89 delete (Locale *) obj;
90 }
91
92 static UBool U_CALLCONV locale_cleanup(void)
93 {
94 U_NAMESPACE_USE
95
96 if (availableLocaleList) {
97 delete []availableLocaleList;
98 availableLocaleList = NULL;
99 }
100 availableLocaleListCount = 0;
101
102 if (gLocaleCache) {
103 delete [] gLocaleCache;
104 gLocaleCache = NULL;
105 }
106
107 if (gDefaultLocalesHashT) {
108 uhash_close(gDefaultLocalesHashT); // Automatically deletes all elements, using deleter func.
109 gDefaultLocalesHashT = NULL;
110 }
111 gDefaultLocale = NULL;
112
113 return TRUE;
114 }
115 U_CDECL_END
116
117 U_NAMESPACE_BEGIN
118 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale)
119
120 //
121 // locale_set_default_internal.
122 //
123 void locale_set_default_internal(const char *id)
124 {
125 U_NAMESPACE_USE
126 UErrorCode status = U_ZERO_ERROR;
127 UBool canonicalize = FALSE;
128
129 // If given a NULL string for the locale id, grab the default
130 // name from the system.
131 // (Different from most other locale APIs, where a null name means use
132 // the current ICU default locale.)
133 if (id == NULL) {
134 umtx_lock(NULL);
135 id = uprv_getDefaultLocaleID();
136 umtx_unlock(NULL);
137 canonicalize = TRUE; // always canonicalize host ID
138 }
139
140 // put the locale id into a canonical form,
141 // in preparation for looking up this locale in the hash table of
142 // already-created locale objects.
143 //
144 status = U_ZERO_ERROR;
145 char localeNameBuf[512];
146
147 if (canonicalize) {
148 uloc_canonicalize(id, localeNameBuf, sizeof(localeNameBuf)-1, &status);
149 } else {
150 uloc_getName(id, localeNameBuf, sizeof(localeNameBuf)-1, &status);
151 }
152 localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of
153 // a long name filling the buffer.
154 // (long names are truncated.)
155
156 // Lazy creation of the hash table itself, if needed.
157 //
158 umtx_lock(NULL);
159 UBool hashTableNeedsInit = (gDefaultLocalesHashT == NULL);
160 umtx_unlock(NULL);
161 if (hashTableNeedsInit) {
162 status = U_ZERO_ERROR;
163 UHashtable *tHashTable = uhash_open(uhash_hashChars, uhash_compareChars, &status);
164 if (U_FAILURE(status)) {
165 return;
166 }
167 uhash_setValueDeleter(tHashTable, deleteLocale);
168 umtx_lock(NULL);
169 if (gDefaultLocalesHashT == NULL) {
170 gDefaultLocalesHashT = tHashTable;
171 ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
172 umtx_unlock(NULL);
173 } else {
174 umtx_unlock(NULL);
175 uhash_close(tHashTable);
176 }
177 }
178
179 // Hash table lookup, key is the locale full name
180 umtx_lock(NULL);
181 Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf);
182 if (newDefault != NULL) {
183 // We have the requested locale in the hash table already.
184 // Just set it as default. Inside the mutex lock, for those troublesome processors.
185 gDefaultLocale = newDefault;
186 umtx_unlock(NULL);
187 } else {
188 umtx_unlock(NULL);
189 // We haven't seen this locale id before.
190 // Create a new Locale object for it.
191 newDefault = new Locale(Locale::eBOGUS);
192 if (newDefault == NULL) {
193 // No way to report errors from here.
194 return;
195 }
196 newDefault->init(localeNameBuf, FALSE);
197
198 // Add newly created Locale to the hash table of default Locales
199 const char *key = newDefault->getName();
200 U_ASSERT(uprv_strcmp(key, localeNameBuf) == 0);
201 umtx_lock(NULL);
202 const Locale *hashTableVal = (const Locale *)uhash_get(gDefaultLocalesHashT, key);
203 if (hashTableVal == NULL) {
204 uhash_put(gDefaultLocalesHashT, (void *)key, newDefault, &status);
205 gDefaultLocale = newDefault;
206 umtx_unlock(NULL);
207 // ignore errors from hash table insert. (Couldn't do anything anyway)
208 // We can still set the default Locale,
209 // it just wont be cached, and will eventually leak.
210 } else {
211 // Some other thread raced us through here, and got the new Locale
212 // into the hash table before us. Use that one.
213 gDefaultLocale = hashTableVal; // Assignment to gDefaultLocale must happen inside mutex
214 umtx_unlock(NULL);
215 delete newDefault;
216 }
217 }
218 }
219 U_NAMESPACE_END
220
221
222 /* sfb 07/21/99 */
223 U_CFUNC void
224 locale_set_default(const char *id)
225 {
226 U_NAMESPACE_USE
227 locale_set_default_internal(id);
228 }
229 /* end */
230
231 U_CFUNC const char *
232 locale_get_default(void)
233 {
234 U_NAMESPACE_USE
235
236 return Locale::getDefault().getName();
237 }
238
239
240 U_NAMESPACE_BEGIN
241
242 /*Character separating the posix id fields*/
243 // '_'
244 // In the platform codepage.
245 #define SEP_CHAR '_'
246
247 Locale::~Locale()
248 {
249 /*if fullName is on the heap, we free it*/
250 if (fullName != fullNameBuffer)
251 {
252 uprv_free(fullName);
253 fullName = NULL;
254 }
255 if (baseName && baseName != baseNameBuffer) {
256 uprv_free(baseName);
257 baseName = NULL;
258 }
259 }
260
261 Locale::Locale()
262 : UObject(), fullName(fullNameBuffer), baseName(NULL)
263 {
264 init(NULL, FALSE);
265 }
266
267 /*
268 * Internal constructor to allow construction of a locale object with
269 * NO side effects. (Default constructor tries to get
270 * the default locale.)
271 */
272 Locale::Locale(Locale::ELocaleType)
273 : UObject(), fullName(fullNameBuffer), baseName(NULL)
274 {
275 setToBogus();
276 }
277
278
279 Locale::Locale( const char * newLanguage,
280 const char * newCountry,
281 const char * newVariant,
282 const char * newKeywords)
283 : UObject(), fullName(fullNameBuffer), baseName(NULL)
284 {
285 if( (newLanguage==NULL) && (newCountry == NULL) && (newVariant == NULL) )
286 {
287 init(NULL, FALSE); /* shortcut */
288 }
289 else
290 {
291 char togo_stack[ULOC_FULLNAME_CAPACITY];
292 char *togo;
293 char *togo_heap = NULL;
294 int32_t size = 0;
295 int32_t lsize = 0;
296 int32_t csize = 0;
297 int32_t vsize = 0;
298 int32_t ksize = 0;
299 char *p;
300
301 // Calculate the size of the resulting string.
302
303 // Language
304 if ( newLanguage != NULL )
305 {
306 lsize = (int32_t)uprv_strlen(newLanguage);
307 size = lsize;
308 }
309
310 // _Country
311 if ( newCountry != NULL )
312 {
313 csize = (int32_t)uprv_strlen(newCountry);
314 size += csize;
315 }
316
317 // _Variant
318 if ( newVariant != NULL )
319 {
320 // remove leading _'s
321 while(newVariant[0] == SEP_CHAR)
322 {
323 newVariant++;
324 }
325
326 // remove trailing _'s
327 vsize = (int32_t)uprv_strlen(newVariant);
328 while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) )
329 {
330 vsize--;
331 }
332 }
333
334 if( vsize > 0 )
335 {
336 size += vsize;
337 }
338
339 // Separator rules:
340 if ( vsize > 0 )
341 {
342 size += 2; // at least: __v
343 }
344 else if ( csize > 0 )
345 {
346 size += 1; // at least: _v
347 }
348
349 if ( newKeywords != NULL)
350 {
351 ksize = (int32_t)uprv_strlen(newKeywords);
352 size += ksize + 1;
353 }
354
355
356 // NOW we have the full locale string..
357
358 /*if the whole string is longer than our internal limit, we need
359 to go to the heap for temporary buffers*/
360 if (size > ULOC_FULLNAME_CAPACITY)
361 {
362 togo_heap = (char *)uprv_malloc(sizeof(char)*(size+1));
363 togo = togo_heap;
364 }
365 else
366 {
367 togo = togo_stack;
368 }
369
370 togo[0] = 0;
371
372 // Now, copy it back.
373 p = togo;
374 if ( lsize != 0 )
375 {
376 uprv_strcpy(p, newLanguage);
377 p += lsize;
378 }
379
380 if ( ( vsize != 0 ) || (csize != 0) ) // at least: __v
381 { // ^
382 *p++ = SEP_CHAR;
383 }
384
385 if ( csize != 0 )
386 {
387 uprv_strcpy(p, newCountry);
388 p += csize;
389 }
390
391 if ( vsize != 0)
392 {
393 *p++ = SEP_CHAR; // at least: __v
394
395 uprv_strncpy(p, newVariant, vsize); // Must use strncpy because
396 p += vsize; // of trimming (above).
397 *p = 0; // terminate
398 }
399
400 if ( ksize != 0)
401 {
402 if (uprv_strchr(newKeywords, '=')) {
403 *p++ = '@'; /* keyword parsing */
404 }
405 else {
406 *p++ = '_'; /* Variant parsing with a script */
407 if ( vsize == 0) {
408 *p++ = '_'; /* No country found */
409 }
410 }
411 uprv_strcpy(p, newKeywords);
412 p += ksize;
413 }
414
415 // Parse it, because for example 'language' might really be a complete
416 // string.
417 init(togo, FALSE);
418
419 if (togo_heap) {
420 uprv_free(togo_heap);
421 }
422 }
423 }
424
425 Locale::Locale(const Locale &other)
426 : UObject(other), fullName(fullNameBuffer), baseName(NULL)
427 {
428 *this = other;
429 }
430
431 Locale &Locale::operator=(const Locale &other)
432 {
433 if (this == &other) {
434 return *this;
435 }
436
437 if (&other == NULL) {
438 this->setToBogus();
439 return *this;
440 }
441
442 /* Free our current storage */
443 if(fullName != fullNameBuffer) {
444 uprv_free(fullName);
445 fullName = fullNameBuffer;
446 }
447
448 /* Allocate the full name if necessary */
449 if(other.fullName != other.fullNameBuffer) {
450 fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)+1));
451 }
452 /* Copy the full name */
453 uprv_strcpy(fullName, other.fullName);
454
455 /* baseName is the cached result of getBaseName. if 'other' has a
456 baseName and it fits in baseNameBuffer, then copy it. otherwise set
457 it to NULL, and let the user lazy-create it (in getBaseName) if they
458 want it. */
459 if(baseName && baseName != baseNameBuffer) {
460 uprv_free(baseName);
461 }
462 baseName = NULL;
463
464 if(other.baseName == other.baseNameBuffer) {
465 uprv_strcpy(baseNameBuffer, other.baseNameBuffer);
466 baseName = baseNameBuffer;
467 }
468
469 /* Copy the language and country fields */
470 uprv_strcpy(language, other.language);
471 uprv_strcpy(script, other.script);
472 uprv_strcpy(country, other.country);
473
474 /* The variantBegin is an offset into fullName, just copy it */
475 variantBegin = other.variantBegin;
476 fIsBogus = other.fIsBogus;
477 return *this;
478 }
479
480 Locale *
481 Locale::clone() const {
482 return new Locale(*this);
483 }
484
485 UBool
486 Locale::operator==( const Locale& other) const
487 {
488 return (uprv_strcmp(other.fullName, fullName) == 0);
489 }
490
491 /*This function initializes a Locale from a C locale ID*/
492 Locale& Locale::init(const char* localeID, UBool canonicalize)
493 {
494 fIsBogus = FALSE;
495 /* Free our current storage */
496 if(fullName != fullNameBuffer) {
497 uprv_free(fullName);
498 fullName = fullNameBuffer;
499 }
500
501 if(baseName && baseName != baseNameBuffer) {
502 uprv_free(baseName);
503 baseName = NULL;
504 }
505
506 // not a loop:
507 // just an easy way to have a common error-exit
508 // without goto and without another function
509 do {
510 char *separator;
511 char *field[5] = {0};
512 int32_t fieldLen[5] = {0};
513 int32_t fieldIdx;
514 int32_t variantField;
515 int32_t length;
516 UErrorCode err;
517
518 if(localeID == NULL) {
519 // not an error, just set the default locale
520 return *this = getDefault();
521 }
522
523 /* preset all fields to empty */
524 language[0] = script[0] = country[0] = 0;
525
526 // "canonicalize" the locale ID to ICU/Java format
527 err = U_ZERO_ERROR;
528 length = canonicalize ?
529 uloc_canonicalize(localeID, fullName, sizeof(fullNameBuffer), &err) :
530 uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
531
532 if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameBuffer)) {
533 /*Go to heap for the fullName if necessary*/
534 fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
535 if(fullName == 0) {
536 fullName = fullNameBuffer;
537 break; // error: out of memory
538 }
539 err = U_ZERO_ERROR;
540 length = canonicalize ?
541 uloc_canonicalize(localeID, fullName, length+1, &err) :
542 uloc_getName(localeID, fullName, length+1, &err);
543 }
544 if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
545 /* should never occur */
546 break;
547 }
548
549 variantBegin = length;
550
551 /* after uloc_getName/canonicalize() we know that only '_' are separators */
552 separator = field[0] = fullName;
553 fieldIdx = 1;
554 while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) && fieldIdx < (int32_t)(sizeof(field)/sizeof(field[0]))-1) {
555 field[fieldIdx] = separator + 1;
556 fieldLen[fieldIdx-1] = separator - field[fieldIdx-1];
557 fieldIdx++;
558 }
559 // variant may contain @foo or .foo POSIX cruft; remove it
560 separator = uprv_strchr(field[fieldIdx-1], '@');
561 char* sep2 = uprv_strchr(field[fieldIdx-1], '.');
562 if (separator!=NULL || sep2!=NULL) {
563 if (separator==NULL || (sep2!=NULL && separator > sep2)) {
564 separator = sep2;
565 }
566 fieldLen[fieldIdx-1] = separator - field[fieldIdx-1];
567 } else {
568 fieldLen[fieldIdx-1] = length - (int32_t)(field[fieldIdx-1] - fullName);
569 }
570
571 if (fieldLen[0] >= (int32_t)(sizeof(language))
572 || (fieldLen[1] == 4 && fieldLen[2] >= (int32_t)(sizeof(country)))
573 || (fieldLen[1] != 4 && fieldLen[1] >= (int32_t)(sizeof(country))))
574 {
575 break; // error: one of the fields is too long
576 }
577
578 variantField = 2; /* Usually the 2nd one, except when a script is used. */
579 if (fieldLen[0] > 0) {
580 /* We have a language */
581 uprv_memcpy(language, fullName, fieldLen[0]);
582 language[fieldLen[0]] = 0;
583 }
584 if (fieldLen[1] == 4) {
585 /* We have at least a script */
586 uprv_memcpy(script, field[1], fieldLen[1]);
587 script[fieldLen[1]] = 0;
588 variantField = 3;
589 if (fieldLen[2] > 0) {
590 /* We have a country */
591 uprv_memcpy(country, field[2], fieldLen[2]);
592 country[fieldLen[2]] = 0;
593 }
594 }
595 else if (fieldLen[1] > 0) {
596 /* We have a country and no script */
597 uprv_memcpy(country, field[1], fieldLen[1]);
598 country[fieldLen[1]] = 0;
599 }
600 if (variantField > 0 && fieldLen[variantField] > 0) {
601 /* We have a variant */
602 variantBegin = (int32_t)(field[variantField] - fullName);
603 }
604
605 // successful end of init()
606 return *this;
607 } while(0);
608
609 // when an error occurs, then set this object to "bogus" (there is no UErrorCode here)
610 setToBogus();
611
612 return *this;
613 }
614
615 int32_t
616 Locale::hashCode() const
617 {
618 UHashTok hashKey;
619 hashKey.pointer = fullName;
620 return uhash_hashChars(hashKey);
621 }
622
623 void
624 Locale::setToBogus() {
625 /* Free our current storage */
626 if(fullName != fullNameBuffer) {
627 uprv_free(fullName);
628 fullName = fullNameBuffer;
629 }
630 *fullNameBuffer = 0;
631 *language = 0;
632 *script = 0;
633 *country = 0;
634 fIsBogus = TRUE;
635 }
636
637 const Locale& U_EXPORT2
638 Locale::getDefault()
639 {
640 const Locale *retLocale;
641 umtx_lock(NULL);
642 retLocale = gDefaultLocale;
643 umtx_unlock(NULL);
644 if (retLocale == NULL) {
645 locale_set_default_internal(NULL);
646 umtx_lock(NULL);
647 // Need a mutex in case some other thread set a new
648 // default inbetween when we set and when we get the new default. For
649 // processors with weak memory coherency, we might not otherwise see all
650 // of the newly created new default locale.
651 retLocale = gDefaultLocale;
652 umtx_unlock(NULL);
653 }
654 return *retLocale;
655 }
656
657
658
659 void U_EXPORT2
660 Locale::setDefault( const Locale& newLocale,
661 UErrorCode& status)
662 {
663 if (U_FAILURE(status)) {
664 return;
665 }
666
667 /* Set the default from the full name string of the supplied locale.
668 * This is a convenient way to access the default locale caching mechanisms.
669 */
670 const char *localeID = newLocale.getName();
671 locale_set_default_internal(localeID);
672 }
673
674 Locale U_EXPORT2
675 Locale::createFromName (const char *name)
676 {
677 if (name) {
678 Locale l("");
679 l.init(name, FALSE);
680 return l;
681 }
682 else {
683 return getDefault();
684 }
685 }
686
687 Locale U_EXPORT2
688 Locale::createCanonical(const char* name) {
689 Locale loc("");
690 loc.init(name, TRUE);
691 return loc;
692 }
693
694 const char *
695 Locale::getISO3Language() const
696 {
697 return uloc_getISO3Language(fullName);
698 }
699
700
701 const char *
702 Locale::getISO3Country() const
703 {
704 return uloc_getISO3Country(fullName);
705 }
706
707 /**
708 * Return the LCID value as specified in the "LocaleID" resource for this
709 * locale. The LocaleID must be expressed as a hexadecimal number, from
710 * one to four digits. If the LocaleID resource is not present, or is
711 * in an incorrect format, 0 is returned. The LocaleID is for use in
712 * Windows (it is an LCID), but is available on all platforms.
713 */
714 uint32_t
715 Locale::getLCID() const
716 {
717 return uloc_getLCID(fullName);
718 }
719
720 UnicodeString&
721 Locale::getDisplayLanguage(UnicodeString& dispLang) const
722 {
723 return this->getDisplayLanguage(getDefault(), dispLang);
724 }
725
726 /*We cannot make any assumptions on the size of the output display strings
727 * Yet, since we are calling through to a C API, we need to set limits on
728 * buffer size. For all the following getDisplay functions we first attempt
729 * to fill up a stack allocated buffer. If it is to small we heap allocated
730 * the exact buffer we need copy it to the UnicodeString and delete it*/
731
732 UnicodeString&
733 Locale::getDisplayLanguage(const Locale &displayLocale,
734 UnicodeString &result) const {
735 UChar *buffer;
736 UErrorCode errorCode=U_ZERO_ERROR;
737 int32_t length;
738
739 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
740 if(buffer==0) {
741 result.truncate(0);
742 return result;
743 }
744
745 length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
746 buffer, result.getCapacity(),
747 &errorCode);
748 result.releaseBuffer(length);
749
750 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
751 buffer=result.getBuffer(length);
752 if(buffer==0) {
753 result.truncate(0);
754 return result;
755 }
756 errorCode=U_ZERO_ERROR;
757 length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,
758 buffer, result.getCapacity(),
759 &errorCode);
760 result.releaseBuffer(length);
761 }
762
763 if(U_FAILURE(errorCode)) {
764 result.truncate(0);
765 }
766
767 return result;
768 }
769
770 UnicodeString&
771 Locale::getDisplayScript(UnicodeString& dispScript) const
772 {
773 return this->getDisplayScript(getDefault(), dispScript);
774 }
775
776 UnicodeString&
777 Locale::getDisplayScript(const Locale &displayLocale,
778 UnicodeString &result) const {
779 UChar *buffer;
780 UErrorCode errorCode=U_ZERO_ERROR;
781 int32_t length;
782
783 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
784 if(buffer==0) {
785 result.truncate(0);
786 return result;
787 }
788
789 length=uloc_getDisplayScript(fullName, displayLocale.fullName,
790 buffer, result.getCapacity(),
791 &errorCode);
792 result.releaseBuffer(length);
793
794 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
795 buffer=result.getBuffer(length);
796 if(buffer==0) {
797 result.truncate(0);
798 return result;
799 }
800 errorCode=U_ZERO_ERROR;
801 length=uloc_getDisplayScript(fullName, displayLocale.fullName,
802 buffer, result.getCapacity(),
803 &errorCode);
804 result.releaseBuffer(length);
805 }
806
807 if(U_FAILURE(errorCode)) {
808 result.truncate(0);
809 }
810
811 return result;
812 }
813
814 UnicodeString&
815 Locale::getDisplayCountry(UnicodeString& dispCntry) const
816 {
817 return this->getDisplayCountry(getDefault(), dispCntry);
818 }
819
820 UnicodeString&
821 Locale::getDisplayCountry(const Locale &displayLocale,
822 UnicodeString &result) const {
823 UChar *buffer;
824 UErrorCode errorCode=U_ZERO_ERROR;
825 int32_t length;
826
827 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
828 if(buffer==0) {
829 result.truncate(0);
830 return result;
831 }
832
833 length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
834 buffer, result.getCapacity(),
835 &errorCode);
836 result.releaseBuffer(length);
837
838 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
839 buffer=result.getBuffer(length);
840 if(buffer==0) {
841 result.truncate(0);
842 return result;
843 }
844 errorCode=U_ZERO_ERROR;
845 length=uloc_getDisplayCountry(fullName, displayLocale.fullName,
846 buffer, result.getCapacity(),
847 &errorCode);
848 result.releaseBuffer(length);
849 }
850
851 if(U_FAILURE(errorCode)) {
852 result.truncate(0);
853 }
854
855 return result;
856 }
857
858 UnicodeString&
859 Locale::getDisplayVariant(UnicodeString& dispVar) const
860 {
861 return this->getDisplayVariant(getDefault(), dispVar);
862 }
863
864 UnicodeString&
865 Locale::getDisplayVariant(const Locale &displayLocale,
866 UnicodeString &result) const {
867 UChar *buffer;
868 UErrorCode errorCode=U_ZERO_ERROR;
869 int32_t length;
870
871 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
872 if(buffer==0) {
873 result.truncate(0);
874 return result;
875 }
876
877 length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
878 buffer, result.getCapacity(),
879 &errorCode);
880 result.releaseBuffer(length);
881
882 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
883 buffer=result.getBuffer(length);
884 if(buffer==0) {
885 result.truncate(0);
886 return result;
887 }
888 errorCode=U_ZERO_ERROR;
889 length=uloc_getDisplayVariant(fullName, displayLocale.fullName,
890 buffer, result.getCapacity(),
891 &errorCode);
892 result.releaseBuffer(length);
893 }
894
895 if(U_FAILURE(errorCode)) {
896 result.truncate(0);
897 }
898
899 return result;
900 }
901
902 UnicodeString&
903 Locale::getDisplayName( UnicodeString& name ) const
904 {
905 return this->getDisplayName(getDefault(), name);
906 }
907
908 UnicodeString&
909 Locale::getDisplayName(const Locale &displayLocale,
910 UnicodeString &result) const {
911 UChar *buffer;
912 UErrorCode errorCode=U_ZERO_ERROR;
913 int32_t length;
914
915 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);
916 if(buffer==0) {
917 result.truncate(0);
918 return result;
919 }
920
921 length=uloc_getDisplayName(fullName, displayLocale.fullName,
922 buffer, result.getCapacity(),
923 &errorCode);
924 result.releaseBuffer(length);
925
926 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
927 buffer=result.getBuffer(length);
928 if(buffer==0) {
929 result.truncate(0);
930 return result;
931 }
932 errorCode=U_ZERO_ERROR;
933 length=uloc_getDisplayName(fullName, displayLocale.fullName,
934 buffer, result.getCapacity(),
935 &errorCode);
936 result.releaseBuffer(length);
937 }
938
939 if(U_FAILURE(errorCode)) {
940 result.truncate(0);
941 }
942
943 return result;
944 }
945 const Locale* U_EXPORT2
946 Locale::getAvailableLocales(int32_t& count)
947 {
948 // for now, there is a hardcoded list, so just walk through that list and set it up.
949 umtx_lock(NULL);
950 UBool needInit = availableLocaleList == 0;
951 umtx_unlock(NULL);
952
953 if (needInit) {
954 int32_t locCount = uloc_countAvailable();
955 Locale *newLocaleList = 0;
956 if(locCount) {
957 newLocaleList = new Locale[locCount];
958 }
959 if (newLocaleList == NULL) {
960 return NULL;
961 }
962
963 count = locCount;
964
965 while(--locCount >= 0) {
966 newLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
967 }
968
969 umtx_lock(NULL);
970 if(availableLocaleList == 0) {
971 availableLocaleListCount = count;
972 availableLocaleList = newLocaleList;
973 newLocaleList = NULL;
974 ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
975 }
976 umtx_unlock(NULL);
977 delete []newLocaleList;
978 }
979 count = availableLocaleListCount;
980 return availableLocaleList;
981 }
982
983 const char* const* U_EXPORT2 Locale::getISOCountries()
984 {
985 return uloc_getISOCountries();
986 }
987
988 const char* const* U_EXPORT2 Locale::getISOLanguages()
989 {
990 return uloc_getISOLanguages();
991 }
992
993 // Set the locale's data based on a posix id.
994 void Locale::setFromPOSIXID(const char *posixID)
995 {
996 init(posixID, TRUE);
997 }
998
999 const Locale & U_EXPORT2
1000 Locale::getEnglish(void)
1001 {
1002 return getLocale(eENGLISH);
1003 }
1004
1005 const Locale & U_EXPORT2
1006 Locale::getFrench(void)
1007 {
1008 return getLocale(eFRENCH);
1009 }
1010
1011 const Locale & U_EXPORT2
1012 Locale::getGerman(void)
1013 {
1014 return getLocale(eGERMAN);
1015 }
1016
1017 const Locale & U_EXPORT2
1018 Locale::getItalian(void)
1019 {
1020 return getLocale(eITALIAN);
1021 }
1022
1023 const Locale & U_EXPORT2
1024 Locale::getJapanese(void)
1025 {
1026 return getLocale(eJAPANESE);
1027 }
1028
1029 const Locale & U_EXPORT2
1030 Locale::getKorean(void)
1031 {
1032 return getLocale(eKOREAN);
1033 }
1034
1035 const Locale & U_EXPORT2
1036 Locale::getChinese(void)
1037 {
1038 return getLocale(eCHINESE);
1039 }
1040
1041 const Locale & U_EXPORT2
1042 Locale::getSimplifiedChinese(void)
1043 {
1044 return getLocale(eCHINA);
1045 }
1046
1047 const Locale & U_EXPORT2
1048 Locale::getTraditionalChinese(void)
1049 {
1050 return getLocale(eTAIWAN);
1051 }
1052
1053
1054 const Locale & U_EXPORT2
1055 Locale::getFrance(void)
1056 {
1057 return getLocale(eFRANCE);
1058 }
1059
1060 const Locale & U_EXPORT2
1061 Locale::getGermany(void)
1062 {
1063 return getLocale(eGERMANY);
1064 }
1065
1066 const Locale & U_EXPORT2
1067 Locale::getItaly(void)
1068 {
1069 return getLocale(eITALY);
1070 }
1071
1072 const Locale & U_EXPORT2
1073 Locale::getJapan(void)
1074 {
1075 return getLocale(eJAPAN);
1076 }
1077
1078 const Locale & U_EXPORT2
1079 Locale::getKorea(void)
1080 {
1081 return getLocale(eKOREA);
1082 }
1083
1084 const Locale & U_EXPORT2
1085 Locale::getChina(void)
1086 {
1087 return getLocale(eCHINA);
1088 }
1089
1090 const Locale & U_EXPORT2
1091 Locale::getPRC(void)
1092 {
1093 return getLocale(eCHINA);
1094 }
1095
1096 const Locale & U_EXPORT2
1097 Locale::getTaiwan(void)
1098 {
1099 return getLocale(eTAIWAN);
1100 }
1101
1102 const Locale & U_EXPORT2
1103 Locale::getUK(void)
1104 {
1105 return getLocale(eUK);
1106 }
1107
1108 const Locale & U_EXPORT2
1109 Locale::getUS(void)
1110 {
1111 return getLocale(eUS);
1112 }
1113
1114 const Locale & U_EXPORT2
1115 Locale::getCanada(void)
1116 {
1117 return getLocale(eCANADA);
1118 }
1119
1120 const Locale & U_EXPORT2
1121 Locale::getCanadaFrench(void)
1122 {
1123 return getLocale(eCANADA_FRENCH);
1124 }
1125
1126 const Locale &
1127 Locale::getLocale(int locid)
1128 {
1129 Locale *localeCache = getLocaleCache();
1130 U_ASSERT(locid < eMAX_LOCALES);
1131 if (localeCache == NULL) {
1132 // Failure allocating the locale cache.
1133 // The best we can do is return a NULL reference.
1134 locid = 0;
1135 }
1136 return localeCache[locid];
1137 }
1138
1139 /*
1140 This function is defined this way in order to get around static
1141 initialization and static destruction.
1142 */
1143 Locale *
1144 Locale::getLocaleCache(void)
1145 {
1146 umtx_lock(NULL);
1147 UBool needInit = (gLocaleCache == NULL);
1148 umtx_unlock(NULL);
1149
1150 if (needInit) {
1151 Locale *tLocaleCache = new Locale[(int)eMAX_LOCALES];
1152 if (tLocaleCache == NULL) {
1153 return NULL;
1154 }
1155 tLocaleCache[eENGLISH] = Locale("en");
1156 tLocaleCache[eFRENCH] = Locale("fr");
1157 tLocaleCache[eGERMAN] = Locale("de");
1158 tLocaleCache[eITALIAN] = Locale("it");
1159 tLocaleCache[eJAPANESE] = Locale("ja");
1160 tLocaleCache[eKOREAN] = Locale("ko");
1161 tLocaleCache[eCHINESE] = Locale("zh");
1162 tLocaleCache[eFRANCE] = Locale("fr", "FR");
1163 tLocaleCache[eGERMANY] = Locale("de", "DE");
1164 tLocaleCache[eITALY] = Locale("it", "IT");
1165 tLocaleCache[eJAPAN] = Locale("ja", "JP");
1166 tLocaleCache[eKOREA] = Locale("ko", "KR");
1167 tLocaleCache[eCHINA] = Locale("zh", "CN");
1168 tLocaleCache[eTAIWAN] = Locale("zh", "TW");
1169 tLocaleCache[eUK] = Locale("en", "GB");
1170 tLocaleCache[eUS] = Locale("en", "US");
1171 tLocaleCache[eCANADA] = Locale("en", "CA");
1172 tLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA");
1173
1174 umtx_lock(NULL);
1175 if (gLocaleCache == NULL) {
1176 gLocaleCache = tLocaleCache;
1177 tLocaleCache = NULL;
1178 ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
1179 }
1180 umtx_unlock(NULL);
1181 if (tLocaleCache) {
1182 delete [] tLocaleCache; // Fancy array delete will destruct each member.
1183 }
1184 }
1185 return gLocaleCache;
1186 }
1187
1188 class KeywordEnumeration : public StringEnumeration {
1189 private:
1190 char *keywords;
1191 char *current;
1192 int32_t length;
1193 UnicodeString currUSKey;
1194 static const char fgClassID;/* Warning this is used beyond the typical RTTI usage. */
1195
1196 public:
1197 static UClassID U_EXPORT2 getStaticClassID(void) { return (UClassID)&fgClassID; }
1198 virtual UClassID getDynamicClassID(void) const { return getStaticClassID(); }
1199 public:
1200 KeywordEnumeration(const char *keys, int32_t keywordLen, int32_t currentIndex, UErrorCode &status)
1201 : keywords((char *)&fgClassID), current((char *)&fgClassID), length(0) {
1202 if(U_SUCCESS(status) && keywordLen != 0) {
1203 if(keys == NULL || keywordLen < 0) {
1204 status = U_ILLEGAL_ARGUMENT_ERROR;
1205 } else {
1206 keywords = (char *)uprv_malloc(keywordLen+1);
1207 if (keywords == NULL) {
1208 status = U_MEMORY_ALLOCATION_ERROR;
1209 }
1210 else {
1211 uprv_memcpy(keywords, keys, keywordLen);
1212 keywords[keywordLen] = 0;
1213 current = keywords + currentIndex;
1214 length = keywordLen;
1215 }
1216 }
1217 }
1218 }
1219
1220 virtual ~KeywordEnumeration() {
1221 uprv_free(keywords);
1222 }
1223
1224 virtual StringEnumeration * clone() const
1225 {
1226 UErrorCode status = U_ZERO_ERROR;
1227 return new KeywordEnumeration(keywords, length, (int32_t)(current - keywords), status);
1228 }
1229
1230 virtual int32_t count(UErrorCode &/*status*/) const {
1231 char *kw = keywords;
1232 int32_t result = 0;
1233 while(*kw) {
1234 result++;
1235 kw += uprv_strlen(kw)+1;
1236 }
1237 return result;
1238 }
1239
1240 virtual const char* next(int32_t* resultLength, UErrorCode& status) {
1241 const char* result;
1242 int32_t len;
1243 if(U_SUCCESS(status) && *current != 0) {
1244 result = current;
1245 len = uprv_strlen(current);
1246 current += len+1;
1247 if(resultLength != NULL) {
1248 *resultLength = len;
1249 }
1250 } else {
1251 if(resultLength != NULL) {
1252 *resultLength = 0;
1253 }
1254 result = NULL;
1255 }
1256 return result;
1257 }
1258
1259 virtual const UnicodeString* snext(UErrorCode& status) {
1260 int32_t resultLength = 0;
1261 const char *s = next(&resultLength, status);
1262 return setChars(s, resultLength, status);
1263 }
1264
1265 virtual void reset(UErrorCode& /*status*/) {
1266 current = keywords;
1267 }
1268 };
1269
1270 const char KeywordEnumeration::fgClassID = '\0';
1271
1272 StringEnumeration *
1273 Locale::createKeywords(UErrorCode &status) const
1274 {
1275 char keywords[256];
1276 int32_t keywordCapacity = 256;
1277 StringEnumeration *result = NULL;
1278
1279 const char* variantStart = uprv_strchr(fullName, '@');
1280 const char* assignment = uprv_strchr(fullName, '=');
1281 if(variantStart) {
1282 if(assignment > variantStart) {
1283 int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status);
1284 if(keyLen) {
1285 result = new KeywordEnumeration(keywords, keyLen, 0, status);
1286 }
1287 } else {
1288 status = U_INVALID_FORMAT_ERROR;
1289 }
1290 }
1291 return result;
1292 }
1293
1294 int32_t
1295 Locale::getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, UErrorCode &status) const
1296 {
1297 return uloc_getKeywordValue(fullName, keywordName, buffer, bufLen, &status);
1298 }
1299
1300 const char *
1301 Locale::getBaseName() const
1302 {
1303 // lazy init
1304 UErrorCode status = U_ZERO_ERROR;
1305 // semantically const
1306 if(baseName == 0) {
1307 ((Locale *)this)->baseName = ((Locale *)this)->baseNameBuffer;
1308 int32_t baseNameSize = uloc_getBaseName(fullName, baseName, ULOC_FULLNAME_CAPACITY, &status);
1309 if(baseNameSize >= ULOC_FULLNAME_CAPACITY) {
1310 ((Locale *)this)->baseName = (char *)uprv_malloc(sizeof(char) * baseNameSize + 1);
1311 uloc_getBaseName(fullName, baseName, baseNameSize+1, &status);
1312 }
1313 baseName[baseNameSize] = 0;
1314 }
1315 return baseName;
1316 }
1317
1318
1319 //eof
1320 U_NAMESPACE_END