2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 2002-2014, Apple Inc. All rights reserved.
26 Responsibility: David Smith
29 // Note the header file is in the OpenSource set (stripped to almost nothing), but not the .c file
31 #include <CoreFoundation/CFLocale.h>
32 #include <CoreFoundation/CFString.h>
33 #include <CoreFoundation/CFArray.h>
34 #include <CoreFoundation/CFDictionary.h>
35 #include <CoreFoundation/CFPreferences.h>
36 #include <CoreFoundation/CFCalendar.h>
37 #include <CoreFoundation/CFNumber.h>
38 #include "CFInternal.h"
39 #include "CFLocaleInternal.h"
40 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
41 #include <unicode/uloc.h> // ICU locales
42 #include <unicode/ulocdata.h> // ICU locale data
43 #include <unicode/ucal.h>
44 #include <unicode/ucurr.h> // ICU currency functions
45 #include <unicode/uset.h> // ICU Unicode sets
46 #include <unicode/putil.h> // ICU low-level utilities
47 #include <unicode/umsg.h> // ICU message formatting
48 #include <unicode/ucol.h>
50 #include <CoreFoundation/CFNumberFormatter.h>
55 #if DEPLOYMENT_TARGET_EMBEDDED_MINI
56 // Some compatability definitions
57 #define ULOC_FULLNAME_CAPACITY 157
58 #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
60 //typedef long UErrorCode;
61 //#define U_BUFFER_OVERFLOW_ERROR 15
62 //#define U_ZERO_ERROR 0
64 //typedef uint16_t UChar;
68 CONST_STRING_DECL(kCFLocaleCurrentLocaleDidChangeNotification
, "kCFLocaleCurrentLocaleDidChangeNotification")
70 static const char *kCalendarKeyword
= "calendar";
71 static const char *kCollationKeyword
= "collation";
72 #define kMaxICUNameSize 1024
74 typedef struct __CFLocale
*CFMutableLocaleRef
;
76 PE_CONST_STRING_DECL(__kCFLocaleCollatorID
, "locale:collator id")
80 __kCFLocaleKeyTableCount
= 21
85 bool (*get
)(CFLocaleRef
, bool user
, CFTypeRef
*, CFStringRef context
); // returns an immutable copy & reference
86 bool (*set
)(CFMutableLocaleRef
, CFTypeRef
, CFStringRef context
);
87 bool (*name
)(const char *, const char *, CFStringRef
*);
92 // Must forward decl. these functions:
93 static bool __CFLocaleCopyLocaleID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
94 static bool __CFLocaleSetNOP(CFMutableLocaleRef locale
, CFTypeRef cf
, CFStringRef context
);
95 static bool __CFLocaleFullName(const char *locale
, const char *value
, CFStringRef
*out
);
96 static bool __CFLocaleCopyCodes(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
97 static bool __CFLocaleCountryName(const char *locale
, const char *value
, CFStringRef
*out
);
98 static bool __CFLocaleScriptName(const char *locale
, const char *value
, CFStringRef
*out
);
99 static bool __CFLocaleLanguageName(const char *locale
, const char *value
, CFStringRef
*out
);
100 static bool __CFLocaleCurrencyShortName(const char *locale
, const char *value
, CFStringRef
*out
);
101 static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
102 static bool __CFLocaleVariantName(const char *locale
, const char *value
, CFStringRef
*out
);
103 static bool __CFLocaleNoName(const char *locale
, const char *value
, CFStringRef
*out
);
104 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
105 static bool __CFLocaleCalendarName(const char *locale
, const char *value
, CFStringRef
*out
);
106 static bool __CFLocaleCollationName(const char *locale
, const char *value
, CFStringRef
*out
);
107 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
108 static bool __CFLocaleCopyCalendar(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
109 static bool __CFLocaleCopyCollationID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
110 static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
111 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
112 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
113 static bool __CFLocaleCurrencyFullName(const char *locale
, const char *value
, CFStringRef
*out
);
114 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
115 static bool __CFLocaleCopyDelimiter(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
);
117 // Note string members start with an extra &, and are fixed up at init time
118 static struct key_table __CFLocaleKeyTable
[__kCFLocaleKeyTableCount
] = {
119 {(CFStringRef
)&kCFLocaleIdentifierKey
, __CFLocaleCopyLocaleID
, __CFLocaleSetNOP
, __CFLocaleFullName
, NULL
},
120 {(CFStringRef
)&kCFLocaleLanguageCodeKey
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleLanguageName
, (CFStringRef
)&kCFLocaleLanguageCodeKey
},
121 {(CFStringRef
)&kCFLocaleCountryCodeKey
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleCountryName
, (CFStringRef
)&kCFLocaleCountryCodeKey
},
122 {(CFStringRef
)&kCFLocaleScriptCodeKey
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleScriptName
, (CFStringRef
)&kCFLocaleScriptCodeKey
},
123 {(CFStringRef
)&kCFLocaleVariantCodeKey
, __CFLocaleCopyCodes
, __CFLocaleSetNOP
, __CFLocaleVariantName
, (CFStringRef
)&kCFLocaleVariantCodeKey
},
124 {(CFStringRef
)&kCFLocaleExemplarCharacterSetKey
, __CFLocaleCopyExemplarCharSet
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
125 {(CFStringRef
)&kCFLocaleCalendarIdentifierKey
, __CFLocaleCopyCalendarID
, __CFLocaleSetNOP
, __CFLocaleCalendarName
, NULL
},
126 {(CFStringRef
)&kCFLocaleCalendarKey
, __CFLocaleCopyCalendar
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
127 {(CFStringRef
)&kCFLocaleCollationIdentifierKey
, __CFLocaleCopyCollationID
, __CFLocaleSetNOP
, __CFLocaleCollationName
, NULL
},
128 {(CFStringRef
)&kCFLocaleUsesMetricSystemKey
, __CFLocaleCopyUsesMetric
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
129 {(CFStringRef
)&kCFLocaleMeasurementSystemKey
, __CFLocaleCopyMeasurementSystem
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
130 {(CFStringRef
)&kCFLocaleDecimalSeparatorKey
, __CFLocaleCopyNumberFormat
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFNumberFormatterDecimalSeparatorKey
},
131 {(CFStringRef
)&kCFLocaleGroupingSeparatorKey
, __CFLocaleCopyNumberFormat
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFNumberFormatterGroupingSeparatorKey
},
132 {(CFStringRef
)&kCFLocaleCurrencySymbolKey
, __CFLocaleCopyNumberFormat2
, __CFLocaleSetNOP
, __CFLocaleCurrencyShortName
, (CFStringRef
)&kCFNumberFormatterCurrencySymbolKey
},
133 {(CFStringRef
)&kCFLocaleCurrencyCodeKey
, __CFLocaleCopyNumberFormat2
, __CFLocaleSetNOP
, __CFLocaleCurrencyFullName
, (CFStringRef
)&kCFNumberFormatterCurrencyCodeKey
},
134 {(CFStringRef
)&kCFLocaleCollatorIdentifierKey
, __CFLocaleCopyCollatorID
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
135 {(CFStringRef
)&__kCFLocaleCollatorID
, __CFLocaleCopyCollatorID
, __CFLocaleSetNOP
, __CFLocaleNoName
, NULL
},
136 {(CFStringRef
)&kCFLocaleQuotationBeginDelimiterKey
, __CFLocaleCopyDelimiter
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFLocaleQuotationBeginDelimiterKey
},
137 {(CFStringRef
)&kCFLocaleQuotationEndDelimiterKey
, __CFLocaleCopyDelimiter
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFLocaleQuotationEndDelimiterKey
},
138 {(CFStringRef
)&kCFLocaleAlternateQuotationBeginDelimiterKey
, __CFLocaleCopyDelimiter
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFLocaleAlternateQuotationBeginDelimiterKey
},
139 {(CFStringRef
)&kCFLocaleAlternateQuotationEndDelimiterKey
, __CFLocaleCopyDelimiter
, __CFLocaleSetNOP
, __CFLocaleNoName
, (CFStringRef
)&kCFLocaleAlternateQuotationEndDelimiterKey
},
143 static CFLocaleRef __CFLocaleSystem
= NULL
;
144 static CFMutableDictionaryRef __CFLocaleCache
= NULL
;
145 static CFLock_t __CFLocaleGlobalLock
= CFLockInit
;
149 CFStringRef _identifier
; // canonical identifier, never NULL
150 CFMutableDictionaryRef _cache
;
151 CFMutableDictionaryRef _overrides
;
152 CFDictionaryRef _prefs
;
157 CF_PRIVATE Boolean
__CFLocaleGetNullLocale(struct __CFLocale
*locale
) {
158 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), Boolean
, (NSLocale
*)locale
, _nullLocale
);
159 return locale
->_nullLocale
;
162 CF_PRIVATE
void __CFLocaleSetNullLocale(struct __CFLocale
*locale
) {
163 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), void, (NSLocale
*)locale
, _setNullLocale
);
164 locale
->_nullLocale
= true;
168 enum { /* Bits 0-1 */
169 __kCFLocaleOrdinary
= 0,
170 __kCFLocaleSystem
= 1,
172 __kCFLocaleCustom
= 3
175 CF_INLINE CFIndex
__CFLocaleGetType(CFLocaleRef locale
) {
176 return __CFBitfieldGetValue(((const CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0);
179 CF_INLINE
void __CFLocaleSetType(CFLocaleRef locale
, CFIndex type
) {
180 __CFBitfieldSetValue(((CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0, (uint8_t)type
);
183 CF_INLINE
void __CFLocaleLockGlobal(void) {
184 __CFLock(&__CFLocaleGlobalLock
);
187 CF_INLINE
void __CFLocaleUnlockGlobal(void) {
188 __CFUnlock(&__CFLocaleGlobalLock
);
191 CF_INLINE
void __CFLocaleLock(CFLocaleRef locale
) {
192 __CFLock(&((struct __CFLocale
*)locale
)->_lock
);
195 CF_INLINE
void __CFLocaleUnlock(CFLocaleRef locale
) {
196 __CFUnlock(&((struct __CFLocale
*)locale
)->_lock
);
200 static Boolean
__CFLocaleEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
201 CFLocaleRef locale1
= (CFLocaleRef
)cf1
;
202 CFLocaleRef locale2
= (CFLocaleRef
)cf2
;
203 // a user locale and a locale created with an ident are not the same even if their contents are
204 if (__CFLocaleGetType(locale1
) != __CFLocaleGetType(locale2
)) return false;
205 if (!CFEqual(locale1
->_identifier
, locale2
->_identifier
)) return false;
206 if (NULL
== locale1
->_overrides
&& NULL
!= locale2
->_overrides
) return false;
207 if (NULL
!= locale1
->_overrides
&& NULL
== locale2
->_overrides
) return false;
208 if (NULL
!= locale1
->_overrides
&& !CFEqual(locale1
->_overrides
, locale2
->_overrides
)) return false;
209 if (__kCFLocaleUser
== __CFLocaleGetType(locale1
)) {
210 return CFEqual(locale1
->_prefs
, locale2
->_prefs
);
215 static CFHashCode
__CFLocaleHash(CFTypeRef cf
) {
216 CFLocaleRef locale
= (CFLocaleRef
)cf
;
217 return CFHash(locale
->_identifier
);
220 static CFStringRef
__CFLocaleCopyDescription(CFTypeRef cf
) {
221 CFLocaleRef locale
= (CFLocaleRef
)cf
;
222 const char *type
= NULL
;
223 switch (__CFLocaleGetType(locale
)) {
224 case __kCFLocaleOrdinary
: type
= "ordinary"; break;
225 case __kCFLocaleSystem
: type
= "system"; break;
226 case __kCFLocaleUser
: type
= "user"; break;
227 case __kCFLocaleCustom
: type
= "custom"; break;
229 return CFStringCreateWithFormat(CFGetAllocator(locale
), NULL
, CFSTR("<CFLocale %p [%p]>{type = %s, identifier = '%@'}"), cf
, CFGetAllocator(locale
), type
, locale
->_identifier
);
232 static void __CFLocaleDeallocate(CFTypeRef cf
) {
233 CFLocaleRef locale
= (CFLocaleRef
)cf
;
234 CFRelease(locale
->_identifier
);
235 if (NULL
!= locale
->_cache
) CFRelease(locale
->_cache
);
236 if (NULL
!= locale
->_overrides
) CFRelease(locale
->_overrides
);
237 if (NULL
!= locale
->_prefs
) CFRelease(locale
->_prefs
);
240 static CFTypeID __kCFLocaleTypeID
= _kCFRuntimeNotATypeID
;
242 static const CFRuntimeClass __CFLocaleClass
= {
247 __CFLocaleDeallocate
,
251 __CFLocaleCopyDescription
254 CFTypeID
CFLocaleGetTypeID(void) {
255 static dispatch_once_t initOnce
;
256 dispatch_once(&initOnce
, ^{
257 __kCFLocaleTypeID
= _CFRuntimeRegisterClass(&__CFLocaleClass
); // initOnce covered
258 for (CFIndex idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
259 // table fixup to workaround compiler/language limitations
260 __CFLocaleKeyTable
[idx
].key
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].key
);
261 if (NULL
!= __CFLocaleKeyTable
[idx
].context
) {
262 __CFLocaleKeyTable
[idx
].context
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].context
);
266 return __kCFLocaleTypeID
;
269 CFLocaleRef
CFLocaleGetSystem(void) {
271 __CFLocaleLockGlobal();
272 if (NULL
== __CFLocaleSystem
) {
273 __CFLocaleUnlockGlobal();
274 locale
= CFLocaleCreate(kCFAllocatorSystemDefault
, CFSTR(""));
275 if (!locale
) return NULL
;
276 __CFLocaleSetType(locale
, __kCFLocaleSystem
);
277 __CFLocaleLockGlobal();
278 if (NULL
== __CFLocaleSystem
) {
279 __CFLocaleSystem
= locale
;
281 if (locale
) CFRelease(locale
);
284 locale
= __CFLocaleSystem
? (CFLocaleRef
)CFRetain(__CFLocaleSystem
) : NULL
;
285 __CFLocaleUnlockGlobal();
289 extern CFDictionaryRef
__CFXPreferencesCopyCurrentApplicationState(void);
291 static CFLocaleRef __CFLocaleCurrent
= NULL
;
294 #if DEPLOYMENT_TARGET_MACOSX
295 #define FALLBACK_LOCALE_NAME CFSTR("")
296 #elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
297 #define FALLBACK_LOCALE_NAME CFSTR("en_US")
298 #elif DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
299 #define FALLBACK_LOCALE_NAME CFSTR("en_US")
302 static CFLocaleRef
_CFLocaleCopyCurrentGuts(CFStringRef name
, Boolean useCache
, CFDictionaryRef overridePrefs
) {
304 CFStringRef ident
= NULL
;
305 // We cannot be helpful here, because it causes performance problems,
306 // even though the preference lookup is relatively quick, as there are
307 // things which call this function thousands or millions of times in
310 #if 0 // DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
311 name
= (CFStringRef
)CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication
);
316 if (name
&& (CFStringGetTypeID() == CFGetTypeID(name
))) {
317 ident
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, name
);
319 if (name
) CFRelease(name
);
322 CFLocaleRef oldLocale
= NULL
;
323 __CFLocaleLockGlobal();
324 if (__CFLocaleCurrent
) {
325 if (ident
&& !CFEqual(__CFLocaleCurrent
->_identifier
, ident
)) {
326 oldLocale
= __CFLocaleCurrent
;
327 __CFLocaleCurrent
= NULL
;
329 CFLocaleRef res
= __CFLocaleCurrent
;
331 __CFLocaleUnlockGlobal();
332 if (ident
) CFRelease(ident
);
336 __CFLocaleUnlockGlobal();
337 if (oldLocale
) CFRelease(oldLocale
);
340 CFDictionaryRef prefs
= NULL
;
342 struct __CFLocale
*locale
;
343 uint32_t size
= sizeof(struct __CFLocale
) - sizeof(CFRuntimeBase
);
344 locale
= (struct __CFLocale
*)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault
, CFLocaleGetTypeID(), size
, NULL
);
345 if (NULL
== locale
) {
346 if (prefs
) CFRelease(prefs
);
347 if (ident
) CFRelease(ident
);
350 __CFLocaleSetType(locale
, __kCFLocaleUser
);
351 if (NULL
== ident
) ident
= (CFStringRef
)CFRetain(FALLBACK_LOCALE_NAME
);
352 locale
->_identifier
= ident
;
353 locale
->_cache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
354 locale
->_overrides
= NULL
;
355 locale
->_prefs
= prefs
;
356 locale
->_lock
= CFLockInit
;
357 locale
->_nullLocale
= false;
360 __CFLocaleLockGlobal();
361 if (NULL
== __CFLocaleCurrent
) {
362 __CFLocaleCurrent
= locale
;
366 locale
= (struct __CFLocale
*)CFRetain(__CFLocaleCurrent
);
367 __CFLocaleUnlockGlobal();
373 <rdar://problem/13834276> NSDateFormatter: Cannot specify force12HourTime/force24HourTime
374 This returns an instance of CFLocale that's set up exactly like it would be if the user changed the current locale to that identifier, then called CFLocaleCopyCurrent()
376 CFLocaleRef
_CFLocaleCopyAsIfCurrent(CFStringRef name
) {
377 return _CFLocaleCopyCurrentGuts(name
, false, NULL
);
381 <rdar://problem/14032388> Need the ability to initialize a CFLocaleRef from a preferences dictionary
382 This returns an instance of CFLocale that's set up exactly like it would be if the user changed the current locale to that identifier, set the preferences keys in the overrides dictionary, then called CFLocaleCopyCurrent()
384 CFLocaleRef
_CFLocaleCopyAsIfCurrentWithOverrides(CFStringRef name
, CFDictionaryRef overrides
) {
385 return _CFLocaleCopyCurrentGuts(name
, false, overrides
);
388 CFLocaleRef
CFLocaleCopyCurrent(void) {
389 return _CFLocaleCopyCurrentGuts(NULL
, true, NULL
);
392 CF_PRIVATE CFDictionaryRef
__CFLocaleGetPrefs(CFLocaleRef locale
) {
393 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFDictionaryRef
, (NSLocale
*)locale
, _prefs
);
394 return locale
->_prefs
;
397 CFLocaleRef
CFLocaleCreate(CFAllocatorRef allocator
, CFStringRef identifier
) {
398 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
399 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
400 __CFGenericValidateType(identifier
, CFStringGetTypeID());
401 CFStringRef localeIdentifier
= NULL
;
403 localeIdentifier
= CFLocaleCreateCanonicalLocaleIdentifierFromString(allocator
, identifier
);
405 if (NULL
== localeIdentifier
) return NULL
;
406 CFStringRef old
= localeIdentifier
;
407 localeIdentifier
= (CFStringRef
)CFStringCreateCopy(allocator
, localeIdentifier
);
409 __CFLocaleLockGlobal();
410 // Look for cases where we can return a cached instance.
411 // We only use cached objects if the allocator is the system
412 // default allocator.
413 if (!allocator
) allocator
= __CFGetDefaultAllocator();
414 Boolean canCache
= _CFAllocatorIsSystemDefault(allocator
);
415 if (canCache
&& __CFLocaleCache
) {
416 CFLocaleRef locale
= (CFLocaleRef
)CFDictionaryGetValue(__CFLocaleCache
, localeIdentifier
);
419 __CFLocaleUnlockGlobal();
420 CFRelease(localeIdentifier
);
424 struct __CFLocale
*locale
= NULL
;
425 uint32_t size
= sizeof(struct __CFLocale
) - sizeof(CFRuntimeBase
);
426 locale
= (struct __CFLocale
*)_CFRuntimeCreateInstance(allocator
, CFLocaleGetTypeID(), size
, NULL
);
427 if (NULL
== locale
) {
430 __CFLocaleSetType(locale
, __kCFLocaleOrdinary
);
431 locale
->_identifier
= localeIdentifier
;
432 locale
->_cache
= CFDictionaryCreateMutable(allocator
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
433 locale
->_overrides
= NULL
;
434 locale
->_prefs
= NULL
;
435 locale
->_lock
= CFLockInit
;
437 if (NULL
== __CFLocaleCache
) {
438 __CFLocaleCache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
440 CFDictionarySetValue(__CFLocaleCache
, localeIdentifier
, locale
);
442 __CFLocaleUnlockGlobal();
443 return (CFLocaleRef
)locale
;
446 CFLocaleRef
CFLocaleCreateCopy(CFAllocatorRef allocator
, CFLocaleRef locale
) {
447 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFLocaleRef
, (NSLocale
*)locale
, copy
);
448 return (CFLocaleRef
)CFRetain(locale
);
451 CFStringRef
CFLocaleGetIdentifier(CFLocaleRef locale
) {
452 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef
, (NSLocale
*)locale
, localeIdentifier
);
453 return locale
->_identifier
;
456 CFTypeRef
CFLocaleGetValue(CFLocaleRef locale
, CFStringRef key
) {
457 #if DEPLOYMENT_TARGET_MACOSX
458 if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
)) {
459 // Hack for Opera, which is using the hard-coded string value below instead of
460 // the perfectly good public kCFLocaleCountryCode constant, for whatever reason.
461 if (key
&& CFEqual(key
, CFSTR("locale:country code"))) {
462 key
= kCFLocaleCountryCodeKey
;
466 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFTypeRef
, (NSLocale
*)locale
, objectForKey
:(id
)key
);
467 CFIndex idx
, slot
= -1;
468 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
469 if (__CFLocaleKeyTable
[idx
].key
== key
) {
474 if (-1 == slot
&& NULL
!= key
) {
475 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
476 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
486 if (NULL
!= locale
->_overrides
&& CFDictionaryGetValueIfPresent(locale
->_overrides
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
489 __CFLocaleLock(locale
);
490 if (CFDictionaryGetValueIfPresent(locale
->_cache
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
491 __CFLocaleUnlock(locale
);
494 if (__kCFLocaleUser
== __CFLocaleGetType(locale
) && __CFLocaleKeyTable
[slot
].get(locale
, true, &value
, __CFLocaleKeyTable
[slot
].context
)) {
495 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
496 if (value
) CFRelease(value
);
497 __CFLocaleUnlock(locale
);
500 if (__CFLocaleKeyTable
[slot
].get(locale
, false, &value
, __CFLocaleKeyTable
[slot
].context
)) {
501 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
502 if (value
) CFRelease(value
);
503 __CFLocaleUnlock(locale
);
506 __CFLocaleUnlock(locale
);
510 CFStringRef
CFLocaleCopyDisplayNameForPropertyValue(CFLocaleRef displayLocale
, CFStringRef key
, CFStringRef value
) {
511 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef
, (NSLocale
*)displayLocale
, _copyDisplayNameForKey
:(id
)key value
:(id
)value
);
512 CFIndex idx
, slot
= -1;
513 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
514 if (__CFLocaleKeyTable
[idx
].key
== key
) {
519 if (-1 == slot
&& NULL
!= key
) {
520 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
521 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
527 if (-1 == slot
|| !value
) {
530 // Get the locale ID as a C string
531 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
532 char cValue
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
533 if (CFStringGetCString(displayLocale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
) && CFStringGetCString(value
, cValue
, sizeof(cValue
)/sizeof(char), kCFStringEncodingASCII
)) {
535 if ((NULL
== displayLocale
->_prefs
) && __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
)) {
539 // We could not find a result using the requested language. Fall back through all preferred languages.
540 CFArrayRef langPref
= NULL
;
541 if (displayLocale
->_prefs
) {
542 langPref
= (CFArrayRef
)CFDictionaryGetValue(displayLocale
->_prefs
, CFSTR("AppleLanguages"));
543 if (langPref
) CFRetain(langPref
);
545 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
546 langPref
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
549 if (langPref
!= NULL
) {
550 CFIndex count
= CFArrayGetCount(langPref
);
552 bool success
= false;
553 for (i
= 0; i
< count
&& !success
; ++i
) {
554 CFStringRef language
= (CFStringRef
)CFArrayGetValueAtIndex(langPref
, i
);
555 CFStringRef cleanLanguage
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, language
);
556 if (CFStringGetCString(cleanLanguage
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
)) {
557 success
= __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
);
559 CFRelease(cleanLanguage
);
569 CFArrayRef
CFLocaleCopyAvailableLocaleIdentifiers(void) {
570 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
571 int32_t locale
, localeCount
= uloc_countAvailable();
572 CFMutableSetRef working
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeSetCallBacks
);
573 for (locale
= 0; locale
< localeCount
; ++locale
) {
574 const char *localeID
= uloc_getAvailable(locale
);
575 CFStringRef string1
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, localeID
, kCFStringEncodingASCII
);
576 // do not include canonicalized version as IntlFormats cannot cope with that in its popup
577 CFSetAddValue(working
, string1
);
580 CFIndex cnt
= CFSetGetCount(working
);
581 STACK_BUFFER_DECL(const void *, buffer
, cnt
);
582 CFSetGetValues(working
, buffer
);
583 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, buffer
, cnt
, &kCFTypeArrayCallBacks
);
587 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
591 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
592 static CFArrayRef
__CFLocaleCopyCStringsAsArray(const char* const* p
) {
593 CFMutableArrayRef working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
595 CFStringRef string
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, *p
, kCFStringEncodingASCII
);
596 CFArrayAppendValue(working
, string
);
599 CFArrayRef result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
604 static CFArrayRef
__CFLocaleCopyUEnumerationAsArray(UEnumeration
*enumer
, UErrorCode
*icuErr
) {
605 const UChar
*next
= NULL
;
607 CFMutableArrayRef working
= NULL
;
608 if (U_SUCCESS(*icuErr
)) {
609 working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
611 while ((next
= uenum_unext(enumer
, &len
, icuErr
)) && U_SUCCESS(*icuErr
)) {
612 CFStringRef string
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)next
, (CFIndex
) len
);
613 CFArrayAppendValue(working
, string
);
616 if (*icuErr
== U_INDEX_OUTOFBOUNDS_ERROR
) {
617 *icuErr
= U_ZERO_ERROR
; // Temp: Work around bug (ICU 5220) in ucurr enumerator
619 CFArrayRef result
= NULL
;
620 if (U_SUCCESS(*icuErr
)) {
621 result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
623 if (working
!= NULL
) {
630 CFArrayRef
CFLocaleCopyISOLanguageCodes(void) {
631 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
632 const char* const* p
= uloc_getISOLanguages();
633 return __CFLocaleCopyCStringsAsArray(p
);
635 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
639 CFArrayRef
CFLocaleCopyISOCountryCodes(void) {
640 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
641 const char* const* p
= uloc_getISOCountries();
642 return __CFLocaleCopyCStringsAsArray(p
);
644 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
648 CFArrayRef
CFLocaleCopyISOCurrencyCodes(void) {
649 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
650 UErrorCode icuStatus
= U_ZERO_ERROR
;
651 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_ALL
, &icuStatus
);
652 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
655 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
660 CFArrayRef
CFLocaleCopyCommonISOCurrencyCodes(void) {
661 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
662 UErrorCode icuStatus
= U_ZERO_ERROR
;
663 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_COMMON
|UCURR_NON_DEPRECATED
, &icuStatus
);
664 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
667 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
672 CFStringRef
CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(CFAllocatorRef allocator
, uint32_t lcid
) {
673 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
674 char buffer
[kMaxICUNameSize
];
675 UErrorCode status
= U_ZERO_ERROR
;
676 int32_t ret
= uloc_getLocaleForLCID(lcid
, buffer
, kMaxICUNameSize
, &status
);
677 if (U_FAILURE(status
) || kMaxICUNameSize
<= ret
) return NULL
;
678 CFStringRef str
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, buffer
, kCFStringEncodingASCII
);
679 CFStringRef ident
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, str
);
687 uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier
) {
688 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
689 CFStringRef ident
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, localeIdentifier
);
690 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
691 Boolean b
= ident
? CFStringGetCString(ident
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
692 if (ident
) CFRelease(ident
);
693 return b
? uloc_getLCID(localeID
) : 0;
699 CFLocaleLanguageDirection
CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode
) {
700 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
701 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
702 Boolean b
= isoLangCode
? CFStringGetCString(isoLangCode
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
703 CFLocaleLanguageDirection dir
;
704 UErrorCode status
= U_ZERO_ERROR
;
705 ULayoutType idir
= b
? uloc_getCharacterOrientation(localeID
, &status
) : ULOC_LAYOUT_UNKNOWN
;
707 case ULOC_LAYOUT_LTR
: dir
= kCFLocaleLanguageDirectionLeftToRight
; break;
708 case ULOC_LAYOUT_RTL
: dir
= kCFLocaleLanguageDirectionRightToLeft
; break;
709 case ULOC_LAYOUT_TTB
: dir
= kCFLocaleLanguageDirectionTopToBottom
; break;
710 case ULOC_LAYOUT_BTT
: dir
= kCFLocaleLanguageDirectionBottomToTop
; break;
711 default: dir
= kCFLocaleLanguageDirectionUnknown
; break;
715 return kCFLocaleLanguageDirectionLeftToRight
;
719 CFLocaleLanguageDirection
CFLocaleGetLanguageLineDirection(CFStringRef isoLangCode
) {
720 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
721 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
722 Boolean b
= isoLangCode
? CFStringGetCString(isoLangCode
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
723 CFLocaleLanguageDirection dir
;
724 UErrorCode status
= U_ZERO_ERROR
;
725 ULayoutType idir
= b
? uloc_getLineOrientation(localeID
, &status
) : ULOC_LAYOUT_UNKNOWN
;
727 case ULOC_LAYOUT_LTR
: dir
= kCFLocaleLanguageDirectionLeftToRight
; break;
728 case ULOC_LAYOUT_RTL
: dir
= kCFLocaleLanguageDirectionRightToLeft
; break;
729 case ULOC_LAYOUT_TTB
: dir
= kCFLocaleLanguageDirectionTopToBottom
; break;
730 case ULOC_LAYOUT_BTT
: dir
= kCFLocaleLanguageDirectionBottomToTop
; break;
731 default: dir
= kCFLocaleLanguageDirectionUnknown
; break;
735 return kCFLocaleLanguageDirectionLeftToRight
;
739 CFArrayRef
CFLocaleCopyPreferredLanguages(void) {
740 CFMutableArrayRef newArray
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
741 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
742 CFArrayRef languagesArray
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
743 if (languagesArray
&& (CFArrayGetTypeID() == CFGetTypeID(languagesArray
))) {
744 for (CFIndex idx
= 0, cnt
= CFArrayGetCount(languagesArray
); idx
< cnt
; idx
++) {
745 CFStringRef str
= (CFStringRef
)CFArrayGetValueAtIndex(languagesArray
, idx
);
746 if (str
&& (CFStringGetTypeID() == CFGetTypeID(str
))) {
747 CFStringRef ident
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, str
);
748 CFArrayAppendValue(newArray
, ident
);
753 if (languagesArray
) CFRelease(languagesArray
);
758 // -------- -------- -------- -------- -------- --------
760 // These functions return true or false depending on the success or failure of the function.
761 // In the Copy case, this is failure to fill the *cf out parameter, and that out parameter is
762 // returned by reference WITH a retain on it.
763 static bool __CFLocaleSetNOP(CFMutableLocaleRef locale
, CFTypeRef cf
, CFStringRef context
) {
767 static bool __CFLocaleCopyLocaleID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
768 *cf
= CFRetain(locale
->_identifier
);
773 static bool __CFLocaleCopyCodes(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
774 CFDictionaryRef codes
= NULL
;
775 // this access of _cache is protected by the lock in CFLocaleGetValue()
776 if (!CFDictionaryGetValueIfPresent(locale
->_cache
, CFSTR("__kCFLocaleCodes"), (const void **)&codes
)) {
777 codes
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, locale
->_identifier
);
778 if (codes
) CFDictionarySetValue(locale
->_cache
, CFSTR("__kCFLocaleCodes"), codes
);
779 if (codes
) CFRelease(codes
);
782 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(codes
, context
); // context is one of kCFLocale*Code constants
783 if (value
) CFRetain(value
);
790 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
791 CFCharacterSetRef
_CFCreateCharacterSetFromUSet(USet
*set
) {
792 UErrorCode icuErr
= U_ZERO_ERROR
;
793 CFMutableCharacterSetRef working
= CFCharacterSetCreateMutable(NULL
);
794 UChar buffer
[2048]; // Suitable for most small sets
800 int32_t itemCount
= uset_getItemCount(set
);
802 for (i
= 0; i
< itemCount
; ++i
)
808 stringLen
= uset_getItem(set
, i
, &start
, &end
, buffer
, sizeof(buffer
)/sizeof(UChar
), &icuErr
);
809 if (icuErr
== U_BUFFER_OVERFLOW_ERROR
)
811 string
= (UChar
*) malloc(sizeof(UChar
)*(stringLen
+1));
817 icuErr
= U_ZERO_ERROR
;
818 (void) uset_getItem(set
, i
, &start
, &end
, string
, stringLen
+1, &icuErr
);
820 if (U_FAILURE(icuErr
))
822 if (string
!= buffer
)
828 CFCharacterSetAddCharactersInRange(working
, CFRangeMake(start
, end
-start
+1));
831 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, (UniChar
*)string
, stringLen
, kCFAllocatorNull
);
832 CFCharacterSetAddCharactersInString(working
, cfString
);
835 if (string
!= buffer
)
839 CFCharacterSetRef result
= CFCharacterSetCreateCopy(kCFAllocatorSystemDefault
, working
);
845 static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
846 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
847 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
848 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
849 UErrorCode icuStatus
= U_ZERO_ERROR
;
850 ULocaleData
* uld
= ulocdata_open(localeID
, &icuStatus
);
851 USet
*set
= ulocdata_getExemplarSet(uld
, NULL
, USET_ADD_CASE_MAPPINGS
, ULOCDATA_ES_STANDARD
, &icuStatus
);
853 if (U_FAILURE(icuStatus
))
855 if (icuStatus
== U_USING_DEFAULT_WARNING
) // If default locale used, force to empty set
857 *cf
= (CFTypeRef
) _CFCreateCharacterSetFromUSet(set
);
859 return (*cf
!= NULL
);
865 static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
, const char *keyword
)
867 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
868 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
869 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
))
871 char value
[ULOC_KEYWORD_AND_VALUES_CAPACITY
];
872 UErrorCode icuStatus
= U_ZERO_ERROR
;
873 if (uloc_getKeywordValue(localeID
, keyword
, value
, sizeof(value
)/sizeof(char), &icuStatus
) > 0 && U_SUCCESS(icuStatus
))
875 *cf
= (CFTypeRef
) CFStringCreateWithCString(kCFAllocatorSystemDefault
, value
, kCFStringEncodingASCII
);
884 static bool __CFLocaleCopyICUCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
, const char *keyword
) {
885 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
886 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
887 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
888 UErrorCode icuStatus
= U_ZERO_ERROR
;
889 UEnumeration
*en
= ucal_getKeywordValuesForLocale(keyword
, localeID
, TRUE
, &icuStatus
);
891 const char *value
= uenum_next(en
, &len
, &icuStatus
);
892 if (U_SUCCESS(icuStatus
)) {
893 *cf
= (CFTypeRef
) CFStringCreateWithCString(kCFAllocatorSystemDefault
, value
, kCFStringEncodingASCII
);
904 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
905 bool succeeded
= __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCalendarKeyword
);
907 succeeded
= __CFLocaleCopyICUCalendarID(locale
, user
, cf
, context
, kCalendarKeyword
);
910 if (CFEqual(*cf
, kCFCalendarIdentifierGregorian
)) {
912 *cf
= CFRetain(kCFCalendarIdentifierGregorian
);
913 } else if (CFEqual(*cf
, kCFCalendarIdentifierBuddhist
)) {
915 *cf
= CFRetain(kCFCalendarIdentifierBuddhist
);
916 } else if (CFEqual(*cf
, kCFCalendarIdentifierJapanese
)) {
918 *cf
= CFRetain(kCFCalendarIdentifierJapanese
);
919 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamic
)) {
921 *cf
= CFRetain(kCFCalendarIdentifierIslamic
);
922 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamicCivil
)) {
924 *cf
= CFRetain(kCFCalendarIdentifierIslamicCivil
);
925 } else if (CFEqual(*cf
, kCFCalendarIdentifierHebrew
)) {
927 *cf
= CFRetain(kCFCalendarIdentifierHebrew
);
928 } else if (CFEqual(*cf
, kCFCalendarIdentifierChinese
)) {
930 *cf
= CFRetain(kCFCalendarIdentifierChinese
);
931 } else if (CFEqual(*cf
, kCFCalendarIdentifierRepublicOfChina
)) {
933 *cf
= CFRetain(kCFCalendarIdentifierRepublicOfChina
);
934 } else if (CFEqual(*cf
, kCFCalendarIdentifierPersian
)) {
936 *cf
= CFRetain(kCFCalendarIdentifierPersian
);
937 } else if (CFEqual(*cf
, kCFCalendarIdentifierIndian
)) {
939 *cf
= CFRetain(kCFCalendarIdentifierIndian
);
940 } else if (CFEqual(*cf
, kCFCalendarIdentifierISO8601
)) {
942 *cf
= CFRetain(kCFCalendarIdentifierISO8601
);
943 } else if (CFEqual(*cf
, kCFCalendarIdentifierCoptic
)) {
945 *cf
= CFRetain(kCFCalendarIdentifierCoptic
);
946 } else if (CFEqual(*cf
, kCFCalendarIdentifierEthiopicAmeteMihret
)) {
948 *cf
= CFRetain(kCFCalendarIdentifierEthiopicAmeteMihret
);
949 } else if (CFEqual(*cf
, kCFCalendarIdentifierEthiopicAmeteAlem
)) {
951 *cf
= CFRetain(kCFCalendarIdentifierEthiopicAmeteAlem
);
952 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamicTabular
)) {
954 *cf
= CFRetain(kCFCalendarIdentifierIslamicTabular
);
955 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamicUmmAlQura
)) {
957 *cf
= CFRetain(kCFCalendarIdentifierIslamicUmmAlQura
);
964 *cf
= CFRetain(kCFCalendarIdentifierGregorian
);
969 static bool __CFLocaleCopyCalendar(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
970 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
971 if (__CFLocaleCopyCalendarID(locale
, user
, cf
, context
)) {
972 CFCalendarRef calendar
= CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault
, (CFStringRef
)*cf
);
973 CFCalendarSetLocale(calendar
, locale
);
974 CFDictionaryRef prefs
= __CFLocaleGetPrefs(locale
);
975 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleFirstWeekday")) : NULL
;
976 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
977 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, *cf
);
979 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
981 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &wkdy
)) {
982 CFCalendarSetFirstWeekday(calendar
, wkdy
);
985 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleMinDaysInFirstWeek")) : NULL
;
986 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
987 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, *cf
);
989 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
991 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &mwd
)) {
992 CFCalendarSetMinimumDaysInFirstWeek(calendar
, mwd
);
1003 static bool __CFLocaleCopyDelimiter(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1004 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1005 ULocaleDataDelimiterType type
= (ULocaleDataDelimiterType
)0;
1006 if (context
== kCFLocaleQuotationBeginDelimiterKey
) {
1007 type
= ULOCDATA_QUOTATION_START
;
1008 } else if (context
== kCFLocaleQuotationEndDelimiterKey
) {
1009 type
= ULOCDATA_QUOTATION_END
;
1010 } else if (context
== kCFLocaleAlternateQuotationBeginDelimiterKey
) {
1011 type
= ULOCDATA_ALT_QUOTATION_START
;
1012 } else if (context
== kCFLocaleAlternateQuotationEndDelimiterKey
) {
1013 type
= ULOCDATA_ALT_QUOTATION_END
;
1018 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1019 if (!CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
1024 UErrorCode status
= U_ZERO_ERROR
;
1025 ULocaleData
*uld
= ulocdata_open(localeID
, &status
);
1026 int32_t len
= ulocdata_getDelimiter(uld
, type
, buffer
, sizeof(buffer
) / sizeof(buffer
[0]), &status
);
1027 ulocdata_close(uld
);
1028 if (U_FAILURE(status
) || sizeof(buffer
) / sizeof(buffer
[0]) < len
) {
1032 *cf
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)buffer
, len
);
1033 return (*cf
!= NULL
);
1035 if (context
== kCFLocaleQuotationBeginDelimiterKey
|| context
== kCFLocaleQuotationEndDelimiterKey
|| context
== kCFLocaleAlternateQuotationBeginDelimiterKey
|| context
== kCFLocaleAlternateQuotationEndDelimiterKey
) {
1036 *cf
= CFRetain(CFSTR("\""));
1044 static bool __CFLocaleCopyCollationID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1045 return __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCollationKeyword
);
1048 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1049 CFStringRef canonLocaleCFStr
= NULL
;
1050 if (user
&& locale
->_prefs
) {
1051 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleCollationOrder"));
1053 // Canonicalize pref string in case it's not in the canonical format.
1054 canonLocaleCFStr
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, pref
);
1056 CFArrayRef languagesArray
= (CFArrayRef
)CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleLanguages"));
1057 if (languagesArray
&& (CFArrayGetTypeID() == CFGetTypeID(languagesArray
))) {
1058 if (0 < CFArrayGetCount(languagesArray
)) {
1059 CFStringRef str
= (CFStringRef
)CFArrayGetValueAtIndex(languagesArray
, 0);
1060 if (str
&& (CFStringGetTypeID() == CFGetTypeID(str
))) {
1061 canonLocaleCFStr
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, str
);
1067 if (!canonLocaleCFStr
) {
1068 canonLocaleCFStr
= CFLocaleGetIdentifier(locale
);
1069 CFRetain(canonLocaleCFStr
);
1071 *cf
= canonLocaleCFStr
;
1072 return canonLocaleCFStr
? true : false;
1075 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1076 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1077 bool us
= false; // Default is Metric
1079 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1081 CFTypeRef pref
= CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleMetricUnits"));
1083 us
= (kCFBooleanFalse
== pref
);
1086 pref
= CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleMeasurementUnits"));
1088 us
= CFEqual(pref
, CFSTR("Inches"));
1095 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1096 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
1097 UErrorCode icuStatus
= U_ZERO_ERROR
;
1098 UMeasurementSystem ms
= UMS_SI
;
1099 ms
= ulocdata_getMeasurementSystem(localeID
, &icuStatus
);
1100 if (U_SUCCESS(icuStatus
)) {
1101 us
= (ms
== UMS_US
);
1108 *cf
= us
? CFRetain(kCFBooleanFalse
) : CFRetain(kCFBooleanTrue
);
1111 *cf
= CFRetain(kCFBooleanFalse
);
1116 static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1117 if (__CFLocaleCopyUsesMetric(locale
, user
, cf
, context
)) {
1118 bool us
= (*cf
== kCFBooleanFalse
);
1120 *cf
= us
? CFRetain(CFSTR("U.S.")) : CFRetain(CFSTR("Metric"));
1126 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1127 CFStringRef str
= NULL
;
1128 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1129 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterDecimalStyle
);
1130 str
= nf
? (CFStringRef
)CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
1131 if (nf
) CFRelease(nf
);
1140 // ICU does not reliably set up currency info for other than Currency-type formatters,
1141 // so we have to have another routine here which creates a Currency number formatter.
1142 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1143 CFStringRef str
= NULL
;
1144 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1145 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterCurrencyStyle
);
1146 str
= nf
? (CFStringRef
)CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
1147 if (nf
) CFRelease(nf
);
1156 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1157 typedef int32_t (*__CFICUFunction
)(const char *, const char *, UChar
*, int32_t, UErrorCode
*);
1159 static bool __CFLocaleICUName(const char *locale
, const char *valLocale
, CFStringRef
*out
, __CFICUFunction icu
) {
1160 UErrorCode icuStatus
= U_ZERO_ERROR
;
1162 UChar name
[kMaxICUNameSize
];
1164 size
= (*icu
)(valLocale
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1165 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
1166 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1167 return (*out
!= NULL
);
1172 static bool __CFLocaleICUKeywordValueName(const char *locale
, const char *value
, const char *keyword
, CFStringRef
*out
) {
1173 UErrorCode icuStatus
= U_ZERO_ERROR
;
1175 UChar name
[kMaxICUNameSize
];
1176 // Need to make a fake locale ID
1177 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1178 if (strlen(value
) < ULOC_KEYWORD_AND_VALUES_CAPACITY
) {
1179 strlcpy(lid
, "en_US@", sizeof(lid
));
1180 strlcat(lid
, keyword
, sizeof(lid
));
1181 strlcat(lid
, "=", sizeof(lid
));
1182 strlcat(lid
, value
, sizeof(lid
));
1183 size
= uloc_getDisplayKeywordValue(lid
, keyword
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1184 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
1185 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1186 return (*out
!= NULL
);
1192 static bool __CFLocaleICUCurrencyName(const char *locale
, const char *value
, UCurrNameStyle style
, CFStringRef
*out
) {
1193 int valLen
= strlen(value
);
1194 if (valLen
!= 3) // not a valid ISO code
1197 UBool isChoice
= FALSE
;
1199 UErrorCode icuStatus
= U_ZERO_ERROR
;
1200 u_charsToUChars(value
, curr
, valLen
);
1201 curr
[valLen
] = '\0';
1203 name
= ucurr_getName(curr
, locale
, style
, &isChoice
, &size
, &icuStatus
);
1204 if (U_FAILURE(icuStatus
) || icuStatus
== U_USING_DEFAULT_WARNING
)
1206 UChar result
[kMaxICUNameSize
];
1209 UChar pattern
[kMaxICUNameSize
];
1210 CFStringRef patternRef
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("{0,choice,%S}"), name
);
1211 CFIndex pattlen
= CFStringGetLength(patternRef
);
1212 CFStringGetCharacters(patternRef
, CFRangeMake(0, pattlen
), (UniChar
*)pattern
);
1213 CFRelease(patternRef
);
1214 pattern
[pattlen
] = '\0'; // null terminate the pattern
1215 // Format the message assuming a large amount of the currency
1216 size
= u_formatMessage("en_US", pattern
, pattlen
, result
, kMaxICUNameSize
, &icuStatus
, 10.0);
1217 if (U_FAILURE(icuStatus
))
1222 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1223 return (*out
!= NULL
);
1227 static bool __CFLocaleFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
1228 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1229 UErrorCode icuStatus
= U_ZERO_ERROR
;
1231 UChar name
[kMaxICUNameSize
];
1233 // First, try to get the full locale.
1234 size
= uloc_getDisplayName(value
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1235 if (U_FAILURE(icuStatus
) || size
<= 0)
1238 // Did we wind up using a default somewhere?
1239 if (icuStatus
== U_USING_DEFAULT_WARNING
) {
1240 // For some locale IDs, there may be no language which has a translation for every
1241 // piece. Rather than return nothing, see if we can at least handle
1242 // the language part of the locale.
1243 UErrorCode localStatus
= U_ZERO_ERROR
;
1245 UChar localName
[kMaxICUNameSize
];
1246 localSize
= uloc_getDisplayLanguage(value
, locale
, localName
, kMaxICUNameSize
, &localStatus
);
1247 if (U_FAILURE(localStatus
) || size
<= 0 || localStatus
== U_USING_DEFAULT_WARNING
)
1251 // This locale is OK, so use the result.
1252 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1253 return (*out
!= NULL
);
1255 *out
= CFRetain(CFSTR("(none)"));
1260 static bool __CFLocaleLanguageName(const char *locale
, const char *value
, CFStringRef
*out
) {
1261 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1262 return __CFLocaleICUName(locale
, value
, out
, uloc_getDisplayLanguage
);
1264 *out
= CFRetain(CFSTR("(none)"));
1269 static bool __CFLocaleCountryName(const char *locale
, const char *value
, CFStringRef
*out
) {
1270 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1271 // Need to make a fake locale ID
1272 char lid
[ULOC_FULLNAME_CAPACITY
];
1273 if (strlen(value
) < sizeof(lid
) - 3) {
1274 strlcpy(lid
, "en_", sizeof(lid
));
1275 strlcat(lid
, value
, sizeof(lid
));
1276 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayCountry
);
1280 *out
= CFRetain(CFSTR("(none)"));
1285 static bool __CFLocaleScriptName(const char *locale
, const char *value
, CFStringRef
*out
) {
1286 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1287 // Need to make a fake locale ID
1288 char lid
[ULOC_FULLNAME_CAPACITY
];
1289 if (strlen(value
) == 4) {
1290 strlcpy(lid
, "en_", sizeof(lid
));
1291 strlcat(lid
, value
, sizeof(lid
));
1292 strlcat(lid
, "_US", sizeof(lid
));
1293 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayScript
);
1297 *out
= CFRetain(CFSTR("(none)"));
1302 static bool __CFLocaleVariantName(const char *locale
, const char *value
, CFStringRef
*out
) {
1303 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1304 // Need to make a fake locale ID
1305 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1306 if (strlen(value
) < sizeof(lid
) - 6) {
1307 strlcpy(lid
, "en_US_", sizeof(lid
));
1308 strlcat(lid
, value
, sizeof(lid
));
1309 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayVariant
);
1313 *out
= CFRetain(CFSTR("(none)"));
1318 static bool __CFLocaleCalendarName(const char *locale
, const char *value
, CFStringRef
*out
) {
1319 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1320 return __CFLocaleICUKeywordValueName(locale
, value
, kCalendarKeyword
, out
);
1322 *out
= CFRetain(CFSTR("(none)"));
1327 static bool __CFLocaleCollationName(const char *locale
, const char *value
, CFStringRef
*out
) {
1328 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1329 return __CFLocaleICUKeywordValueName(locale
, value
, kCollationKeyword
, out
);
1331 *out
= CFRetain(CFSTR("(none)"));
1336 static bool __CFLocaleCurrencyShortName(const char *locale
, const char *value
, CFStringRef
*out
) {
1337 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1338 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_SYMBOL_NAME
, out
);
1340 *out
= CFRetain(CFSTR("(none)"));
1345 static bool __CFLocaleCurrencyFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
1346 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1347 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_LONG_NAME
, out
);
1349 *out
= CFRetain(CFSTR("(none)"));
1354 static bool __CFLocaleNoName(const char *locale
, const char *value
, CFStringRef
*out
) {
1358 #undef kMaxICUNameSize