1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h"
  27 #include <CoreFoundation/CoreFoundation.h>
  28 #include <stdio.h>
  29 
  30 #define BUFLEN 256
  31 
  32 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle);
  33 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle);
  34 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count);
  35 static jstring getNumberSymbolString(JNIEnv *env, jstring jdefault, CFStringRef type);
  36 static jchar getNumberSymbolChar(jchar jdefault, CFStringRef type);
  37 
  38 // from java_props_macosx.c
  39 extern char * getMacOSXLocale(int cat);
  40 extern char * getPosixLocale(int cat);
  41 
  42 /*
  43  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
  44  * Method:    getDefaultLocale
  45  * Signature: (I)Ljava/lang/String;
  46  */
  47 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDefaultLocale
  48   (JNIEnv *env, jclass cls, jint cat) {
  49     char * localeString = NULL;
  50     int posixCat;
  51     jstring ret = NULL;
  52 
  53     switch (cat) {
  54         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_DISPLAY:
  55             posixCat = LC_MESSAGES;
  56             break;
  57         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_FORMAT:
  58         default:
  59             posixCat = LC_CTYPE;
  60             break;
  61     }
  62 
  63     localeString = getMacOSXLocale(posixCat);
  64     if (localeString == NULL) {
  65         localeString = getPosixLocale(posixCat);
  66     }
  67     ret = (*env)->NewStringUTF(env, localeString);
  68     free(localeString);
  69 
  70     return ret;
  71 }
  72 
  73 /*
  74  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
  75  * Method:    getDateTimePatternNative
  76  * Signature: (IILjava/lang/String;)Ljava/lang/String;
  77  */
  78 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePatternNative
  79   (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) {
  80     jstring ret = NULL;
  81     CFLocaleRef cflocale = CFLocaleCopyCurrent();
  82 
  83     if (cflocale != NULL) {
  84         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
  85                                                   cflocale,
  86                                                   convertDateFormatterStyle(dateStyle),
  87                                                   convertDateFormatterStyle(timeStyle));
  88         if (df != NULL) {
  89             char buf[BUFLEN];
  90             CFStringRef formatStr = CFDateFormatterGetFormat(df);
  91             CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8);
  92             ret = (*env)->NewStringUTF(env, buf);
  93             CFRelease(df);
  94         }
  95         CFRelease(cflocale);
  96     }
  97 
  98     return ret;
  99 }
 100 
 101 /*
 102  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 103  * Method:    getCalendarID
 104  * Signature: (Ljava/lang/String;)Ljava/lang/String;
 105  */
 106 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID
 107   (JNIEnv *env, jclass cls, jstring jlangtag) {
 108     jstring ret = NULL;
 109     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 110 
 111     if (cflocale != NULL) {
 112         char buf[BUFLEN];
 113         CFTypeRef calid = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier);
 114         CFStringGetCString((CFStringRef)calid, buf, BUFLEN, kCFStringEncodingUTF8);
 115         ret = (*env)->NewStringUTF(env, buf);
 116         CFRelease(cflocale);
 117     }
 118 
 119     return ret;
 120 }
 121 
 122 /*
 123  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 124  * Method:    getAmPmStrings
 125  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 126  */
 127 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings
 128   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) {
 129     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 130     if (cflocale != NULL) {
 131         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 132                                                   cflocale,
 133                                                   kCFDateFormatterFullStyle,
 134                                                   kCFDateFormatterFullStyle);
 135         if (df != NULL) {
 136             char buf[BUFLEN];
 137             CFStringRef amStr = CFDateFormatterCopyProperty(df, kCFDateFormatterAMSymbol);
 138             if (amStr != NULL) {
 139                 CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8);
 140                 CFRelease(amStr);
 141                 (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewStringUTF(env, buf));
 142             }
 143             CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol);
 144             if (pmStr != NULL) {
 145                 CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8);
 146                 CFRelease(pmStr);
 147                 (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewStringUTF(env, buf));
 148             }
 149             CFRelease(df);
 150         }
 151         CFRelease(cflocale);
 152     }
 153 
 154     return ampms;
 155 }
 156 
 157 /*
 158  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 159  * Method:    getEras
 160  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 161  */
 162 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras
 163   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) {
 164     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 165     if (cflocale != NULL) {
 166         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 167                                                   cflocale,
 168                                                   kCFDateFormatterFullStyle,
 169                                                   kCFDateFormatterFullStyle);
 170         if (df != NULL) {
 171             CFArrayRef cferas = CFDateFormatterCopyProperty(df, kCFDateFormatterEraSymbols);
 172             if (cferas != NULL) {
 173                 copyArrayElements(env, cferas, eras, 0, 0, CFArrayGetCount(cferas));
 174                 CFRelease(cferas);
 175             }
 176             CFRelease(df);
 177         }
 178         CFRelease(cflocale);
 179     }
 180 
 181     return eras;
 182 }
 183 
 184 /*
 185  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 186  * Method:    getMonths
 187  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 188  */
 189 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths
 190   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) {
 191     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 192     if (cflocale != NULL) {
 193         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 194                                                   cflocale,
 195                                                   kCFDateFormatterFullStyle,
 196                                                   kCFDateFormatterFullStyle);
 197         if (df != NULL) {
 198             CFArrayRef cfmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterMonthSymbols);
 199             if (cfmonths != NULL) {
 200                 copyArrayElements(env, cfmonths, months, 0, 0, CFArrayGetCount(cfmonths));
 201                 CFRelease(cfmonths);
 202             }
 203             CFRelease(df);
 204         }
 205         CFRelease(cflocale);
 206     }
 207 
 208     return months;
 209 }
 210 
 211 /*
 212  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 213  * Method:    getShortMonths
 214  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 215  */
 216 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths
 217   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) {
 218     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 219     if (cflocale != NULL) {
 220         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 221                                                   cflocale,
 222                                                   kCFDateFormatterFullStyle,
 223                                                   kCFDateFormatterFullStyle);
 224         if (df != NULL) {
 225             CFArrayRef cfsmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterShortMonthSymbols);
 226             if (cfsmonths != NULL) {
 227                 copyArrayElements(env, cfsmonths, smonths, 0, 0, CFArrayGetCount(cfsmonths));
 228                 CFRelease(cfsmonths);
 229             }
 230             CFRelease(df);
 231         }
 232         CFRelease(cflocale);
 233     }
 234 
 235     return smonths;
 236 }
 237 
 238 /*
 239  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 240  * Method:    getWeekdays
 241  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 242  */
 243 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays
 244   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) {
 245     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 246     if (cflocale != NULL) {
 247         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 248                                                   cflocale,
 249                                                   kCFDateFormatterFullStyle,
 250                                                   kCFDateFormatterFullStyle);
 251         if (df != NULL) {
 252             CFArrayRef cfwdays = CFDateFormatterCopyProperty(df, kCFDateFormatterWeekdaySymbols);
 253             if (cfwdays != NULL) {
 254                 copyArrayElements(env, cfwdays, wdays, 0, 1, CFArrayGetCount(cfwdays));
 255                 CFRelease(cfwdays);
 256             }
 257             CFRelease(df);
 258         }
 259         CFRelease(cflocale);
 260     }
 261 
 262     return wdays;
 263 }
 264 
 265 /*
 266  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 267  * Method:    getShortWeekdays
 268  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 269  */
 270 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays
 271   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) {
 272     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 273     if (cflocale != NULL) {
 274         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 275                                                   cflocale,
 276                                                   kCFDateFormatterFullStyle,
 277                                                   kCFDateFormatterFullStyle);
 278         if (df != NULL) {
 279             CFArrayRef cfswdays = CFDateFormatterCopyProperty(df, kCFDateFormatterShortWeekdaySymbols);
 280             if (cfswdays != NULL) {
 281                 copyArrayElements(env, cfswdays, swdays, 0, 1, CFArrayGetCount(cfswdays));
 282                 CFRelease(cfswdays);
 283             }
 284             CFRelease(df);
 285         }
 286         CFRelease(cflocale);
 287     }
 288 
 289     return swdays;
 290 }
 291 
 292 /*
 293  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 294  * Method:    getNumberPatternNative
 295  * Signature: (ILjava/lang/String;)Ljava/lang/String;
 296  */
 297 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPatternNative
 298   (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) {
 299     jstring ret = NULL;
 300     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 301     if (cflocale != NULL) {
 302         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 303                                                   cflocale,
 304                                                   convertNumberFormatterStyle(numberStyle));
 305         if (nf != NULL) {
 306             char buf[BUFLEN];
 307             CFStringRef formatStr = CFNumberFormatterGetFormat(nf);
 308             CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8);
 309             ret = (*env)->NewStringUTF(env, buf);
 310             CFRelease(nf);
 311         }
 312         CFRelease(cflocale);
 313     }
 314 
 315     return ret;
 316 }
 317 
 318 /*
 319  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 320  * Method:    getCurrencySymbol
 321  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 322  */
 323 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol
 324   (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) {
 325     return getNumberSymbolString(env, currencySymbol, kCFNumberFormatterCurrencySymbol);
 326 }
 327 
 328 /*
 329  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 330  * Method:    getDecimalSeparator
 331  * Signature: (Ljava/lang/String;C)C
 332  */
 333 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator
 334   (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) {
 335     return getNumberSymbolChar(decimalSeparator, kCFNumberFormatterDecimalSeparator);
 336 }
 337 
 338 /*
 339  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 340  * Method:    getGroupingSeparator
 341  * Signature: (Ljava/lang/String;C)C
 342  */
 343 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator
 344   (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) {
 345     return getNumberSymbolChar(groupingSeparator, kCFNumberFormatterGroupingSeparator);
 346 }
 347 
 348 /*
 349  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 350  * Method:    getInfinity
 351  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 352  */
 353 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity
 354   (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) {
 355     return getNumberSymbolString(env, infinity, kCFNumberFormatterInfinitySymbol);
 356 }
 357 
 358 /*
 359  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 360  * Method:    getInternationalCurrencySymbol
 361  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 362  */
 363 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol
 364   (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) {
 365     return getNumberSymbolString(env, internationalCurrencySymbol, kCFNumberFormatterInternationalCurrencySymbol);
 366 }
 367 
 368 /*
 369  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 370  * Method:    getMinusSign
 371  * Signature: (Ljava/lang/String;C)C
 372  */
 373 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign
 374   (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) {
 375     return getNumberSymbolChar(minusSign, kCFNumberFormatterMinusSign);
 376 }
 377 
 378 /*
 379  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 380  * Method:    getMonetaryDecimalSeparator
 381  * Signature: (Ljava/lang/String;C)C
 382  */
 383 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator
 384   (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) {
 385     return getNumberSymbolChar(monetaryDecimalSeparator, kCFNumberFormatterCurrencyDecimalSeparator);
 386 }
 387 
 388 /*
 389  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 390  * Method:    getNaN
 391  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 392  */
 393 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN
 394   (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) {
 395     return getNumberSymbolString(env, nan, kCFNumberFormatterNaNSymbol);
 396 }
 397 
 398 /*
 399  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 400  * Method:    getPercent
 401  * Signature: (Ljava/lang/String;C)C
 402  */
 403 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent
 404   (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) {
 405     return getNumberSymbolChar(percent, kCFNumberFormatterPercentSymbol);
 406 }
 407 
 408 /*
 409  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 410  * Method:    getPerMill
 411  * Signature: (Ljava/lang/String;C)C
 412  */
 413 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill
 414   (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) {
 415     return getNumberSymbolChar(perMill, kCFNumberFormatterPerMillSymbol);
 416 }
 417 
 418 /*
 419  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 420  * Method:    getZeroDigit
 421  * Signature: (Ljava/lang/String;C)C
 422  */
 423 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit
 424   (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) {
 425     return getNumberSymbolChar(zeroDigit, kCFNumberFormatterZeroSymbol);
 426 }
 427 
 428 /*
 429  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 430  * Method:    getExponentSeparator
 431  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 432  */
 433 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getExponentSeparator
 434   (JNIEnv *env, jclass cls, jstring jlangtag, jstring exponent) {
 435     return getNumberSymbolString(env, exponent, kCFNumberFormatterExponentSymbol);
 436 }
 437 
 438 /*
 439  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 440  * Method:    getCalendarInt
 441  * Signature: (Ljava/lang/String;I)I
 442  */
 443 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarInt
 444   (JNIEnv *env, jclass cls, jstring jlangtag, jint type) {
 445     jint ret = 0;
 446     CFCalendarRef cfcal = CFCalendarCopyCurrent();
 447 
 448     if (cfcal != NULL) {
 449         switch (type) {
 450             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK:
 451                 ret = CFCalendarGetFirstWeekday(cfcal);
 452                 break;
 453             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_MINIMALDAYSINFIRSTWEEK:
 454                 ret = CFCalendarGetMinimumDaysInFirstWeek(cfcal);
 455                 break;
 456             default:
 457                 ret = 0;
 458         }
 459 
 460         CFRelease(cfcal);
 461     }
 462 
 463     return ret;
 464 }
 465 
 466 /*
 467  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 468  * Method:    getDisplayString
 469  * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;
 470  */
 471 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDisplayString
 472   (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring value) {
 473     jstring ret = NULL;
 474 
 475     const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0);
 476     if (clangtag != NULL) {
 477         const char *cvalue = (*env)->GetStringUTFChars(env, value, 0);
 478         if (cvalue != NULL) {
 479             CFStringRef cflangtag =
 480                 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8);
 481             if (cflangtag != NULL) {
 482                 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag);
 483                 if (cflocale != NULL) {
 484                     CFStringRef cfvalue =
 485                         CFStringCreateWithCString(kCFAllocatorDefault, cvalue, kCFStringEncodingUTF8);
 486                     if (cfvalue != NULL) {
 487                         CFStringRef str = NULL;
 488                         switch (type) {
 489                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_LANGUAGE:
 490                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleLanguageCode, cfvalue);
 491                                 break;
 492                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_SCRIPT:
 493                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleScriptCode, cfvalue);
 494                                 break;
 495                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION:
 496                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCountryCode, cfvalue);
 497                                 break;
 498                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_VARIANT:
 499                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleVariantCode, cfvalue);
 500                                 break;
 501                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_CODE:
 502                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencyCode, cfvalue);
 503                                 break;
 504                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_SYMBOL:
 505                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencySymbol, cfvalue);
 506                                 break;
 507                         }
 508                         if (str != NULL) {
 509                             char buf[BUFLEN];
 510                             CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 511                             CFRelease(str);
 512                             ret = (*env)->NewStringUTF(env, buf);
 513                         }
 514                         CFRelease(cfvalue);
 515                     }
 516                     CFRelease(cflocale);
 517                 }
 518                 CFRelease(cflangtag);
 519             }
 520             (*env)->ReleaseStringUTFChars(env, value, cvalue);
 521         }
 522         (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag);
 523     }
 524 
 525     return ret;
 526 }
 527 
 528 /*
 529  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 530  * Method:    getTimeZoneDisplayString
 531  * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;
 532  */
 533 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getTimeZoneDisplayString
 534   (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring tzid) {
 535     jstring ret = NULL;
 536 
 537     const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0);
 538     if (clangtag != NULL) {
 539         const char *ctzid = (*env)->GetStringUTFChars(env, tzid, 0);
 540         if (ctzid != NULL) {
 541             CFStringRef cflangtag =
 542                 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8);
 543             if (cflangtag != NULL) {
 544                 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag);
 545                 if (cflocale != NULL) {
 546                     CFStringRef cftzid =
 547                         CFStringCreateWithCString(kCFAllocatorDefault, ctzid, kCFStringEncodingUTF8);
 548                     if (cftzid != NULL) {
 549                         CFTimeZoneRef cftz = CFTimeZoneCreateWithName(kCFAllocatorDefault, cftzid, false);
 550                         if (cftz != NULL) {
 551                             CFStringRef str = NULL;
 552                             switch (type) {
 553                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_STANDARD:
 554                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortStandard, cflocale);
 555                                     break;
 556                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_DST:
 557                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortDaylightSaving, cflocale);
 558                                     break;
 559                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_STANDARD:
 560                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleStandard, cflocale);
 561                                     break;
 562                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_DST:
 563                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleDaylightSaving, cflocale);
 564                                     break;
 565                             }
 566                             if (str != NULL) {
 567                                 char buf[BUFLEN];
 568                                 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 569                                 CFRelease(str);
 570                                 ret = (*env)->NewStringUTF(env, buf);
 571                             }
 572                             CFRelease(cftz);
 573                         }
 574                         CFRelease(cftzid);
 575                     }
 576                     CFRelease(cflocale);
 577                 }
 578                 CFRelease(cflangtag);
 579             }
 580             (*env)->ReleaseStringUTFChars(env, tzid, ctzid);
 581         }
 582         (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag);
 583     }
 584 
 585     return ret;
 586 }
 587 
 588 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle) {
 589     switch (javaStyle) {
 590         case 0: // FULL
 591             return kCFDateFormatterFullStyle;
 592         case 1: // LONG
 593             return kCFDateFormatterLongStyle;
 594         case 2: // MEDIUM
 595             return kCFDateFormatterMediumStyle;
 596         case 3: // LONG
 597             return kCFDateFormatterShortStyle;
 598         case -1: // No style
 599         default:
 600             return kCFDateFormatterNoStyle;
 601     }
 602 }
 603 
 604 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle) {
 605     switch (javaStyle) {
 606         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY:
 607             return kCFNumberFormatterCurrencyStyle;
 608         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER:
 609             return kCFNumberFormatterDecimalStyle;
 610         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER:
 611             return kCFNumberFormatterDecimalStyle;
 612         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT:
 613             return kCFNumberFormatterPercentStyle;
 614         default:
 615             return kCFNumberFormatterNoStyle;
 616     }
 617 }
 618 
 619 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) {
 620     char buf[BUFLEN];
 621 
 622     for (; count > 0; sindex++, dindex++, count--) {
 623         CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8);
 624         (*env)->SetObjectArrayElement(env, jarray, dindex, (*env)->NewStringUTF(env, buf));
 625     }
 626 }
 627 
 628 static jstring getNumberSymbolString(JNIEnv *env, jstring jdefault, CFStringRef type) {
 629     char buf[BUFLEN];
 630     jstring ret = jdefault;
 631     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 632 
 633     if (cflocale != NULL) {
 634         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 635                                                   cflocale,
 636                                                   kCFNumberFormatterDecimalStyle);
 637         if (nf != NULL) {
 638             CFStringRef str = CFNumberFormatterCopyProperty(nf, type);
 639             if (str != NULL) {
 640                 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 641                 CFRelease(str);
 642                 ret = (*env)->NewStringUTF(env, buf);
 643             }
 644 
 645             CFRelease(nf);
 646         }
 647 
 648         CFRelease(cflocale);
 649     }
 650 
 651     return ret;
 652 }
 653 
 654 static jchar getNumberSymbolChar(jchar jdefault, CFStringRef type) {
 655     char buf[BUFLEN];
 656     jchar ret = jdefault;
 657     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 658 
 659     if (cflocale != NULL) {
 660         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 661                                                   cflocale,
 662                                                   kCFNumberFormatterDecimalStyle);
 663         if (nf != NULL) {
 664             CFStringRef str = CFNumberFormatterCopyProperty(nf, type);
 665             if (str != NULL) {
 666                 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 667                 CFRelease(str);
 668                 ret = buf[0];
 669             }
 670 
 671             CFRelease(nf);
 672         }
 673 
 674         CFRelease(cflocale);
 675     }
 676 
 677     return ret;
 678 }