2 * Copyright (c) 2014 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-2013, 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 CFSpinLock_t __CFLocaleGlobalLock
= CFSpinLockInit
;
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 return locale
->_nullLocale
;
161 CF_PRIVATE
void __CFLocaleSetNullLocale(struct __CFLocale
*locale
) {
162 locale
->_nullLocale
= true;
166 enum { /* Bits 0-1 */
167 __kCFLocaleOrdinary
= 0,
168 __kCFLocaleSystem
= 1,
170 __kCFLocaleCustom
= 3
173 CF_INLINE CFIndex
__CFLocaleGetType(CFLocaleRef locale
) {
174 return __CFBitfieldGetValue(((const CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0);
177 CF_INLINE
void __CFLocaleSetType(CFLocaleRef locale
, CFIndex type
) {
178 __CFBitfieldSetValue(((CFRuntimeBase
*)locale
)->_cfinfo
[CF_INFO_BITS
], 1, 0, (uint8_t)type
);
181 CF_INLINE
void __CFLocaleLockGlobal(void) {
182 __CFSpinLock(&__CFLocaleGlobalLock
);
185 CF_INLINE
void __CFLocaleUnlockGlobal(void) {
186 __CFSpinUnlock(&__CFLocaleGlobalLock
);
189 CF_INLINE
void __CFLocaleLock(CFLocaleRef locale
) {
190 __CFSpinLock(&((struct __CFLocale
*)locale
)->_lock
);
193 CF_INLINE
void __CFLocaleUnlock(CFLocaleRef locale
) {
194 __CFSpinUnlock(&((struct __CFLocale
*)locale
)->_lock
);
198 static Boolean
__CFLocaleEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
199 CFLocaleRef locale1
= (CFLocaleRef
)cf1
;
200 CFLocaleRef locale2
= (CFLocaleRef
)cf2
;
201 // a user locale and a locale created with an ident are not the same even if their contents are
202 if (__CFLocaleGetType(locale1
) != __CFLocaleGetType(locale2
)) return false;
203 if (!CFEqual(locale1
->_identifier
, locale2
->_identifier
)) return false;
204 if (NULL
== locale1
->_overrides
&& NULL
!= locale2
->_overrides
) return false;
205 if (NULL
!= locale1
->_overrides
&& NULL
== locale2
->_overrides
) return false;
206 if (NULL
!= locale1
->_overrides
&& !CFEqual(locale1
->_overrides
, locale2
->_overrides
)) return false;
207 if (__kCFLocaleUser
== __CFLocaleGetType(locale1
)) {
208 return CFEqual(locale1
->_prefs
, locale2
->_prefs
);
213 static CFHashCode
__CFLocaleHash(CFTypeRef cf
) {
214 CFLocaleRef locale
= (CFLocaleRef
)cf
;
215 return CFHash(locale
->_identifier
);
218 static CFStringRef
__CFLocaleCopyDescription(CFTypeRef cf
) {
219 CFLocaleRef locale
= (CFLocaleRef
)cf
;
220 const char *type
= NULL
;
221 switch (__CFLocaleGetType(locale
)) {
222 case __kCFLocaleOrdinary
: type
= "ordinary"; break;
223 case __kCFLocaleSystem
: type
= "system"; break;
224 case __kCFLocaleUser
: type
= "user"; break;
225 case __kCFLocaleCustom
: type
= "custom"; break;
227 return CFStringCreateWithFormat(CFGetAllocator(locale
), NULL
, CFSTR("<CFLocale %p [%p]>{type = %s, identifier = '%@'}"), cf
, CFGetAllocator(locale
), type
, locale
->_identifier
);
230 static void __CFLocaleDeallocate(CFTypeRef cf
) {
231 CFLocaleRef locale
= (CFLocaleRef
)cf
;
232 CFRelease(locale
->_identifier
);
233 if (NULL
!= locale
->_cache
) CFRelease(locale
->_cache
);
234 if (NULL
!= locale
->_overrides
) CFRelease(locale
->_overrides
);
235 if (NULL
!= locale
->_prefs
) CFRelease(locale
->_prefs
);
238 static CFTypeID __kCFLocaleTypeID
= _kCFRuntimeNotATypeID
;
240 static const CFRuntimeClass __CFLocaleClass
= {
245 __CFLocaleDeallocate
,
249 __CFLocaleCopyDescription
252 static void __CFLocaleInitialize(void) {
254 __kCFLocaleTypeID
= _CFRuntimeRegisterClass(&__CFLocaleClass
);
255 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
256 // table fixup to workaround compiler/language limitations
257 __CFLocaleKeyTable
[idx
].key
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].key
);
258 if (NULL
!= __CFLocaleKeyTable
[idx
].context
) {
259 __CFLocaleKeyTable
[idx
].context
= *((CFStringRef
*)__CFLocaleKeyTable
[idx
].context
);
264 CFTypeID
CFLocaleGetTypeID(void) {
265 if (_kCFRuntimeNotATypeID
== __kCFLocaleTypeID
) __CFLocaleInitialize();
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
= CFSpinLockInit
;
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
= CFSpinLockInit
;
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 return (CFLocaleRef
)CFRetain(locale
);
450 CFStringRef
CFLocaleGetIdentifier(CFLocaleRef locale
) {
451 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef
, (NSLocale
*)locale
, localeIdentifier
);
452 return locale
->_identifier
;
455 CFTypeRef
CFLocaleGetValue(CFLocaleRef locale
, CFStringRef key
) {
456 #if DEPLOYMENT_TARGET_MACOSX
457 if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard
)) {
458 // Hack for Opera, which is using the hard-coded string value below instead of
459 // the perfectly good public kCFLocaleCountryCode constant, for whatever reason.
460 if (key
&& CFEqual(key
, CFSTR("locale:country code"))) {
461 key
= kCFLocaleCountryCodeKey
;
465 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFTypeRef
, (NSLocale
*)locale
, objectForKey
:(id
)key
);
466 CFIndex idx
, slot
= -1;
467 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
468 if (__CFLocaleKeyTable
[idx
].key
== key
) {
473 if (-1 == slot
&& NULL
!= key
) {
474 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
475 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
485 if (NULL
!= locale
->_overrides
&& CFDictionaryGetValueIfPresent(locale
->_overrides
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
488 __CFLocaleLock(locale
);
489 if (CFDictionaryGetValueIfPresent(locale
->_cache
, __CFLocaleKeyTable
[slot
].key
, &value
)) {
490 __CFLocaleUnlock(locale
);
493 if (__kCFLocaleUser
== __CFLocaleGetType(locale
) && __CFLocaleKeyTable
[slot
].get(locale
, true, &value
, __CFLocaleKeyTable
[slot
].context
)) {
494 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
495 if (value
) CFRelease(value
);
496 __CFLocaleUnlock(locale
);
499 if (__CFLocaleKeyTable
[slot
].get(locale
, false, &value
, __CFLocaleKeyTable
[slot
].context
)) {
500 if (value
) CFDictionarySetValue(locale
->_cache
, __CFLocaleKeyTable
[idx
].key
, value
);
501 if (value
) CFRelease(value
);
502 __CFLocaleUnlock(locale
);
505 __CFLocaleUnlock(locale
);
509 CFStringRef
CFLocaleCopyDisplayNameForPropertyValue(CFLocaleRef displayLocale
, CFStringRef key
, CFStringRef value
) {
510 CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef
, (NSLocale
*)displayLocale
, _copyDisplayNameForKey
:(id
)key value
:(id
)value
);
511 CFIndex idx
, slot
= -1;
512 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
513 if (__CFLocaleKeyTable
[idx
].key
== key
) {
518 if (-1 == slot
&& NULL
!= key
) {
519 for (idx
= 0; idx
< __kCFLocaleKeyTableCount
; idx
++) {
520 if (CFEqual(__CFLocaleKeyTable
[idx
].key
, key
)) {
526 if (-1 == slot
|| !value
) {
529 // Get the locale ID as a C string
530 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
531 char cValue
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
532 if (CFStringGetCString(displayLocale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
) && CFStringGetCString(value
, cValue
, sizeof(cValue
)/sizeof(char), kCFStringEncodingASCII
)) {
534 if ((NULL
== displayLocale
->_prefs
) && __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
)) {
538 // We could not find a result using the requested language. Fall back through all preferred languages.
539 CFArrayRef langPref
= NULL
;
540 if (displayLocale
->_prefs
) {
541 langPref
= (CFArrayRef
)CFDictionaryGetValue(displayLocale
->_prefs
, CFSTR("AppleLanguages"));
542 if (langPref
) CFRetain(langPref
);
544 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
545 langPref
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
548 if (langPref
!= NULL
) {
549 CFIndex count
= CFArrayGetCount(langPref
);
551 bool success
= false;
552 for (i
= 0; i
< count
&& !success
; ++i
) {
553 CFStringRef language
= (CFStringRef
)CFArrayGetValueAtIndex(langPref
, i
);
554 CFStringRef cleanLanguage
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, language
);
555 if (CFStringGetCString(cleanLanguage
, localeID
, sizeof(localeID
)/sizeof(localeID
[0]), kCFStringEncodingASCII
)) {
556 success
= __CFLocaleKeyTable
[slot
].name(localeID
, cValue
, &result
);
558 CFRelease(cleanLanguage
);
568 CFArrayRef
CFLocaleCopyAvailableLocaleIdentifiers(void) {
569 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
570 int32_t locale
, localeCount
= uloc_countAvailable();
571 CFMutableSetRef working
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeSetCallBacks
);
572 for (locale
= 0; locale
< localeCount
; ++locale
) {
573 const char *localeID
= uloc_getAvailable(locale
);
574 CFStringRef string1
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, localeID
, kCFStringEncodingASCII
);
575 // do not include canonicalized version as IntlFormats cannot cope with that in its popup
576 CFSetAddValue(working
, string1
);
579 CFIndex cnt
= CFSetGetCount(working
);
580 STACK_BUFFER_DECL(const void *, buffer
, cnt
);
581 CFSetGetValues(working
, buffer
);
582 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, buffer
, cnt
, &kCFTypeArrayCallBacks
);
586 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
590 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
591 static CFArrayRef
__CFLocaleCopyCStringsAsArray(const char* const* p
) {
592 CFMutableArrayRef working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
594 CFStringRef string
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, *p
, kCFStringEncodingASCII
);
595 CFArrayAppendValue(working
, string
);
598 CFArrayRef result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
603 static CFArrayRef
__CFLocaleCopyUEnumerationAsArray(UEnumeration
*enumer
, UErrorCode
*icuErr
) {
604 const UChar
*next
= NULL
;
606 CFMutableArrayRef working
= NULL
;
607 if (U_SUCCESS(*icuErr
)) {
608 working
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
610 while ((next
= uenum_unext(enumer
, &len
, icuErr
)) && U_SUCCESS(*icuErr
)) {
611 CFStringRef string
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)next
, (CFIndex
) len
);
612 CFArrayAppendValue(working
, string
);
615 if (*icuErr
== U_INDEX_OUTOFBOUNDS_ERROR
) {
616 *icuErr
= U_ZERO_ERROR
; // Temp: Work around bug (ICU 5220) in ucurr enumerator
618 CFArrayRef result
= NULL
;
619 if (U_SUCCESS(*icuErr
)) {
620 result
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, working
);
622 if (working
!= NULL
) {
629 CFArrayRef
CFLocaleCopyISOLanguageCodes(void) {
630 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
631 const char* const* p
= uloc_getISOLanguages();
632 return __CFLocaleCopyCStringsAsArray(p
);
634 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
638 CFArrayRef
CFLocaleCopyISOCountryCodes(void) {
639 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
640 const char* const* p
= uloc_getISOCountries();
641 return __CFLocaleCopyCStringsAsArray(p
);
643 return CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
647 CFArrayRef
CFLocaleCopyISOCurrencyCodes(void) {
648 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
649 UErrorCode icuStatus
= U_ZERO_ERROR
;
650 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_ALL
, &icuStatus
);
651 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
654 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
659 CFArrayRef
CFLocaleCopyCommonISOCurrencyCodes(void) {
660 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
661 UErrorCode icuStatus
= U_ZERO_ERROR
;
662 UEnumeration
*enumer
= ucurr_openISOCurrencies(UCURR_COMMON
|UCURR_NON_DEPRECATED
, &icuStatus
);
663 CFArrayRef result
= __CFLocaleCopyUEnumerationAsArray(enumer
, &icuStatus
);
666 CFArrayRef result
= CFArrayCreate(kCFAllocatorSystemDefault
, NULL
, 0, &kCFTypeArrayCallBacks
);
671 CFStringRef
CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(CFAllocatorRef allocator
, uint32_t lcid
) {
672 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
673 char buffer
[kMaxICUNameSize
];
674 UErrorCode status
= U_ZERO_ERROR
;
675 int32_t ret
= uloc_getLocaleForLCID(lcid
, buffer
, kMaxICUNameSize
, &status
);
676 if (U_FAILURE(status
) || kMaxICUNameSize
<= ret
) return NULL
;
677 CFStringRef str
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, buffer
, kCFStringEncodingASCII
);
678 CFStringRef ident
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, str
);
686 uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier
) {
687 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
688 CFStringRef ident
= CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault
, localeIdentifier
);
689 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
690 Boolean b
= ident
? CFStringGetCString(ident
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
691 if (ident
) CFRelease(ident
);
692 return b
? uloc_getLCID(localeID
) : 0;
698 CFLocaleLanguageDirection
CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode
) {
699 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
700 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
701 Boolean b
= isoLangCode
? CFStringGetCString(isoLangCode
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
702 CFLocaleLanguageDirection dir
;
703 UErrorCode status
= U_ZERO_ERROR
;
704 ULayoutType idir
= b
? uloc_getCharacterOrientation(localeID
, &status
) : ULOC_LAYOUT_UNKNOWN
;
706 case ULOC_LAYOUT_LTR
: dir
= kCFLocaleLanguageDirectionLeftToRight
; break;
707 case ULOC_LAYOUT_RTL
: dir
= kCFLocaleLanguageDirectionRightToLeft
; break;
708 case ULOC_LAYOUT_TTB
: dir
= kCFLocaleLanguageDirectionTopToBottom
; break;
709 case ULOC_LAYOUT_BTT
: dir
= kCFLocaleLanguageDirectionBottomToTop
; break;
710 default: dir
= kCFLocaleLanguageDirectionUnknown
; break;
714 return kCFLocaleLanguageDirectionLeftToRight
;
718 CFLocaleLanguageDirection
CFLocaleGetLanguageLineDirection(CFStringRef isoLangCode
) {
719 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
720 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
721 Boolean b
= isoLangCode
? CFStringGetCString(isoLangCode
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
) : false;
722 CFLocaleLanguageDirection dir
;
723 UErrorCode status
= U_ZERO_ERROR
;
724 ULayoutType idir
= b
? uloc_getLineOrientation(localeID
, &status
) : ULOC_LAYOUT_UNKNOWN
;
726 case ULOC_LAYOUT_LTR
: dir
= kCFLocaleLanguageDirectionLeftToRight
; break;
727 case ULOC_LAYOUT_RTL
: dir
= kCFLocaleLanguageDirectionRightToLeft
; break;
728 case ULOC_LAYOUT_TTB
: dir
= kCFLocaleLanguageDirectionTopToBottom
; break;
729 case ULOC_LAYOUT_BTT
: dir
= kCFLocaleLanguageDirectionBottomToTop
; break;
730 default: dir
= kCFLocaleLanguageDirectionUnknown
; break;
734 return kCFLocaleLanguageDirectionLeftToRight
;
738 CFArrayRef
CFLocaleCopyPreferredLanguages(void) {
739 CFMutableArrayRef newArray
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
740 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
741 CFArrayRef languagesArray
= (CFArrayRef
)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication
);
742 if (languagesArray
&& (CFArrayGetTypeID() == CFGetTypeID(languagesArray
))) {
743 for (CFIndex idx
= 0, cnt
= CFArrayGetCount(languagesArray
); idx
< cnt
; idx
++) {
744 CFStringRef str
= (CFStringRef
)CFArrayGetValueAtIndex(languagesArray
, idx
);
745 if (str
&& (CFStringGetTypeID() == CFGetTypeID(str
))) {
746 CFStringRef ident
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, str
);
747 CFArrayAppendValue(newArray
, ident
);
752 if (languagesArray
) CFRelease(languagesArray
);
757 // -------- -------- -------- -------- -------- --------
759 // These functions return true or false depending on the success or failure of the function.
760 // In the Copy case, this is failure to fill the *cf out parameter, and that out parameter is
761 // returned by reference WITH a retain on it.
762 static bool __CFLocaleSetNOP(CFMutableLocaleRef locale
, CFTypeRef cf
, CFStringRef context
) {
766 static bool __CFLocaleCopyLocaleID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
767 *cf
= CFRetain(locale
->_identifier
);
772 static bool __CFLocaleCopyCodes(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
773 CFDictionaryRef codes
= NULL
;
774 // this access of _cache is protected by the lock in CFLocaleGetValue()
775 if (!CFDictionaryGetValueIfPresent(locale
->_cache
, CFSTR("__kCFLocaleCodes"), (const void **)&codes
)) {
776 codes
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, locale
->_identifier
);
777 if (codes
) CFDictionarySetValue(locale
->_cache
, CFSTR("__kCFLocaleCodes"), codes
);
778 if (codes
) CFRelease(codes
);
781 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(codes
, context
); // context is one of kCFLocale*Code constants
782 if (value
) CFRetain(value
);
789 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
790 CFCharacterSetRef
_CFCreateCharacterSetFromUSet(USet
*set
) {
791 UErrorCode icuErr
= U_ZERO_ERROR
;
792 CFMutableCharacterSetRef working
= CFCharacterSetCreateMutable(NULL
);
793 UChar buffer
[2048]; // Suitable for most small sets
799 int32_t itemCount
= uset_getItemCount(set
);
801 for (i
= 0; i
< itemCount
; ++i
)
807 stringLen
= uset_getItem(set
, i
, &start
, &end
, buffer
, sizeof(buffer
)/sizeof(UChar
), &icuErr
);
808 if (icuErr
== U_BUFFER_OVERFLOW_ERROR
)
810 string
= (UChar
*) malloc(sizeof(UChar
)*(stringLen
+1));
816 icuErr
= U_ZERO_ERROR
;
817 (void) uset_getItem(set
, i
, &start
, &end
, string
, stringLen
+1, &icuErr
);
819 if (U_FAILURE(icuErr
))
821 if (string
!= buffer
)
827 CFCharacterSetAddCharactersInRange(working
, CFRangeMake(start
, end
-start
+1));
830 CFStringRef cfString
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, (UniChar
*)string
, stringLen
, kCFAllocatorNull
);
831 CFCharacterSetAddCharactersInString(working
, cfString
);
834 if (string
!= buffer
)
838 CFCharacterSetRef result
= CFCharacterSetCreateCopy(kCFAllocatorSystemDefault
, working
);
844 static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
845 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
846 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
847 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
848 UErrorCode icuStatus
= U_ZERO_ERROR
;
849 ULocaleData
* uld
= ulocdata_open(localeID
, &icuStatus
);
850 USet
*set
= ulocdata_getExemplarSet(uld
, NULL
, USET_ADD_CASE_MAPPINGS
, ULOCDATA_ES_STANDARD
, &icuStatus
);
852 if (U_FAILURE(icuStatus
))
854 if (icuStatus
== U_USING_DEFAULT_WARNING
) // If default locale used, force to empty set
856 *cf
= (CFTypeRef
) _CFCreateCharacterSetFromUSet(set
);
858 return (*cf
!= NULL
);
864 static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
, const char *keyword
)
866 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
867 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
868 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
))
870 char value
[ULOC_KEYWORD_AND_VALUES_CAPACITY
];
871 UErrorCode icuStatus
= U_ZERO_ERROR
;
872 if (uloc_getKeywordValue(localeID
, keyword
, value
, sizeof(value
)/sizeof(char), &icuStatus
) > 0 && U_SUCCESS(icuStatus
))
874 *cf
= (CFTypeRef
) CFStringCreateWithCString(kCFAllocatorSystemDefault
, value
, kCFStringEncodingASCII
);
883 static bool __CFLocaleCopyICUCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
, const char *keyword
) {
884 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
885 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
886 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
887 UErrorCode icuStatus
= U_ZERO_ERROR
;
888 UEnumeration
*en
= ucal_getKeywordValuesForLocale(keyword
, localeID
, TRUE
, &icuStatus
);
890 const char *value
= uenum_next(en
, &len
, &icuStatus
);
891 if (U_SUCCESS(icuStatus
)) {
892 *cf
= (CFTypeRef
) CFStringCreateWithCString(kCFAllocatorSystemDefault
, value
, kCFStringEncodingASCII
);
903 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
904 bool succeeded
= __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCalendarKeyword
);
906 succeeded
= __CFLocaleCopyICUCalendarID(locale
, user
, cf
, context
, kCalendarKeyword
);
909 if (CFEqual(*cf
, kCFCalendarIdentifierGregorian
)) {
911 *cf
= CFRetain(kCFCalendarIdentifierGregorian
);
912 } else if (CFEqual(*cf
, kCFCalendarIdentifierBuddhist
)) {
914 *cf
= CFRetain(kCFCalendarIdentifierBuddhist
);
915 } else if (CFEqual(*cf
, kCFCalendarIdentifierJapanese
)) {
917 *cf
= CFRetain(kCFCalendarIdentifierJapanese
);
918 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamic
)) {
920 *cf
= CFRetain(kCFCalendarIdentifierIslamic
);
921 } else if (CFEqual(*cf
, kCFCalendarIdentifierIslamicCivil
)) {
923 *cf
= CFRetain(kCFCalendarIdentifierIslamicCivil
);
924 } else if (CFEqual(*cf
, kCFCalendarIdentifierHebrew
)) {
926 *cf
= CFRetain(kCFCalendarIdentifierHebrew
);
927 } else if (CFEqual(*cf
, kCFCalendarIdentifierChinese
)) {
929 *cf
= CFRetain(kCFCalendarIdentifierChinese
);
930 } else if (CFEqual(*cf
, kCFCalendarIdentifierRepublicOfChina
)) {
932 *cf
= CFRetain(kCFCalendarIdentifierRepublicOfChina
);
933 } else if (CFEqual(*cf
, kCFCalendarIdentifierPersian
)) {
935 *cf
= CFRetain(kCFCalendarIdentifierPersian
);
936 } else if (CFEqual(*cf
, kCFCalendarIdentifierIndian
)) {
938 *cf
= CFRetain(kCFCalendarIdentifierIndian
);
939 } else if (CFEqual(*cf
, kCFCalendarIdentifierISO8601
)) {
941 *cf
= CFRetain(kCFCalendarIdentifierISO8601
);
942 } else if (CFEqual(*cf
, kCFCalendarIdentifierCoptic
)) {
944 *cf
= CFRetain(kCFCalendarIdentifierCoptic
);
945 } else if (CFEqual(*cf
, kCFCalendarIdentifierEthiopicAmeteMihret
)) {
947 *cf
= CFRetain(kCFCalendarIdentifierEthiopicAmeteMihret
);
948 } else if (CFEqual(*cf
, kCFCalendarIdentifierEthiopicAmeteAlem
)) {
950 *cf
= CFRetain(kCFCalendarIdentifierEthiopicAmeteAlem
);
957 *cf
= CFRetain(kCFCalendarIdentifierGregorian
);
962 static bool __CFLocaleCopyCalendar(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
963 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
964 if (__CFLocaleCopyCalendarID(locale
, user
, cf
, context
)) {
965 CFCalendarRef calendar
= CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault
, (CFStringRef
)*cf
);
966 CFCalendarSetLocale(calendar
, locale
);
967 CFDictionaryRef prefs
= __CFLocaleGetPrefs(locale
);
968 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleFirstWeekday")) : NULL
;
969 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
970 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, *cf
);
972 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
974 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &wkdy
)) {
975 CFCalendarSetFirstWeekday(calendar
, wkdy
);
978 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleMinDaysInFirstWeek")) : NULL
;
979 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
980 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, *cf
);
982 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
984 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &mwd
)) {
985 CFCalendarSetMinimumDaysInFirstWeek(calendar
, mwd
);
996 static bool __CFLocaleCopyDelimiter(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
997 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
998 ULocaleDataDelimiterType type
= (ULocaleDataDelimiterType
)0;
999 if (context
== kCFLocaleQuotationBeginDelimiterKey
) {
1000 type
= ULOCDATA_QUOTATION_START
;
1001 } else if (context
== kCFLocaleQuotationEndDelimiterKey
) {
1002 type
= ULOCDATA_QUOTATION_END
;
1003 } else if (context
== kCFLocaleAlternateQuotationBeginDelimiterKey
) {
1004 type
= ULOCDATA_ALT_QUOTATION_START
;
1005 } else if (context
== kCFLocaleAlternateQuotationEndDelimiterKey
) {
1006 type
= ULOCDATA_ALT_QUOTATION_END
;
1011 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1012 if (!CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
1017 UErrorCode status
= U_ZERO_ERROR
;
1018 ULocaleData
*uld
= ulocdata_open(localeID
, &status
);
1019 int32_t len
= ulocdata_getDelimiter(uld
, type
, buffer
, sizeof(buffer
) / sizeof(buffer
[0]), &status
);
1020 ulocdata_close(uld
);
1021 if (U_FAILURE(status
) || sizeof(buffer
) / sizeof(buffer
[0]) < len
) {
1025 *cf
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)buffer
, len
);
1026 return (*cf
!= NULL
);
1028 if (context
== kCFLocaleQuotationBeginDelimiterKey
|| context
== kCFLocaleQuotationEndDelimiterKey
|| context
== kCFLocaleAlternateQuotationBeginDelimiterKey
|| context
== kCFLocaleAlternateQuotationEndDelimiterKey
) {
1029 *cf
= CFRetain(CFSTR("\""));
1037 static bool __CFLocaleCopyCollationID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1038 return __CFLocaleCopyICUKeyword(locale
, user
, cf
, context
, kCollationKeyword
);
1041 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1042 CFStringRef canonLocaleCFStr
= NULL
;
1043 if (user
&& locale
->_prefs
) {
1044 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleCollationOrder"));
1046 // Canonicalize pref string in case it's not in the canonical format.
1047 canonLocaleCFStr
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, pref
);
1049 CFArrayRef languagesArray
= (CFArrayRef
)CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleLanguages"));
1050 if (languagesArray
&& (CFArrayGetTypeID() == CFGetTypeID(languagesArray
))) {
1051 if (0 < CFArrayGetCount(languagesArray
)) {
1052 CFStringRef str
= (CFStringRef
)CFArrayGetValueAtIndex(languagesArray
, 0);
1053 if (str
&& (CFStringGetTypeID() == CFGetTypeID(str
))) {
1054 canonLocaleCFStr
= CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault
, str
);
1060 if (!canonLocaleCFStr
) {
1061 canonLocaleCFStr
= CFLocaleGetIdentifier(locale
);
1062 CFRetain(canonLocaleCFStr
);
1064 *cf
= canonLocaleCFStr
;
1065 return canonLocaleCFStr
? true : false;
1068 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1069 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1070 bool us
= false; // Default is Metric
1072 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1074 CFTypeRef pref
= CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleMetricUnits"));
1076 us
= (kCFBooleanFalse
== pref
);
1079 pref
= CFDictionaryGetValue(locale
->_prefs
, CFSTR("AppleMeasurementUnits"));
1081 us
= CFEqual(pref
, CFSTR("Inches"));
1088 char localeID
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1089 if (CFStringGetCString(locale
->_identifier
, localeID
, sizeof(localeID
)/sizeof(char), kCFStringEncodingASCII
)) {
1090 UErrorCode icuStatus
= U_ZERO_ERROR
;
1091 UMeasurementSystem ms
= UMS_SI
;
1092 ms
= ulocdata_getMeasurementSystem(localeID
, &icuStatus
);
1093 if (U_SUCCESS(icuStatus
)) {
1094 us
= (ms
== UMS_US
);
1101 *cf
= us
? CFRetain(kCFBooleanFalse
) : CFRetain(kCFBooleanTrue
);
1104 *cf
= CFRetain(kCFBooleanFalse
);
1109 static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1110 if (__CFLocaleCopyUsesMetric(locale
, user
, cf
, context
)) {
1111 bool us
= (*cf
== kCFBooleanFalse
);
1113 *cf
= us
? CFRetain(CFSTR("U.S.")) : CFRetain(CFSTR("Metric"));
1119 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1120 CFStringRef str
= NULL
;
1121 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1122 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterDecimalStyle
);
1123 str
= nf
? (CFStringRef
)CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
1124 if (nf
) CFRelease(nf
);
1133 // ICU does not reliably set up currency info for other than Currency-type formatters,
1134 // so we have to have another routine here which creates a Currency number formatter.
1135 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale
, bool user
, CFTypeRef
*cf
, CFStringRef context
) {
1136 CFStringRef str
= NULL
;
1137 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1138 CFNumberFormatterRef nf
= CFNumberFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFNumberFormatterCurrencyStyle
);
1139 str
= nf
? (CFStringRef
)CFNumberFormatterCopyProperty(nf
, context
) : NULL
;
1140 if (nf
) CFRelease(nf
);
1149 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1150 typedef int32_t (*__CFICUFunction
)(const char *, const char *, UChar
*, int32_t, UErrorCode
*);
1152 static bool __CFLocaleICUName(const char *locale
, const char *valLocale
, CFStringRef
*out
, __CFICUFunction icu
) {
1153 UErrorCode icuStatus
= U_ZERO_ERROR
;
1155 UChar name
[kMaxICUNameSize
];
1157 size
= (*icu
)(valLocale
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1158 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
1159 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1160 return (*out
!= NULL
);
1165 static bool __CFLocaleICUKeywordValueName(const char *locale
, const char *value
, const char *keyword
, CFStringRef
*out
) {
1166 UErrorCode icuStatus
= U_ZERO_ERROR
;
1168 UChar name
[kMaxICUNameSize
];
1169 // Need to make a fake locale ID
1170 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1171 if (strlen(value
) < ULOC_KEYWORD_AND_VALUES_CAPACITY
) {
1172 strlcpy(lid
, "en_US@", sizeof(lid
));
1173 strlcat(lid
, keyword
, sizeof(lid
));
1174 strlcat(lid
, "=", sizeof(lid
));
1175 strlcat(lid
, value
, sizeof(lid
));
1176 size
= uloc_getDisplayKeywordValue(lid
, keyword
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1177 if (U_SUCCESS(icuStatus
) && size
> 0 && icuStatus
!= U_USING_DEFAULT_WARNING
) {
1178 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1179 return (*out
!= NULL
);
1185 static bool __CFLocaleICUCurrencyName(const char *locale
, const char *value
, UCurrNameStyle style
, CFStringRef
*out
) {
1186 int valLen
= strlen(value
);
1187 if (valLen
!= 3) // not a valid ISO code
1190 UBool isChoice
= FALSE
;
1192 UErrorCode icuStatus
= U_ZERO_ERROR
;
1193 u_charsToUChars(value
, curr
, valLen
);
1194 curr
[valLen
] = '\0';
1196 name
= ucurr_getName(curr
, locale
, style
, &isChoice
, &size
, &icuStatus
);
1197 if (U_FAILURE(icuStatus
) || icuStatus
== U_USING_DEFAULT_WARNING
)
1199 UChar result
[kMaxICUNameSize
];
1202 UChar pattern
[kMaxICUNameSize
];
1203 CFStringRef patternRef
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("{0,choice,%S}"), name
);
1204 CFIndex pattlen
= CFStringGetLength(patternRef
);
1205 CFStringGetCharacters(patternRef
, CFRangeMake(0, pattlen
), (UniChar
*)pattern
);
1206 CFRelease(patternRef
);
1207 pattern
[pattlen
] = '\0'; // null terminate the pattern
1208 // Format the message assuming a large amount of the currency
1209 size
= u_formatMessage("en_US", pattern
, pattlen
, result
, kMaxICUNameSize
, &icuStatus
, 10.0);
1210 if (U_FAILURE(icuStatus
))
1215 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1216 return (*out
!= NULL
);
1220 static bool __CFLocaleFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
1221 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1222 UErrorCode icuStatus
= U_ZERO_ERROR
;
1224 UChar name
[kMaxICUNameSize
];
1226 // First, try to get the full locale.
1227 size
= uloc_getDisplayName(value
, locale
, name
, kMaxICUNameSize
, &icuStatus
);
1228 if (U_FAILURE(icuStatus
) || size
<= 0)
1231 // Did we wind up using a default somewhere?
1232 if (icuStatus
== U_USING_DEFAULT_WARNING
) {
1233 // For some locale IDs, there may be no language which has a translation for every
1234 // piece. Rather than return nothing, see if we can at least handle
1235 // the language part of the locale.
1236 UErrorCode localStatus
= U_ZERO_ERROR
;
1238 UChar localName
[kMaxICUNameSize
];
1239 localSize
= uloc_getDisplayLanguage(value
, locale
, localName
, kMaxICUNameSize
, &localStatus
);
1240 if (U_FAILURE(localStatus
) || size
<= 0 || localStatus
== U_USING_DEFAULT_WARNING
)
1244 // This locale is OK, so use the result.
1245 *out
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)name
, size
);
1246 return (*out
!= NULL
);
1248 *out
= CFRetain(CFSTR("(none)"));
1253 static bool __CFLocaleLanguageName(const char *locale
, const char *value
, CFStringRef
*out
) {
1254 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1255 return __CFLocaleICUName(locale
, value
, out
, uloc_getDisplayLanguage
);
1257 *out
= CFRetain(CFSTR("(none)"));
1262 static bool __CFLocaleCountryName(const char *locale
, const char *value
, CFStringRef
*out
) {
1263 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1264 // Need to make a fake locale ID
1265 char lid
[ULOC_FULLNAME_CAPACITY
];
1266 if (strlen(value
) < sizeof(lid
) - 3) {
1267 strlcpy(lid
, "en_", sizeof(lid
));
1268 strlcat(lid
, value
, sizeof(lid
));
1269 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayCountry
);
1273 *out
= CFRetain(CFSTR("(none)"));
1278 static bool __CFLocaleScriptName(const char *locale
, const char *value
, CFStringRef
*out
) {
1279 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1280 // Need to make a fake locale ID
1281 char lid
[ULOC_FULLNAME_CAPACITY
];
1282 if (strlen(value
) == 4) {
1283 strlcpy(lid
, "en_", sizeof(lid
));
1284 strlcat(lid
, value
, sizeof(lid
));
1285 strlcat(lid
, "_US", sizeof(lid
));
1286 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayScript
);
1290 *out
= CFRetain(CFSTR("(none)"));
1295 static bool __CFLocaleVariantName(const char *locale
, const char *value
, CFStringRef
*out
) {
1296 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1297 // Need to make a fake locale ID
1298 char lid
[ULOC_FULLNAME_CAPACITY
+ULOC_KEYWORD_AND_VALUES_CAPACITY
];
1299 if (strlen(value
) < sizeof(lid
) - 6) {
1300 strlcpy(lid
, "en_US_", sizeof(lid
));
1301 strlcat(lid
, value
, sizeof(lid
));
1302 return __CFLocaleICUName(locale
, lid
, out
, uloc_getDisplayVariant
);
1306 *out
= CFRetain(CFSTR("(none)"));
1311 static bool __CFLocaleCalendarName(const char *locale
, const char *value
, CFStringRef
*out
) {
1312 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1313 return __CFLocaleICUKeywordValueName(locale
, value
, kCalendarKeyword
, out
);
1315 *out
= CFRetain(CFSTR("(none)"));
1320 static bool __CFLocaleCollationName(const char *locale
, const char *value
, CFStringRef
*out
) {
1321 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1322 return __CFLocaleICUKeywordValueName(locale
, value
, kCollationKeyword
, out
);
1324 *out
= CFRetain(CFSTR("(none)"));
1329 static bool __CFLocaleCurrencyShortName(const char *locale
, const char *value
, CFStringRef
*out
) {
1330 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1331 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_SYMBOL_NAME
, out
);
1333 *out
= CFRetain(CFSTR("(none)"));
1338 static bool __CFLocaleCurrencyFullName(const char *locale
, const char *value
, CFStringRef
*out
) {
1339 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
1340 return __CFLocaleICUCurrencyName(locale
, value
, UCURR_LONG_NAME
, out
);
1342 *out
= CFRetain(CFSTR("(none)"));
1347 static bool __CFLocaleNoName(const char *locale
, const char *value
, CFStringRef
*out
) {
1351 #undef kMaxICUNameSize