/ CFLocale.c
CFLocale.c
   1  /*
   2   * Copyright (c) 2015 Apple Inc. All rights reserved.
   3   *
   4   * @APPLE_LICENSE_HEADER_START@
   5   *
   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
  11   * file.
  12   *
  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.
  20   *
  21   * @APPLE_LICENSE_HEADER_END@
  22   */
  23  
  24  /*  CFLocale.c
  25      Copyright (c) 2002-2014, Apple Inc. All rights reserved.
  26      Responsibility: David Smith
  27  */
  28  
  29  // Note the header file is in the OpenSource set (stripped to almost nothing), but not the .c file
  30  
  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>
  49  #endif
  50  #include <CoreFoundation/CFNumberFormatter.h>
  51  #include <stdlib.h>
  52  #include <stdio.h>
  53  #include <string.h>
  54  
  55  #if DEPLOYMENT_TARGET_EMBEDDED_MINI
  56  // Some compatability definitions
  57  #define ULOC_FULLNAME_CAPACITY 157
  58  #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
  59  
  60  //typedef long UErrorCode;
  61  //#define U_BUFFER_OVERFLOW_ERROR 15
  62  //#define U_ZERO_ERROR 0
  63  //
  64  //typedef uint16_t UChar;
  65  #endif
  66  
  67  
  68  CONST_STRING_DECL(kCFLocaleCurrentLocaleDidChangeNotification, "kCFLocaleCurrentLocaleDidChangeNotification")
  69  
  70  static const char *kCalendarKeyword = "calendar";
  71  static const char *kCollationKeyword = "collation";
  72  #define kMaxICUNameSize 1024
  73  
  74  typedef struct __CFLocale *CFMutableLocaleRef;
  75  
  76  PE_CONST_STRING_DECL(__kCFLocaleCollatorID, "locale:collator id")
  77  
  78  
  79  enum {
  80      __kCFLocaleKeyTableCount = 21
  81  };
  82  
  83  struct key_table {
  84      CFStringRef key;
  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 *); 
  88      CFStringRef context;
  89  };
  90  
  91  
  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);
 116  
 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},
 140  };
 141  
 142  
 143  static CFLocaleRef __CFLocaleSystem = NULL;
 144  static CFMutableDictionaryRef __CFLocaleCache = NULL;
 145  static CFLock_t __CFLocaleGlobalLock = CFLockInit;
 146  
 147  struct __CFLocale {
 148      CFRuntimeBase _base;
 149      CFStringRef _identifier;    // canonical identifier, never NULL
 150      CFMutableDictionaryRef _cache;
 151      CFMutableDictionaryRef _overrides;
 152      CFDictionaryRef _prefs;
 153      CFLock_t _lock;
 154      Boolean _nullLocale;
 155  };
 156   
 157  CF_PRIVATE Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale) {
 158      CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), Boolean, (NSLocale *)locale, _nullLocale);
 159      return locale->_nullLocale;
 160  }
 161  
 162  CF_PRIVATE void __CFLocaleSetNullLocale(struct __CFLocale *locale) {
 163      CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), void, (NSLocale *)locale, _setNullLocale);
 164      locale->_nullLocale = true;
 165  }
 166  
 167  /* Flag bits */
 168  enum {      /* Bits 0-1 */
 169      __kCFLocaleOrdinary = 0,
 170      __kCFLocaleSystem = 1,
 171      __kCFLocaleUser = 2,
 172      __kCFLocaleCustom = 3
 173  };
 174  
 175  CF_INLINE CFIndex __CFLocaleGetType(CFLocaleRef locale) {
 176      return __CFBitfieldGetValue(((const CFRuntimeBase *)locale)->_cfinfo[CF_INFO_BITS], 1, 0);
 177  }
 178  
 179  CF_INLINE void __CFLocaleSetType(CFLocaleRef locale, CFIndex type) {
 180      __CFBitfieldSetValue(((CFRuntimeBase *)locale)->_cfinfo[CF_INFO_BITS], 1, 0, (uint8_t)type);
 181  }
 182  
 183  CF_INLINE void __CFLocaleLockGlobal(void) {
 184      __CFLock(&__CFLocaleGlobalLock);
 185  }
 186  
 187  CF_INLINE void __CFLocaleUnlockGlobal(void) {
 188      __CFUnlock(&__CFLocaleGlobalLock);
 189  }
 190  
 191  CF_INLINE void __CFLocaleLock(CFLocaleRef locale) {
 192      __CFLock(&((struct __CFLocale *)locale)->_lock);
 193  }
 194  
 195  CF_INLINE void __CFLocaleUnlock(CFLocaleRef locale) {
 196      __CFUnlock(&((struct __CFLocale *)locale)->_lock);
 197  }
 198  
 199  
 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);
 211      }
 212      return true;
 213  }
 214  
 215  static CFHashCode __CFLocaleHash(CFTypeRef cf) {
 216      CFLocaleRef locale = (CFLocaleRef)cf;
 217      return CFHash(locale->_identifier);
 218  }
 219  
 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;
 228      }
 229      return CFStringCreateWithFormat(CFGetAllocator(locale), NULL, CFSTR("<CFLocale %p [%p]>{type = %s, identifier = '%@'}"), cf, CFGetAllocator(locale), type, locale->_identifier);
 230  }
 231  
 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);
 238  }
 239  
 240  static CFTypeID __kCFLocaleTypeID = _kCFRuntimeNotATypeID;
 241  
 242  static const CFRuntimeClass __CFLocaleClass = {
 243      0,
 244      "CFLocale",
 245      NULL,   // init
 246      NULL,   // copy
 247      __CFLocaleDeallocate,
 248      __CFLocaleEqual,
 249      __CFLocaleHash,
 250      NULL,   // 
 251      __CFLocaleCopyDescription
 252  };
 253  
 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);
 263              }
 264          }
 265      });
 266      return __kCFLocaleTypeID;
 267  }
 268  
 269  CFLocaleRef CFLocaleGetSystem(void) {
 270      CFLocaleRef locale;
 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;
 280  	} else {
 281  	    if (locale) CFRelease(locale);
 282  	}
 283      }
 284      locale = __CFLocaleSystem ? (CFLocaleRef)CFRetain(__CFLocaleSystem) : NULL;
 285      __CFLocaleUnlockGlobal();
 286      return locale;
 287  }
 288  
 289  extern CFDictionaryRef __CFXPreferencesCopyCurrentApplicationState(void);
 290  
 291  static CFLocaleRef __CFLocaleCurrent = NULL;
 292  
 293  
 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")
 300  #endif
 301  
 302  static CFLocaleRef _CFLocaleCopyCurrentGuts(CFStringRef name, Boolean useCache, CFDictionaryRef overridePrefs) {
 303      
 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
 308      // a short period.
 309      if (!name) {
 310  #if 0 // DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
 311          name = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication);
 312  #endif
 313      } else {
 314          CFRetain(name);
 315      }
 316      if (name && (CFStringGetTypeID() == CFGetTypeID(name))) {
 317          ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, name);
 318      }
 319      if (name) CFRelease(name);
 320      
 321      if (useCache) {
 322          CFLocaleRef oldLocale = NULL;
 323          __CFLocaleLockGlobal();
 324          if (__CFLocaleCurrent) {
 325              if (ident && !CFEqual(__CFLocaleCurrent->_identifier, ident)) {
 326                  oldLocale = __CFLocaleCurrent;
 327                  __CFLocaleCurrent = NULL;
 328              } else {
 329                  CFLocaleRef res = __CFLocaleCurrent;
 330                  CFRetain(res);
 331                  __CFLocaleUnlockGlobal();
 332                  if (ident) CFRelease(ident);
 333                  return res;
 334              }
 335          }
 336          __CFLocaleUnlockGlobal();
 337          if (oldLocale) CFRelease(oldLocale);
 338      }
 339      
 340      CFDictionaryRef prefs = NULL;
 341      
 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);
 348  	return NULL;
 349      }
 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;
 358      
 359      if (useCache) {
 360          __CFLocaleLockGlobal();
 361          if (NULL == __CFLocaleCurrent) {
 362              __CFLocaleCurrent = locale;
 363          } else {
 364              CFRelease(locale);
 365          }
 366          locale = (struct __CFLocale *)CFRetain(__CFLocaleCurrent);
 367          __CFLocaleUnlockGlobal();
 368      }
 369      return locale;
 370  }
 371  
 372  /*
 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()
 375   */
 376  CFLocaleRef _CFLocaleCopyAsIfCurrent(CFStringRef name) {
 377      return _CFLocaleCopyCurrentGuts(name, false, NULL);
 378  }
 379  
 380  /*
 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()
 383   */
 384  CFLocaleRef _CFLocaleCopyAsIfCurrentWithOverrides(CFStringRef name, CFDictionaryRef overrides) {
 385      return _CFLocaleCopyCurrentGuts(name, false, overrides);
 386  }
 387  
 388  CFLocaleRef CFLocaleCopyCurrent(void) {
 389      return _CFLocaleCopyCurrentGuts(NULL, true, NULL);
 390  }
 391  
 392  CF_PRIVATE CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale) {
 393      CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFDictionaryRef, (NSLocale *)locale, _prefs);
 394      return locale->_prefs;
 395  }
 396  
 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;
 402      if (identifier) {
 403  	localeIdentifier = CFLocaleCreateCanonicalLocaleIdentifierFromString(allocator, identifier);
 404      }
 405      if (NULL == localeIdentifier) return NULL;
 406      CFStringRef old = localeIdentifier;
 407      localeIdentifier = (CFStringRef)CFStringCreateCopy(allocator, localeIdentifier);
 408      CFRelease(old);
 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);
 417  	if (locale) {
 418  	    CFRetain(locale);
 419  	    __CFLocaleUnlockGlobal();
 420  	    CFRelease(localeIdentifier);
 421  	    return locale;
 422  	}
 423      }
 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) {
 428  	return NULL;
 429      }
 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;
 436      if (canCache) {
 437  	if (NULL == __CFLocaleCache) {
 438  	    __CFLocaleCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 439  	}
 440          CFDictionarySetValue(__CFLocaleCache, localeIdentifier, locale);
 441      }
 442      __CFLocaleUnlockGlobal();
 443      return (CFLocaleRef)locale;
 444  }
 445  
 446  CFLocaleRef CFLocaleCreateCopy(CFAllocatorRef allocator, CFLocaleRef locale) {
 447      CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFLocaleRef, (NSLocale *)locale, copy);
 448      return (CFLocaleRef)CFRetain(locale);
 449  }
 450  
 451  CFStringRef CFLocaleGetIdentifier(CFLocaleRef locale) {
 452      CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef, (NSLocale *)locale, localeIdentifier);
 453      return locale->_identifier;
 454  }
 455  
 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;
 463  	}
 464      }
 465  #endif
 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) {
 470  	    slot = idx;
 471  	    break;
 472  	}
 473      }
 474      if (-1 == slot && NULL != key) {
 475  	for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) {
 476  	    if (CFEqual(__CFLocaleKeyTable[idx].key, key)) {
 477  		slot = idx;
 478  		break;
 479  	    }
 480  	}
 481      }
 482      if (-1 == slot) {
 483  	return NULL;
 484      }
 485      CFTypeRef value;
 486      if (NULL != locale->_overrides && CFDictionaryGetValueIfPresent(locale->_overrides, __CFLocaleKeyTable[slot].key, &value)) {
 487  	return value;
 488      }
 489      __CFLocaleLock(locale);
 490      if (CFDictionaryGetValueIfPresent(locale->_cache, __CFLocaleKeyTable[slot].key, &value)) {
 491  	__CFLocaleUnlock(locale);
 492  	return value;
 493      }
 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);
 498  	return value;
 499      }
 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);
 504  	return value;
 505      }
 506      __CFLocaleUnlock(locale);
 507      return NULL;
 508  }
 509  
 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) {
 515  	    slot = idx;
 516  	    break;
 517  	}
 518      }
 519      if (-1 == slot && NULL != key) {
 520  	for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) {
 521  	    if (CFEqual(__CFLocaleKeyTable[idx].key, key)) {
 522  		slot = idx;
 523  		break;
 524  	    }
 525  	}
 526      }
 527      if (-1 == slot || !value) {
 528  	return NULL;
 529      }
 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)) {
 534          CFStringRef result;
 535          if ((NULL == displayLocale->_prefs) && __CFLocaleKeyTable[slot].name(localeID, cValue, &result)) {
 536              return result;
 537          }
 538  
 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);
 544  	} else {
 545  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
 546  	    langPref = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
 547  #endif
 548  	}
 549          if (langPref != NULL) {
 550              CFIndex count = CFArrayGetCount(langPref);
 551              CFIndex i;
 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);
 558  		}
 559                  CFRelease(cleanLanguage);
 560              }
 561  	    CFRelease(langPref);
 562              if (success)
 563                  return result;
 564          }
 565      }
 566      return NULL;
 567  }
 568  
 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);
 578          CFRelease(string1);
 579      }
 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);
 584      CFRelease(working);
 585      return result;
 586  #else
 587      return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
 588  #endif
 589  }
 590  
 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);
 594      for (; *p; ++p) {
 595          CFStringRef string = CFStringCreateWithCString(kCFAllocatorSystemDefault, *p, kCFStringEncodingASCII);
 596          CFArrayAppendValue(working, string);
 597          CFRelease(string);
 598      }
 599      CFArrayRef result = CFArrayCreateCopy(kCFAllocatorSystemDefault, working);
 600      CFRelease(working);
 601      return result;
 602  }
 603  
 604  static CFArrayRef __CFLocaleCopyUEnumerationAsArray(UEnumeration *enumer, UErrorCode *icuErr) {
 605      const UChar *next = NULL;
 606      int32_t len = 0;
 607      CFMutableArrayRef working = NULL;
 608      if (U_SUCCESS(*icuErr)) {
 609          working = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
 610      }
 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);
 614          CFRelease(string);
 615      }
 616      if (*icuErr == U_INDEX_OUTOFBOUNDS_ERROR) {
 617          *icuErr = U_ZERO_ERROR;      // Temp: Work around bug (ICU 5220) in ucurr enumerator
 618      }
 619      CFArrayRef result = NULL;
 620      if (U_SUCCESS(*icuErr)) {
 621          result = CFArrayCreateCopy(kCFAllocatorSystemDefault, working);
 622      }
 623      if (working != NULL) {
 624          CFRelease(working);
 625      }
 626      return result;
 627  }
 628  #endif
 629  
 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);
 634  #else
 635      return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
 636  #endif
 637  }
 638  
 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);
 643  #else
 644      return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
 645  #endif
 646  }
 647  
 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);
 653      uenum_close(enumer);
 654  #else
 655      CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
 656  #endif
 657      return result;
 658  }
 659  
 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);
 665      uenum_close(enumer);
 666  #else
 667      CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
 668  #endif
 669      return result;
 670  }
 671  
 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);
 680      CFRelease(str);
 681      return ident;
 682  #else
 683      return CFSTR("");
 684  #endif
 685  }
 686  
 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;
 694  #else
 695      return 0;
 696  #endif
 697  }
 698  
 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;
 706      switch (idir) {
 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;
 712      }
 713      return dir;
 714  #else
 715      return kCFLocaleLanguageDirectionLeftToRight;
 716  #endif
 717  }
 718  
 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;
 726      switch (idir) {
 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;
 732      }
 733      return dir;
 734  #else
 735      return kCFLocaleLanguageDirectionLeftToRight;
 736  #endif
 737  }
 738  
 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);
 749  		CFRelease(ident);
 750  	    }
 751  	}
 752      }
 753      if (languagesArray)	CFRelease(languagesArray);
 754  #endif
 755      return newArray;
 756  }
 757  
 758  // -------- -------- -------- -------- -------- --------
 759  
 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) {
 764      return false;
 765  }
 766  
 767  static bool __CFLocaleCopyLocaleID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
 768      *cf = CFRetain(locale->_identifier);
 769      return true;
 770  }
 771  
 772  
 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);
 780      }
 781      if (codes) {
 782  	CFStringRef value = (CFStringRef)CFDictionaryGetValue(codes, context); // context is one of kCFLocale*Code constants
 783  	if (value) CFRetain(value);
 784  	*cf = value;
 785  	return true;
 786      }
 787      return false;
 788  }
 789  
 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
 795      int32_t stringLen;
 796  
 797      if (working == NULL)
 798          return NULL;
 799  
 800      int32_t itemCount = uset_getItemCount(set);
 801      int32_t i;
 802      for (i = 0; i < itemCount; ++i)
 803      {
 804          UChar32   start, end;
 805          UChar * string;
 806  
 807          string = buffer;
 808          stringLen = uset_getItem(set, i, &start, &end, buffer, sizeof(buffer)/sizeof(UChar), &icuErr);
 809          if (icuErr == U_BUFFER_OVERFLOW_ERROR)
 810          {
 811              string = (UChar *) malloc(sizeof(UChar)*(stringLen+1));
 812              if (!string)
 813              {
 814                  CFRelease(working);
 815                  return NULL;
 816              }
 817              icuErr = U_ZERO_ERROR;
 818              (void) uset_getItem(set, i, &start, &end, string, stringLen+1, &icuErr);
 819          }
 820          if (U_FAILURE(icuErr))
 821          {
 822              if (string != buffer)
 823                  free(string);
 824              CFRelease(working);
 825              return NULL;
 826          }
 827          if (stringLen <= 0)
 828              CFCharacterSetAddCharactersInRange(working, CFRangeMake(start, end-start+1));
 829          else
 830          {
 831              CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, (UniChar *)string, stringLen, kCFAllocatorNull);
 832              CFCharacterSetAddCharactersInString(working, cfString);
 833              CFRelease(cfString);
 834          }
 835          if (string != buffer)
 836              free(string);
 837      }
 838      
 839      CFCharacterSetRef   result = CFCharacterSetCreateCopy(kCFAllocatorSystemDefault, working);
 840      CFRelease(working);
 841      return result;
 842  }
 843  #endif
 844  
 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);
 852  	ulocdata_close(uld);
 853          if (U_FAILURE(icuStatus))
 854              return false;
 855          if (icuStatus == U_USING_DEFAULT_WARNING)   // If default locale used, force to empty set
 856              uset_clear(set);
 857          *cf = (CFTypeRef) _CFCreateCharacterSetFromUSet(set);
 858          uset_close(set);
 859          return (*cf != NULL);
 860      }
 861  #endif
 862      return false;
 863  }
 864  
 865  static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context, const char *keyword)
 866  {
 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))
 870      {
 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))
 874          {
 875              *cf = (CFTypeRef) CFStringCreateWithCString(kCFAllocatorSystemDefault, value, kCFStringEncodingASCII);
 876              return true;
 877          }
 878      }
 879  #endif
 880      *cf = NULL;
 881      return false;
 882  }
 883  
 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);
 890  	int32_t len;
 891  	const char *value = uenum_next(en, &len, &icuStatus);
 892  	if (U_SUCCESS(icuStatus)) {
 893              *cf = (CFTypeRef) CFStringCreateWithCString(kCFAllocatorSystemDefault, value, kCFStringEncodingASCII);
 894  	    uenum_close(en);
 895              return true;
 896          }
 897  	uenum_close(en);
 898      }
 899  #endif
 900      *cf = NULL;
 901      return false;
 902  }
 903  
 904  static bool __CFLocaleCopyCalendarID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
 905      bool succeeded = __CFLocaleCopyICUKeyword(locale, user, cf, context, kCalendarKeyword);
 906      if (!succeeded) {
 907  	succeeded = __CFLocaleCopyICUCalendarID(locale, user, cf, context, kCalendarKeyword);
 908      }
 909      if (succeeded) {
 910  	if (CFEqual(*cf, kCFCalendarIdentifierGregorian)) {
 911  	    CFRelease(*cf);
 912  	    *cf = CFRetain(kCFCalendarIdentifierGregorian);
 913  	} else if (CFEqual(*cf, kCFCalendarIdentifierBuddhist)) {
 914  	    CFRelease(*cf);
 915  	    *cf = CFRetain(kCFCalendarIdentifierBuddhist);
 916  	} else if (CFEqual(*cf, kCFCalendarIdentifierJapanese)) {
 917  	    CFRelease(*cf);
 918  	    *cf = CFRetain(kCFCalendarIdentifierJapanese);
 919  	} else if (CFEqual(*cf, kCFCalendarIdentifierIslamic)) {
 920  	    CFRelease(*cf);
 921  	    *cf = CFRetain(kCFCalendarIdentifierIslamic);
 922  	} else if (CFEqual(*cf, kCFCalendarIdentifierIslamicCivil)) {
 923  	    CFRelease(*cf);
 924  	    *cf = CFRetain(kCFCalendarIdentifierIslamicCivil);
 925  	} else if (CFEqual(*cf, kCFCalendarIdentifierHebrew)) {
 926  	    CFRelease(*cf);
 927  	    *cf = CFRetain(kCFCalendarIdentifierHebrew);
 928  	} else if (CFEqual(*cf, kCFCalendarIdentifierChinese)) {
 929  	    CFRelease(*cf);
 930  	    *cf = CFRetain(kCFCalendarIdentifierChinese);
 931  	} else if (CFEqual(*cf, kCFCalendarIdentifierRepublicOfChina)) {
 932  	    CFRelease(*cf);
 933  	    *cf = CFRetain(kCFCalendarIdentifierRepublicOfChina);
 934  	} else if (CFEqual(*cf, kCFCalendarIdentifierPersian)) {
 935  	    CFRelease(*cf);
 936  	    *cf = CFRetain(kCFCalendarIdentifierPersian);
 937  	} else if (CFEqual(*cf, kCFCalendarIdentifierIndian)) {
 938  	    CFRelease(*cf);
 939  	    *cf = CFRetain(kCFCalendarIdentifierIndian);
 940  	} else if (CFEqual(*cf, kCFCalendarIdentifierISO8601)) {
 941  	    CFRelease(*cf);
 942  	    *cf = CFRetain(kCFCalendarIdentifierISO8601);
 943  	} else if (CFEqual(*cf, kCFCalendarIdentifierCoptic)) {
 944  	    CFRelease(*cf);
 945  	    *cf = CFRetain(kCFCalendarIdentifierCoptic);
 946  	} else if (CFEqual(*cf, kCFCalendarIdentifierEthiopicAmeteMihret)) {
 947  	    CFRelease(*cf);
 948  	    *cf = CFRetain(kCFCalendarIdentifierEthiopicAmeteMihret);
 949  	} else if (CFEqual(*cf, kCFCalendarIdentifierEthiopicAmeteAlem)) {
 950  	    CFRelease(*cf);
 951  	    *cf = CFRetain(kCFCalendarIdentifierEthiopicAmeteAlem);
 952          } else if (CFEqual(*cf, kCFCalendarIdentifierIslamicTabular)) {
 953              CFRelease(*cf);
 954              *cf = CFRetain(kCFCalendarIdentifierIslamicTabular);
 955          } else if (CFEqual(*cf, kCFCalendarIdentifierIslamicUmmAlQura)) {
 956              CFRelease(*cf);
 957              *cf = CFRetain(kCFCalendarIdentifierIslamicUmmAlQura);
 958          } else {
 959  	    CFRelease(*cf);
 960  	    *cf = NULL;
 961  	    return false;
 962  	}
 963      } else {
 964  	*cf = CFRetain(kCFCalendarIdentifierGregorian);
 965      }
 966      return true;
 967  }
 968  
 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);
 978          }
 979          if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
 980              CFIndex wkdy;
 981              if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &wkdy)) {
 982                  CFCalendarSetFirstWeekday(calendar, wkdy);
 983              }
 984          }
 985          metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleMinDaysInFirstWeek")) : NULL;
 986          if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
 987              metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, *cf);
 988          }
 989          if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
 990              CFIndex mwd;
 991              if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &mwd)) {
 992                  CFCalendarSetMinimumDaysInFirstWeek(calendar, mwd);
 993              }
 994          }
 995  	CFRelease(*cf);
 996  	*cf = calendar;
 997  	return true;
 998      }
 999  #endif
1000      return false;
1001  }
1002  
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;
1014      } else {
1015  	return false;
1016      }
1017  
1018      char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
1019      if (!CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII)) {
1020  	return false;
1021      }
1022  
1023      UChar buffer[130];
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) {
1029          return false;
1030      }
1031  
1032      *cf = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)buffer, len);
1033      return (*cf != NULL);
1034  #else
1035      if (context == kCFLocaleQuotationBeginDelimiterKey || context == kCFLocaleQuotationEndDelimiterKey || context == kCFLocaleAlternateQuotationBeginDelimiterKey || context == kCFLocaleAlternateQuotationEndDelimiterKey) {
1036  	*cf = CFRetain(CFSTR("\""));
1037          return true;
1038      } else {
1039          return false;
1040      }
1041  #endif
1042  }
1043  
1044  static bool __CFLocaleCopyCollationID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
1045      return __CFLocaleCopyICUKeyword(locale, user, cf, context, kCollationKeyword);
1046  }
1047  
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"));
1052  	if (pref) {
1053  	    // Canonicalize pref string in case it's not in the canonical format.
1054  	    canonLocaleCFStr = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault, pref);
1055  	} else {
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);
1062  		    }
1063  		}
1064  	    }
1065  	}
1066      }
1067      if (!canonLocaleCFStr) {
1068  	canonLocaleCFStr = CFLocaleGetIdentifier(locale);
1069  	CFRetain(canonLocaleCFStr);
1070      }
1071      *cf = canonLocaleCFStr;
1072      return canonLocaleCFStr ? true : false;
1073  }
1074  
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
1078      bool done = false;
1079  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1080      if (user) {
1081  	CFTypeRef pref = CFDictionaryGetValue(locale->_prefs, CFSTR("AppleMetricUnits"));
1082  	if (pref) {
1083  	    us = (kCFBooleanFalse == pref);
1084  	    done = true;
1085  	} else {
1086  	    pref = CFDictionaryGetValue(locale->_prefs, CFSTR("AppleMeasurementUnits"));
1087  	    if (pref) {
1088  		us = CFEqual(pref, CFSTR("Inches"));
1089  		done = true;
1090  	    }
1091  	}
1092      }
1093  #endif
1094      if (!done) {
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);
1102                  done = true;
1103              }
1104          }
1105      }
1106      if (!done)
1107          us = false;
1108      *cf = us ? CFRetain(kCFBooleanFalse) : CFRetain(kCFBooleanTrue);
1109      return true;
1110  #else
1111      *cf = CFRetain(kCFBooleanFalse);
1112      return true;
1113  #endif
1114  }
1115  
1116  static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
1117      if (__CFLocaleCopyUsesMetric(locale, user, cf, context)) {
1118  	bool us = (*cf == kCFBooleanFalse);
1119  	CFRelease(*cf);
1120  	*cf = us ? CFRetain(CFSTR("U.S.")) : CFRetain(CFSTR("Metric"));
1121  	return true;
1122      }
1123      return false;
1124  }
1125  
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);
1132  #endif
1133      if (str) {
1134  	*cf = str;
1135  	return true;
1136      }
1137      return false;
1138  }
1139  
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);
1148  #endif
1149      if (str) {
1150  	*cf = str;
1151  	return true;
1152      }
1153      return false;
1154  }
1155  
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 *);
1158  
1159  static bool __CFLocaleICUName(const char *locale, const char *valLocale, CFStringRef *out, __CFICUFunction icu) {
1160      UErrorCode icuStatus = U_ZERO_ERROR;
1161      int32_t size;
1162      UChar name[kMaxICUNameSize];
1163  
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);
1168      }
1169      return false;
1170  }
1171  
1172  static bool __CFLocaleICUKeywordValueName(const char *locale, const char *value, const char *keyword, CFStringRef *out) {
1173      UErrorCode icuStatus = U_ZERO_ERROR;
1174      int32_t size = 0;
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);
1187          }
1188      }
1189      return false;
1190  }
1191  
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
1195          return false;
1196      UChar curr[4];
1197      UBool isChoice = FALSE;
1198      int32_t size = 0;
1199      UErrorCode icuStatus = U_ZERO_ERROR;
1200      u_charsToUChars(value, curr, valLen);
1201      curr[valLen] = '\0';
1202      const UChar *name;
1203      name = ucurr_getName(curr, locale, style, &isChoice, &size, &icuStatus);
1204      if (U_FAILURE(icuStatus) || icuStatus == U_USING_DEFAULT_WARNING)
1205          return false;
1206      UChar result[kMaxICUNameSize];
1207      if (isChoice)
1208      {
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))
1218              return false;
1219          name = result;
1220          
1221      }
1222      *out = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)name, size);
1223      return (*out != NULL);
1224  }
1225  #endif
1226  
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;
1230      int32_t size;
1231      UChar name[kMaxICUNameSize];
1232      
1233      // First, try to get the full locale.
1234      size = uloc_getDisplayName(value, locale, name, kMaxICUNameSize, &icuStatus);
1235      if (U_FAILURE(icuStatus) || size <= 0)
1236          return false;
1237  
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;
1244          int32_t localSize;
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)
1248              return false;
1249      }
1250  
1251      // This locale is OK, so use the result.
1252      *out = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)name, size);
1253      return (*out != NULL);
1254  #else
1255      *out = CFRetain(CFSTR("(none)"));
1256      return true;
1257  #endif
1258  }
1259  
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);
1263  #else
1264      *out = CFRetain(CFSTR("(none)"));
1265      return true;
1266  #endif
1267  }
1268  
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);
1277      }
1278      return false;
1279  #else
1280      *out = CFRetain(CFSTR("(none)"));
1281      return true;
1282  #endif
1283  }
1284  
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);
1294      }
1295      return false;
1296  #else
1297      *out = CFRetain(CFSTR("(none)"));
1298      return true;
1299  #endif
1300  }
1301  
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);
1310      }
1311      return false;
1312  #else
1313      *out = CFRetain(CFSTR("(none)"));
1314      return true;
1315  #endif
1316  }
1317  
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);
1321  #else
1322      *out = CFRetain(CFSTR("(none)"));
1323      return true;
1324  #endif
1325  }
1326  
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);
1330  #else
1331      *out = CFRetain(CFSTR("(none)"));
1332      return true;
1333  #endif
1334  }
1335  
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);
1339  #else
1340      *out = CFRetain(CFSTR("(none)"));
1341      return true;
1342  #endif
1343  }
1344  
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);
1348  #else
1349      *out = CFRetain(CFSTR("(none)"));
1350      return true;
1351  #endif
1352  }
1353  
1354  static bool __CFLocaleNoName(const char *locale, const char *value, CFStringRef *out) {
1355      return false;
1356  }
1357  
1358  #undef kMaxICUNameSize
1359