1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "JNIHelp.h" 18#include "AndroidSystemNatives.h" 19#include "unicode/numfmt.h" 20#include "unicode/locid.h" 21#include "unicode/ucal.h" 22#include "unicode/gregocal.h" 23#include "unicode/ucurr.h" 24#include "unicode/calendar.h" 25#include "unicode/datefmt.h" 26#include "unicode/dtfmtsym.h" 27#include "unicode/decimfmt.h" 28#include "unicode/dcfmtsym.h" 29#include "unicode/uclean.h" 30#include "unicode/smpdtfmt.h" 31#include "unicode/strenum.h" 32#include "unicode/ustring.h" 33#include "unicode/timezone.h" 34#include "ErrorCode.h" 35#include <cutils/log.h> 36#include <stdlib.h> 37#include <string.h> 38#include <time.h> 39#include <sys/time.h> 40 41jclass string_class; 42 43static UBool icuError(JNIEnv *env, UErrorCode errorcode) 44{ 45 const char *emsg = u_errorName(errorcode); 46 jclass exception; 47 48 if (U_FAILURE(errorcode)) { 49 switch (errorcode) { 50 case U_ILLEGAL_ARGUMENT_ERROR : 51 exception = env->FindClass("java/lang/IllegalArgumentException"); 52 break; 53 case U_INDEX_OUTOFBOUNDS_ERROR : 54 case U_BUFFER_OVERFLOW_ERROR : 55 exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException"); 56 break; 57 case U_UNSUPPORTED_ERROR : 58 exception = env->FindClass("java/lang/UnsupportedOperationException"); 59 break; 60 default : 61 exception = env->FindClass("java/lang/RuntimeException"); 62 } 63 64 return (env->ThrowNew(exception, emsg) != 0); 65 } 66 return 0; 67} 68 69static Locale getLocale(JNIEnv *env, jstring locale) { 70 const char *name = env->GetStringUTFChars(locale, NULL); 71 Locale result = Locale::createFromName(name); 72 env->ReleaseStringUTFChars(locale, name); 73 return result; 74} 75 76static jstring getJStringFromUnicodeString(JNIEnv *env, UnicodeString string) { 77 78 UErrorCode status = U_ZERO_ERROR; 79 80 int stringLength = string.length(); 81 jchar *res = (jchar *) malloc(sizeof(jchar) * (stringLength + 1)); 82 string.extract(res, stringLength+1, status); 83 if(U_FAILURE(status)) { 84 free(res); 85 LOGI("Error getting string for getJStringFromUnicodeString"); 86 status = U_ZERO_ERROR; 87 return NULL; 88 } 89 jstring result = env->NewString(res, stringLength); 90 free(res); 91 return result; 92} 93 94static void addObject(JNIEnv *env, jobjectArray result, const char *keyStr, jobject elem, int index) { 95 jclass objArray_class = env->FindClass("java/lang/Object"); 96 jobjectArray element = env->NewObjectArray(2, objArray_class, NULL); 97 jstring key = env->NewStringUTF(keyStr); 98 env->SetObjectArrayElement(element, 0, key); 99 env->SetObjectArrayElement(element, 1, elem); 100 env->SetObjectArrayElement(result, index, element); 101 env->DeleteLocalRef(key); 102 env->DeleteLocalRef(element); 103} 104 105static jint getFractionDigitsNative(JNIEnv* env, jclass clazz, 106 jstring currencyCode) { 107 // LOGI("ENTER getFractionDigitsNative"); 108 109 UErrorCode status = U_ZERO_ERROR; 110 111 NumberFormat *fmt = NumberFormat::createCurrencyInstance(status); 112 if(U_FAILURE(status)) { 113 return -1; 114 } 115 116 const jchar *cCode = env->GetStringChars(currencyCode, NULL); 117 fmt->setCurrency(cCode, status); 118 env->ReleaseStringChars(currencyCode, cCode); 119 if(U_FAILURE(status)) { 120 return -1; 121 } 122 123 // for CurrencyFormats the minimum and maximum fraction digits are the same. 124 int result = fmt->getMinimumFractionDigits(); 125 delete(fmt); 126 return result; 127} 128 129static jstring getCurrencyCodeNative(JNIEnv* env, jclass clazz, 130 jstring key) { 131 // LOGI("ENTER getCurrencyCodeNative"); 132 133 UErrorCode status = U_ZERO_ERROR; 134 135 UResourceBundle *supplData = ures_openDirect(NULL, "supplementalData", &status); 136 if(U_FAILURE(status)) { 137 return NULL; 138 } 139 140 UResourceBundle *currencyMap = ures_getByKey(supplData, "CurrencyMap", NULL, &status); 141 if(U_FAILURE(status)) { 142 ures_close(supplData); 143 return NULL; 144 } 145 146 const char *keyChars = env->GetStringUTFChars(key, NULL); 147 UResourceBundle *currency = ures_getByKey(currencyMap, keyChars, NULL, &status); 148 env->ReleaseStringUTFChars(key, keyChars); 149 if(U_FAILURE(status)) { 150 ures_close(currencyMap); 151 ures_close(supplData); 152 return NULL; 153 } 154 155 UResourceBundle *currencyElem = ures_getByIndex(currency, 0, NULL, &status); 156 if(U_FAILURE(status)) { 157 ures_close(currency); 158 ures_close(currencyMap); 159 ures_close(supplData); 160 return env->NewStringUTF("None"); 161 } 162 163 // check if there is a to date. If there is, the currency isn't used anymore. 164 UResourceBundle *currencyTo = ures_getByKey(currencyElem, "to", NULL, &status); 165 if(!U_FAILURE(status)) { 166 // return and let the ResourceBundle throw an exception 167 ures_close(currencyElem); 168 ures_close(currency); 169 ures_close(currencyMap); 170 ures_close(supplData); 171 return NULL; 172 } 173 status = U_ZERO_ERROR; 174 ures_close(currencyTo); 175 176 UResourceBundle *currencyId = ures_getByKey(currencyElem, "id", NULL, &status); 177 if(U_FAILURE(status)) { 178 // No id defined for this country 179 ures_close(currencyElem); 180 ures_close(currency); 181 ures_close(currencyMap); 182 ures_close(supplData); 183 return env->NewStringUTF("None"); 184 } 185 186 int length; 187 const jchar *id = ures_getString(currencyId, &length, &status); 188 if(U_FAILURE(status)) { 189 ures_close(currencyId); 190 ures_close(currencyElem); 191 ures_close(currency); 192 ures_close(currencyMap); 193 ures_close(supplData); 194 return env->NewStringUTF("None"); 195 } 196 197 ures_close(currencyId); 198 ures_close(currencyElem); 199 ures_close(currency); 200 ures_close(currencyMap); 201 ures_close(supplData); 202 203 if(length == 0) { 204 return env->NewStringUTF("None"); 205 } 206 return env->NewString(id, length); 207} 208 209static jstring getCurrencySymbolNative(JNIEnv* env, jclass clazz, 210 jstring locale, jstring currencyCode) { 211 // LOGI("ENTER getCurrencySymbolNative"); 212 213 UErrorCode status = U_ZERO_ERROR; 214 215 const char *locName = env->GetStringUTFChars(locale, NULL); 216 UResourceBundle *root = ures_open(NULL, locName, &status); 217 env->ReleaseStringUTFChars(locale, locName); 218 if(U_FAILURE(status)) { 219 return NULL; 220 } 221 222 UResourceBundle *rootElems = ures_getByKey(root, "Currencies", NULL, &status); 223 if(U_FAILURE(status)) { 224 ures_close(root); 225 return NULL; 226 } 227 228 const char *currName = env->GetStringUTFChars(currencyCode, NULL); 229 UResourceBundle *currencyElems = ures_getByKey(rootElems, currName, NULL, &status); 230 env->ReleaseStringUTFChars(currencyCode, currName); 231 if(U_FAILURE(status)) { 232 ures_close(rootElems); 233 ures_close(root); 234 return NULL; 235 } 236 237 int currSymbL; 238 const jchar *currSymbU = ures_getStringByIndex(currencyElems, 0, &currSymbL, &status); 239 if(U_FAILURE(status)) { 240 ures_close(currencyElems); 241 ures_close(rootElems); 242 ures_close(root); 243 return NULL; 244 } 245 246 ures_close(currencyElems); 247 ures_close(rootElems); 248 ures_close(root); 249 250 if(currSymbL == 0) { 251 return NULL; 252 } 253 return env->NewString(currSymbU, currSymbL); 254} 255 256static jstring getDisplayCountryNative(JNIEnv* env, jclass clazz, 257 jstring targetLocale, jstring locale) { 258 // LOGI("ENTER getDisplayCountryNative"); 259 260 UErrorCode status = U_ZERO_ERROR; 261 262 Locale loc = getLocale(env, locale); 263 Locale targetLoc = getLocale(env, targetLocale); 264 265 UnicodeString string; 266 targetLoc.getDisplayCountry(loc, string); 267 268 jstring result = getJStringFromUnicodeString(env, string); 269 270 return result; 271} 272 273static jstring getDisplayLanguageNative(JNIEnv* env, jclass clazz, 274 jstring targetLocale, jstring locale) { 275 // LOGI("ENTER getDisplayLanguageNative"); 276 277 Locale loc = getLocale(env, locale); 278 Locale targetLoc = getLocale(env, targetLocale); 279 280 UnicodeString string; 281 targetLoc.getDisplayLanguage(loc, string); 282 283 jstring result = getJStringFromUnicodeString(env, string); 284 285 return result; 286} 287 288static jstring getDisplayVariantNative(JNIEnv* env, jclass clazz, 289 jstring targetLocale, jstring locale) { 290 // LOGI("ENTER getDisplayVariantNative"); 291 292 Locale loc = getLocale(env, locale); 293 Locale targetLoc = getLocale(env, targetLocale); 294 295 UnicodeString string; 296 targetLoc.getDisplayVariant(loc, string); 297 298 jstring result = getJStringFromUnicodeString(env, string); 299 300 return result; 301} 302 303static jstring getISO3CountryNative(JNIEnv* env, jclass clazz, jstring locale) { 304 // LOGI("ENTER getISO3CountryNative"); 305 306 Locale loc = getLocale(env, locale); 307 308 const char *string = loc.getISO3Country(); 309 310 jstring result = env->NewStringUTF(string); 311 312 return result; 313} 314 315static jstring getISO3LanguageNative(JNIEnv* env, jclass clazz, jstring locale) { 316 // LOGI("ENTER getISO3LanguageNative"); 317 318 Locale loc = getLocale(env, locale); 319 320 const char *string = loc.getISO3Language(); 321 322 jstring result = env->NewStringUTF(string); 323 324 return result; 325} 326 327static jobjectArray getISOCountriesNative(JNIEnv* env, jclass clazz) { 328 // LOGI("ENTER getISOCountriesNative"); 329 330 const char* const* strings = Locale::getISOCountries(); 331 332 int count = 0; 333 while(strings[count] != NULL) { 334 count++; 335 } 336 337 jobjectArray result = env->NewObjectArray(count, string_class, NULL); 338 339 jstring res; 340 for(int i = 0; i < count; i++) { 341 res = env->NewStringUTF(strings[i]); 342 env->SetObjectArrayElement(result, i, res); 343 env->DeleteLocalRef(res); 344 } 345 return result; 346} 347 348static jobjectArray getISOLanguagesNative(JNIEnv* env, jclass clazz) { 349 // LOGI("ENTER getISOLanguagesNative"); 350 351 const char* const* strings = Locale::getISOLanguages(); 352 353 const char *string = strings[0]; 354 355 int count = 0; 356 while(strings[count] != NULL) { 357 count++; 358 } 359 360 jobjectArray result = env->NewObjectArray(count, string_class, NULL); 361 362 jstring res; 363 for(int i = 0; i < count; i++) { 364 res = env->NewStringUTF(strings[i]); 365 env->SetObjectArrayElement(result, i, res); 366 env->DeleteLocalRef(res); 367 } 368 return result; 369} 370 371static jobjectArray getAvailableLocalesNative(JNIEnv* env, jclass clazz) { 372 // LOGI("ENTER getAvailableLocalesNative"); 373 374 int count = uloc_countAvailable(); 375 376 jobjectArray result = env->NewObjectArray(count, string_class, NULL); 377 378 jstring res; 379 const char * string; 380 for(int i = 0; i < count; i++) { 381 string = uloc_getAvailable(i); 382 res = env->NewStringUTF(string); 383 env->SetObjectArrayElement(result, i, res); 384 env->DeleteLocalRef(res); 385 } 386 387 return result; 388} 389 390static void getTimeZonesNative(JNIEnv* env, jclass clazz, 391 jobjectArray outerArray, jstring locale) { 392 // LOGI("ENTER getTimeZonesNative"); 393 394 UErrorCode status = U_ZERO_ERROR; 395 396 jobjectArray zoneIdArray; 397 jobjectArray longStdTimeArray; 398 jobjectArray shortStdTimeArray; 399 jobjectArray longDlTimeArray; 400 jobjectArray shortDlTimeArray; 401 402 jstring content; 403 jstring strObj; 404 const jchar *res; 405 UnicodeString resU; 406 jint length; 407 const UnicodeString *zoneID; 408 DateFormat *df; 409 410 UnicodeString longPattern("zzzz",""); 411 UnicodeString shortPattern("z",""); 412 413 Locale loc = getLocale(env, locale); 414 415 SimpleDateFormat longFormat(longPattern, loc, status); 416 SimpleDateFormat shortFormat(shortPattern, loc, status); 417 418 419 zoneIdArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 0); 420 longStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 1); 421 shortStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 2); 422 longDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 3); 423 shortDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 4); 424 425 int count = env->GetArrayLength(zoneIdArray); 426 427 TimeZone* zones[count]; 428 429 // get all timezone objects 430 for(int i = 0; i < count; i++) { 431 strObj = (jstring) env->GetObjectArrayElement(zoneIdArray, i); 432 length = env->GetStringLength(strObj); 433 res = env->GetStringChars(strObj, NULL); 434 const UnicodeString zoneID((UChar *)res, length); 435 env->ReleaseStringChars(strObj, res); 436 zones[i] = TimeZone::createTimeZone(zoneID); 437 env->DeleteLocalRef(strObj); 438 } 439 440 // 15th January 2008 441 UDate date1 = 1203105600000.0; 442 // 15th July 2008 443 UDate date2 = 1218826800000.0; 444 445 for (int i = 0; i < count; i++) { 446 TimeZone *tz = zones[i]; 447 longFormat.setTimeZone(*tz); 448 shortFormat.setTimeZone(*tz); 449 450 int32_t daylightOffset; 451 int32_t rawOffset; 452 UDate standardDate; 453 UDate daylightSavingDate; 454 tz->getOffset(date1, false, rawOffset, daylightOffset, status); 455 if (daylightOffset != 0) { 456 // The Timezone is reporting that we are in daylight time 457 // for the winter date. The dates are for the wrong hemisphere, 458 // swap them. 459 standardDate = date2; 460 daylightSavingDate = date1; 461 } else { 462 standardDate = date1; 463 daylightSavingDate = date2; 464 } 465 466 UnicodeString shortDayLight; 467 UnicodeString longDayLight; 468 UnicodeString shortStandard; 469 UnicodeString longStandard; 470 471 shortFormat.format(daylightSavingDate, shortDayLight); 472 content = getJStringFromUnicodeString(env, shortDayLight); 473 env->SetObjectArrayElement(shortDlTimeArray, i, content); 474 env->DeleteLocalRef(content); 475 476 shortFormat.format(standardDate, shortStandard); 477 content = getJStringFromUnicodeString(env, shortStandard); 478 env->SetObjectArrayElement(shortStdTimeArray, i, content); 479 env->DeleteLocalRef(content); 480 481 longFormat.format (daylightSavingDate, longDayLight); 482 content = getJStringFromUnicodeString(env, longDayLight); 483 env->SetObjectArrayElement(longDlTimeArray, i, content); 484 env->DeleteLocalRef(content); 485 486 longFormat.format (standardDate, longStandard); 487 content = getJStringFromUnicodeString(env, longStandard); 488 env->SetObjectArrayElement(longStdTimeArray, i, content); 489 env->DeleteLocalRef(content); 490 delete(tz); 491 } 492} 493 494 495 496 497static jstring getDisplayTimeZoneNative(JNIEnv* env, jclass clazz, 498 jstring zoneID, jboolean isDST, jint style, jstring localeID) { 499 500 // Build TimeZone object 501 const jchar* idChars = env->GetStringChars(zoneID, NULL); 502 jint idLength = env->GetStringLength(zoneID); 503 UnicodeString idString((UChar*)idChars, idLength); 504 TimeZone* zone = TimeZone::createTimeZone(idString); 505 env->ReleaseStringChars(zoneID, idChars); 506 507 // Build Locale object (can we rely on zero termination of JNI result?) 508 const char* localeChars = env->GetStringUTFChars(localeID, NULL); 509 jint localeLength = env->GetStringLength(localeID); 510 Locale locale = Locale::createFromName(localeChars); 511 512 // Try to get the display name of the TimeZone according to the Locale 513 UnicodeString buffer; 514 zone->getDisplayName((UBool)isDST, (style == 0 ? TimeZone::SHORT : TimeZone::LONG), locale, buffer); 515 const UChar* tempChars = buffer.getBuffer(); 516 int tempLength = buffer.length(); 517 jstring result = env->NewString((jchar*)tempChars, tempLength); 518 env->ReleaseStringUTFChars(localeID, localeChars); 519 520 // Clean up everything 521 delete(zone); 522 523 return result; 524} 525 526static void getDayInitVector(JNIEnv *env, UResourceBundle *gregorian, int *values) { 527 528 UErrorCode status = U_ZERO_ERROR; 529 530 // get the First day of week and the minimal days in first week numbers 531 UResourceBundle *gregorianElems = ures_getByKey(gregorian, "DateTimeElements", NULL, &status); 532 if(U_FAILURE(status)) { 533 return; 534 } 535 536 int intVectSize; 537 const int *result; 538 result = ures_getIntVector(gregorianElems, &intVectSize, &status); 539 if(U_FAILURE(status)) { 540 ures_close(gregorianElems); 541 return; 542 } 543 544 if(intVectSize == 2) { 545 values[0] = result[0]; 546 values[1] = result[1]; 547 } 548 549 ures_close(gregorianElems); 550 551} 552 553static jobjectArray getAmPmMarkers(JNIEnv *env, UResourceBundle *gregorian) { 554 555 jobjectArray amPmMarkers; 556 jstring pmU, amU; 557 558 UErrorCode status = U_ZERO_ERROR; 559 560 UResourceBundle *gregorianElems; 561 562 gregorianElems = ures_getByKey(gregorian, "AmPmMarkers", NULL, &status); 563 if(U_FAILURE(status)) { 564 return NULL; 565 } 566 567 int lengthAm, lengthPm; 568 569 ures_resetIterator(gregorianElems); 570 571 const jchar* am = ures_getStringByIndex(gregorianElems, 0, &lengthAm, &status); 572 const jchar* pm = ures_getStringByIndex(gregorianElems, 1, &lengthPm, &status); 573 574 if(U_FAILURE(status)) { 575 ures_close(gregorianElems); 576 return NULL; 577 } 578 579 amPmMarkers = env->NewObjectArray(2, string_class, NULL); 580 amU = env->NewString(am, lengthAm); 581 env->SetObjectArrayElement(amPmMarkers, 0, amU); 582 env->DeleteLocalRef(amU); 583 pmU = env->NewString(pm, lengthPm); 584 env->SetObjectArrayElement(amPmMarkers, 1, pmU); 585 env->DeleteLocalRef(pmU); 586 ures_close(gregorianElems); 587 588 return amPmMarkers; 589} 590 591static jobjectArray getEras(JNIEnv* env, UResourceBundle *gregorian) { 592 593 jobjectArray eras; 594 jstring eraU; 595 const jchar* era; 596 597 UErrorCode status = U_ZERO_ERROR; 598 599 UResourceBundle *gregorianElems; 600 UResourceBundle *eraElems; 601 602 gregorianElems = ures_getByKey(gregorian, "eras", NULL, &status); 603 if(U_FAILURE(status)) { 604 return NULL; 605 } 606 607 eraElems = ures_getByKey(gregorianElems, "abbreviated", NULL, &status); 608 if(U_FAILURE(status)) { 609 ures_close(gregorianElems); 610 return NULL; 611 } 612 613 int eraLength; 614 615 int eraCount = ures_getSize(eraElems); 616 eras = env->NewObjectArray(eraCount, string_class, NULL); 617 618 ures_resetIterator(eraElems); 619 for(int i = 0; i < eraCount; i++) { 620 era = ures_getStringByIndex(eraElems, i, &eraLength, &status); 621 if(U_FAILURE(status)) { 622 ures_close(gregorianElems); 623 ures_close(eraElems); 624 return NULL; 625 } 626 eraU = env->NewString(era, eraLength); 627 env->SetObjectArrayElement(eras, i, eraU); 628 env->DeleteLocalRef(eraU); 629 } 630 ures_close(eraElems); 631 ures_close(gregorianElems); 632 633 return eras; 634} 635 636static jobjectArray getMonthNames(JNIEnv *env, UResourceBundle *gregorian) { 637 638 UErrorCode status = U_ZERO_ERROR; 639 640 const jchar* month; 641 jstring monthU; 642 643 UResourceBundle *gregorianElems = ures_getByKey(gregorian, "monthNames", NULL, &status); 644 if(U_FAILURE(status)) { 645 return NULL; 646 } 647 648 UResourceBundle *monthNameElems = ures_getByKey(gregorianElems, "format", NULL, &status); 649 if(U_FAILURE(status)) { 650 ures_close(gregorianElems); 651 return NULL; 652 } 653 654 UResourceBundle *monthNameElemsFormat = ures_getByKey(monthNameElems, "wide", NULL, &status); 655 if(U_FAILURE(status)) { 656 ures_close(monthNameElems); 657 ures_close(gregorianElems); 658 return NULL; 659 } 660 661 int monthNameLength; 662 ures_resetIterator(monthNameElemsFormat); 663 int monthCount = ures_getSize(monthNameElemsFormat); 664 jobjectArray months = env->NewObjectArray(monthCount + 1, string_class, NULL); 665 for(int i = 0; i < monthCount; i++) { 666 month = ures_getStringByIndex(monthNameElemsFormat, i, &monthNameLength, &status); 667 if(U_FAILURE(status)) { 668 ures_close(monthNameElemsFormat); 669 ures_close(monthNameElems); 670 ures_close(gregorianElems); 671 return NULL; 672 } 673 monthU = env->NewString(month, monthNameLength); 674 env->SetObjectArrayElement(months, i, monthU); 675 env->DeleteLocalRef(monthU); 676 } 677 678 monthU = env->NewStringUTF(""); 679 env->SetObjectArrayElement(months, monthCount, monthU); 680 env->DeleteLocalRef(monthU); 681 682 ures_close(monthNameElemsFormat); 683 ures_close(monthNameElems); 684 ures_close(gregorianElems); 685 return months; 686} 687 688static jobjectArray getShortMonthNames(JNIEnv *env, UResourceBundle *gregorian) { 689 690 UErrorCode status = U_ZERO_ERROR; 691 692 const jchar* shortMonth; 693 jstring shortMonthU; 694 695 UResourceBundle *gregorianElems = ures_getByKey(gregorian, "monthNames", NULL, &status); 696 if(U_FAILURE(status)) { 697 return NULL; 698 } 699 700 UResourceBundle *monthNameElems = ures_getByKey(gregorianElems, "format", NULL, &status); 701 if(U_FAILURE(status)) { 702 ures_close(gregorianElems); 703 return NULL; 704 } 705 706 UResourceBundle *monthNameElemsFormat = ures_getByKey(monthNameElems, "abbreviated", NULL, &status); 707 if(U_FAILURE(status)) { 708 ures_close(monthNameElems); 709 ures_close(gregorianElems); 710 return NULL; 711 } 712 713 int shortMonthNameLength; 714 ures_resetIterator(monthNameElemsFormat); 715 int shortMonthCount = ures_getSize(monthNameElemsFormat); 716 // the array length is +1 because the harmony locales had an empty string at the end of their month name array 717 jobjectArray shortMonths = env->NewObjectArray(shortMonthCount + 1, string_class, NULL); 718 for(int i = 0; i < shortMonthCount; i++) { 719 shortMonth = ures_getStringByIndex(monthNameElemsFormat, i, &shortMonthNameLength, &status); 720 if(U_FAILURE(status)) { 721 ures_close(monthNameElemsFormat); 722 ures_close(monthNameElems); 723 ures_close(gregorianElems); 724 return NULL; 725 } 726 shortMonthU = env->NewString(shortMonth, shortMonthNameLength); 727 env->SetObjectArrayElement(shortMonths, i, shortMonthU); 728 env->DeleteLocalRef(shortMonthU); 729 } 730 731 shortMonthU = env->NewStringUTF(""); 732 env->SetObjectArrayElement(shortMonths, shortMonthCount, shortMonthU); 733 env->DeleteLocalRef(shortMonthU); 734 735 ures_close(monthNameElemsFormat); 736 ures_close(monthNameElems); 737 ures_close(gregorianElems); 738 return shortMonths; 739} 740 741static jobjectArray getWeekdayNames(JNIEnv *env, UResourceBundle *gregorian) { 742 743 UErrorCode status = U_ZERO_ERROR; 744 745 const jchar* day; 746 jstring dayU; 747 748 UResourceBundle *gregorianElems = ures_getByKey(gregorian, "dayNames", NULL, &status); 749 if(U_FAILURE(status)) { 750 return NULL; 751 } 752 753 UResourceBundle *dayNameElems = ures_getByKey(gregorianElems, "format", NULL, &status); 754 if(U_FAILURE(status)) { 755 ures_close(gregorianElems); 756 return NULL; 757 } 758 759 UResourceBundle *dayNameElemsFormat = ures_getByKey(dayNameElems, "wide", NULL, &status); 760 if(U_FAILURE(status)) { 761 ures_close(dayNameElems); 762 ures_close(gregorianElems); 763 return NULL; 764 } 765 766 int dayNameLength; 767 ures_resetIterator(dayNameElemsFormat); 768 int dayCount = ures_getSize(dayNameElemsFormat); 769 jobjectArray weekdays = env->NewObjectArray(dayCount + 1, string_class, NULL); 770 // first entry in the weekdays array is an empty string 771 env->SetObjectArrayElement(weekdays, 0, env->NewStringUTF("")); 772 for(int i = 0; i < dayCount; i++) { 773 day = ures_getStringByIndex(dayNameElemsFormat, i, &dayNameLength, &status); 774 if(U_FAILURE(status)) { 775 ures_close(dayNameElemsFormat); 776 ures_close(dayNameElems); 777 ures_close(gregorianElems); 778 return NULL; 779 } 780 dayU = env->NewString(day, dayNameLength); 781 env->SetObjectArrayElement(weekdays, i + 1, dayU); 782 env->DeleteLocalRef(dayU); 783 } 784 785 ures_close(dayNameElemsFormat); 786 ures_close(dayNameElems); 787 ures_close(gregorianElems); 788 return weekdays; 789 790} 791 792static jobjectArray getShortWeekdayNames(JNIEnv *env, UResourceBundle *gregorian) { 793 794 UErrorCode status = U_ZERO_ERROR; 795 796 const jchar* shortDay; 797 jstring shortDayU; 798 799 UResourceBundle *gregorianElems = ures_getByKey(gregorian, "dayNames", NULL, &status); 800 if(U_FAILURE(status)) { 801 return NULL; 802 } 803 804 UResourceBundle *dayNameElems = ures_getByKey(gregorianElems, "format", NULL, &status); 805 if(U_FAILURE(status)) { 806 ures_close(gregorianElems); 807 return NULL; 808 } 809 810 UResourceBundle *dayNameElemsFormat = ures_getByKey(dayNameElems, "abbreviated", NULL, &status); 811 if(U_FAILURE(status)) { 812 ures_close(dayNameElems); 813 ures_close(gregorianElems); 814 return NULL; 815 } 816 817 int shortDayNameLength; 818 ures_resetIterator(dayNameElemsFormat); 819 int shortDayCount = ures_getSize(dayNameElemsFormat); 820 jobjectArray shortWeekdays = env->NewObjectArray(shortDayCount + 1, string_class, NULL); 821 env->SetObjectArrayElement(shortWeekdays, 0, env->NewStringUTF("")); 822 for(int i = 0; i < shortDayCount; i++) { 823 shortDay = ures_getStringByIndex(dayNameElemsFormat, i, &shortDayNameLength, &status); 824 if(U_FAILURE(status)) { 825 ures_close(dayNameElemsFormat); 826 ures_close(dayNameElems); 827 ures_close(gregorianElems); 828 return NULL; 829 } 830 shortDayU = env->NewString(shortDay, shortDayNameLength); 831 env->SetObjectArrayElement(shortWeekdays, i + 1, shortDayU); 832 env->DeleteLocalRef(shortDayU); 833 } 834 835 ures_close(dayNameElemsFormat); 836 ures_close(dayNameElems); 837 ures_close(gregorianElems); 838 return shortWeekdays; 839} 840 841static jstring getDecimalPatternChars(JNIEnv *env, UResourceBundle *rootElems) { 842 843 UErrorCode status = U_ZERO_ERROR; 844 845 int zeroL, digitL, decSepL, groupL, listL, percentL, permillL, expL, currSepL, minusL; 846 int patternLength; 847 848 jchar *patternChars; 849 850 const jchar* zero = ures_getStringByIndex(rootElems, 4, &zeroL, &status); 851 852 const jchar* digit = ures_getStringByIndex(rootElems, 5, &digitL, &status); 853 854 const jchar* decSep = ures_getStringByIndex(rootElems, 0, &decSepL, &status); 855 856 const jchar* group = ures_getStringByIndex(rootElems, 1, &groupL, &status); 857 858 const jchar* list = ures_getStringByIndex(rootElems, 2, &listL, &status); 859 860 const jchar* percent = ures_getStringByIndex(rootElems, 3, &percentL, &status); 861 862 const jchar* permill = ures_getStringByIndex(rootElems, 8, &permillL, &status); 863 864 const jchar* exp = ures_getStringByIndex(rootElems, 7, &expL, &status); 865 866 const jchar* currSep = ures_getStringByIndex(rootElems, 0, &currSepL, &status); 867 868 const jchar* minus = ures_getStringByIndex(rootElems, 6, &minusL, &status); 869 870 if(U_FAILURE(status)) { 871 return NULL; 872 } 873 874 875 patternChars = (jchar *) malloc(11 * sizeof(jchar)); 876 877 patternChars[0] = 0; 878 879 u_strncat(patternChars, zero, 1); 880 u_strncat(patternChars, digit, 1); 881 u_strncat(patternChars, decSep, 1); 882 u_strncat(patternChars, group, 1); 883 u_strncat(patternChars, list, 1); 884 u_strncat(patternChars, percent, 1); 885 u_strncat(patternChars, permill, 1); 886 u_strncat(patternChars, exp, 1); 887 u_strncat(patternChars, currSep, 1); 888 u_strncat(patternChars, minus, 1); 889 890 jstring decimalPatternChars = env->NewString(patternChars, 10); 891 892 free(patternChars); 893 894 return decimalPatternChars; 895} 896 897static jstring getIntCurrencyCode(JNIEnv *env, jclass clazz, jstring locale) { 898 899 const char *locStr = env->GetStringUTFChars(locale, NULL); 900 char country[3] = {0,0,0}; 901 902 // getting the 2 character country name 903 if(strlen(locStr) < 5) { 904 env->ReleaseStringUTFChars(locale, locStr); 905 return NULL; 906 } 907 if(locStr[3] < 'A' || locStr[3] > 'Z' || locStr[4] < 'A' || locStr[4] > 'Z') { 908 env->ReleaseStringUTFChars(locale, locStr); 909 return NULL; 910 } 911 country[0] = locStr[3]; 912 country[1] = locStr[4]; 913 914 env->ReleaseStringUTFChars(locale, locStr); 915 916 return getCurrencyCodeNative(env, clazz, env->NewStringUTF(country)); 917} 918 919static jstring getCurrencySymbol(JNIEnv *env, jclass clazz, jstring locale, jstring intCurrencySymbol) { 920 921 jstring result = getCurrencySymbolNative(env, clazz, locale, intCurrencySymbol); 922 if(result == intCurrencySymbol) { 923 return NULL; 924 } 925 return result; 926 927} 928 929static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, 930 jstring locale, jboolean needsTZ) { 931 932 UErrorCode status = U_ZERO_ERROR; 933 934 const char *loc = env->GetStringUTFChars(locale, NULL); 935 UResourceBundle *root = ures_openU(NULL, loc, &status); 936 937 env->ReleaseStringUTFChars(locale, loc); 938 if(U_FAILURE(status)) { 939 LOGI("Error getting resources"); 940 status = U_ZERO_ERROR; 941 return NULL; 942 } 943 944 945 946 jclass obj_class = env->FindClass("java/lang/Object"); 947 jclass integer_class = env->FindClass("java/lang/Integer"); 948 jmethodID integerInit = env->GetMethodID(integer_class, "<init>", "(I)V"); 949 jobjectArray result; 950 951 jobject firstDayOfWeek = NULL; 952 jobject minimalDaysInFirstWeek = NULL; 953 jobjectArray amPmMarkers = NULL; 954 jobjectArray eras = NULL; 955 jstring localPatternChars = NULL; 956 jobjectArray weekdays = NULL; 957 jobjectArray shortWeekdays = NULL; 958 jobjectArray months = NULL; 959 jobjectArray shortMonths = NULL; 960 jstring time_SHORT = NULL; 961 jstring time_MEDIUM = NULL; 962 jstring time_LONG = NULL; 963 jstring time_FULL = NULL; 964 jstring date_SHORT = NULL; 965 jstring date_MEDIUM = NULL; 966 jstring date_LONG = NULL; 967 jstring date_FULL = NULL; 968 jstring decimalPatternChars = NULL; 969 jstring naN = NULL; 970 jstring infinity = NULL; 971 jstring currencySymbol = NULL; 972 jstring intCurrencySymbol = NULL; 973 jstring numberPattern = NULL; 974 jstring integerPattern = NULL; 975 jstring currencyPattern = NULL; 976 jstring percentPattern = NULL; 977 jobjectArray zones = NULL; 978 979 int counter = 0; 980 981 int firstDayVals[2] = {-1, -1}; 982 983 const jchar* nan = (const jchar *)NULL; 984 const jchar* inf = (const jchar *)NULL; 985 int nanL, infL; 986 987 988 UResourceBundle *gregorian; 989 UResourceBundle *gregorianElems; 990 UResourceBundle *rootElems; 991 992 993 994 995 // get the resources needed 996 rootElems = ures_getByKey(root, "calendar", NULL, &status); 997 if(U_FAILURE(status)) { 998 return NULL; 999 } 1000 1001 gregorian = ures_getByKey(rootElems, "gregorian", NULL, &status); 1002 if(U_FAILURE(status)) { 1003 ures_close(rootElems); 1004 return NULL; 1005 } 1006 1007 1008 1009 // adding the first day of week and minimal days in first week values 1010 getDayInitVector(env, gregorian, firstDayVals); 1011 if((firstDayVals[0] != -1) && (firstDayVals[1] != -1)) { 1012 firstDayOfWeek = env->NewObject(integer_class, integerInit, firstDayVals[0]); 1013 minimalDaysInFirstWeek = env->NewObject(integer_class, integerInit, firstDayVals[1]); 1014 // adding First_Day and Minimal_Days integer to the result 1015 counter += 2; 1016 } 1017 1018 1019 // adding ampm string array to the result"); 1020 amPmMarkers = getAmPmMarkers(env, gregorian); 1021 if(amPmMarkers != NULL) { 1022 counter++; 1023 } 1024 1025 1026 // adding eras string array to the result 1027 eras = getEras(env, gregorian); 1028 if(eras != NULL) { 1029 counter++; 1030 } 1031 1032 1033 // local pattern chars are initially always the same 1034 localPatternChars = env->NewStringUTF("GyMdkHmsSEDFwWahKzZ"); 1035 // adding local pattern chars string to the result 1036 counter++; 1037 1038 1039 // adding month names string array to the result 1040 months = getMonthNames(env, gregorian); 1041 if(months != NULL) { 1042 counter++; 1043 } 1044 1045 1046 // adding short month names string array to the result 1047 shortMonths = getShortMonthNames(env, gregorian); 1048 if(shortMonths != NULL) { 1049 counter++; 1050 } 1051 1052 1053 // adding day names string array to the result 1054 weekdays = getWeekdayNames(env, gregorian); 1055 if(weekdays != NULL) { 1056 counter++; 1057 } 1058 1059 1060 // adding short day names string array to the result 1061 shortWeekdays = getShortWeekdayNames(env, gregorian); 1062 if(shortWeekdays != NULL) { 1063 counter++; 1064 } 1065 1066 const UChar *pattern; 1067 jchar check[2] = {0, 0}; 1068 u_uastrcpy(check, "v"); 1069 jchar replacement[2] = {0, 0}; 1070 u_uastrcpy(replacement, "z"); 1071 jchar *pos; 1072 jchar *patternCopy; 1073 int patternLength; 1074 1075 // adding date and time format patterns to the result 1076 gregorianElems = ures_getByKey(gregorian, "DateTimePatterns", NULL, &status); 1077 if(U_FAILURE(status)) { 1078 status = U_ZERO_ERROR; 1079 goto endOfCalendar; 1080 } 1081 1082 pattern = ures_getStringByIndex(gregorianElems, 0, &patternLength, &status); 1083 // there are some patterns in icu that use the pattern character 'v' 1084 // java doesn't accept this, so it gets replaced by 'z' which has 1085 // about the same result as 'v', the timezone name. 1086 // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz 1087 // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time" 1088 patternCopy = (jchar *) malloc((patternLength + 1) * sizeof(jchar)); 1089 u_strcpy(patternCopy, pattern); 1090 if(U_FAILURE(status)) { 1091 free(patternCopy); 1092 status = U_ZERO_ERROR; 1093 goto endOfCalendar; 1094 } 1095 while((pos = u_strchr(patternCopy, check[0])) != NULL) { 1096 u_memset(pos, replacement[0], 1); 1097 } 1098 time_FULL = env->NewString(patternCopy, patternLength); 1099 free(patternCopy); 1100 counter++; 1101 1102 pattern = ures_getStringByIndex(gregorianElems, 1, &patternLength, &status); 1103 if(U_FAILURE(status)) { 1104 status = U_ZERO_ERROR; 1105 goto endOfCalendar; 1106 } 1107 time_LONG = env->NewString(pattern, patternLength); 1108 counter++; 1109 1110 pattern = ures_getStringByIndex(gregorianElems, 2, &patternLength, &status); 1111 if(U_FAILURE(status)) { 1112 status = U_ZERO_ERROR; 1113 goto endOfCalendar; 1114 } 1115 time_MEDIUM = env->NewString(pattern, patternLength); 1116 counter++; 1117 1118 pattern = ures_getStringByIndex(gregorianElems, 3, &patternLength, &status); 1119 if(U_FAILURE(status)) { 1120 status = U_ZERO_ERROR; 1121 goto endOfCalendar; 1122 } 1123 time_SHORT = env->NewString(pattern, patternLength); 1124 counter++; 1125 1126 pattern = ures_getStringByIndex(gregorianElems, 4, &patternLength, &status); 1127 if(U_FAILURE(status)) { 1128 status = U_ZERO_ERROR; 1129 goto endOfCalendar; 1130 } 1131 date_FULL = env->NewString(pattern, patternLength); 1132 counter++; 1133 1134 pattern = ures_getStringByIndex(gregorianElems, 5, &patternLength, &status); 1135 if(U_FAILURE(status)) { 1136 status = U_ZERO_ERROR; 1137 goto endOfCalendar; 1138 } 1139 date_LONG = env->NewString(pattern, patternLength); 1140 counter++; 1141 1142 pattern = ures_getStringByIndex(gregorianElems, 6, &patternLength, &status); 1143 if(U_FAILURE(status)) { 1144 status = U_ZERO_ERROR; 1145 goto endOfCalendar; 1146 } 1147 date_MEDIUM = env->NewString(pattern, patternLength); 1148 counter++; 1149 1150 pattern = ures_getStringByIndex(gregorianElems, 7, &patternLength, &status); 1151 if(U_FAILURE(status)) { 1152 status = U_ZERO_ERROR; 1153 goto endOfCalendar; 1154 } 1155 date_SHORT = env->NewString(pattern, patternLength); 1156 counter++; 1157 1158 1159endOfCalendar: 1160 1161 if(gregorianElems != NULL) { 1162 ures_close(gregorianElems); 1163 } 1164 ures_close(gregorian); 1165 ures_close(rootElems); 1166 1167 1168 rootElems = ures_getByKey(root, "NumberElements", NULL, &status); 1169 if(U_FAILURE(status)) { 1170 status = U_ZERO_ERROR; 1171 } 1172 1173 if(ures_getSize(rootElems) >= 11) { 1174 1175 // adding decimal pattern chars to the result 1176 decimalPatternChars = getDecimalPatternChars(env, rootElems); 1177 if(decimalPatternChars != NULL) { 1178 counter++; 1179 } 1180 1181 // adding NaN pattern char to the result 1182 nan = ures_getStringByIndex(rootElems, 10, &nanL, &status); 1183 if(U_SUCCESS(status)) { 1184 naN = env->NewString(nan, nanL); 1185 counter++; 1186 } 1187 status = U_ZERO_ERROR; 1188 1189 // adding infinity pattern char to the result 1190 inf = ures_getStringByIndex(rootElems, 9, &infL, &status); 1191 if(U_SUCCESS(status)) { 1192 infinity = env->NewString(inf, infL); 1193 counter++; 1194 } 1195 status = U_ZERO_ERROR; 1196 } 1197 1198 ures_close(rootElems); 1199 1200 1201 // adding intl currency code to result 1202 intCurrencySymbol = getIntCurrencyCode(env, clazz, locale); 1203 if(intCurrencySymbol != NULL) { 1204 // adding currency symbol to result 1205 currencySymbol = getCurrencySymbol(env, clazz, locale, intCurrencySymbol); 1206 } else { 1207 intCurrencySymbol = env->NewStringUTF("XXX"); 1208 } 1209 if(currencySymbol == NULL) { 1210 currencySymbol = env->NewStringUTF("\u00a4"); 1211 } 1212 counter += 2; 1213 1214 1215 // adding number format patterns to the result 1216 int numOfEntries; 1217 int decSepOffset; 1218 NumberFormat *nf; 1219 jchar *tmpPattern; 1220 1221 rootElems = ures_getByKey(root, "NumberPatterns", NULL, &status); 1222 if(U_FAILURE(status)) { 1223 status = U_ZERO_ERROR; 1224 goto zones; 1225 } 1226 1227 numOfEntries = ures_getSize(rootElems); 1228 if(numOfEntries < 3) { 1229 ures_close(rootElems); 1230 goto zones; 1231 } 1232 1233 // number pattern 1234 pattern = ures_getStringByIndex(rootElems, 0, &patternLength, &status); 1235 if(U_FAILURE(status)) { 1236 status = U_ZERO_ERROR; 1237 ures_close(rootElems); 1238 goto zones; 1239 } 1240 numberPattern = env->NewString(pattern, patternLength); 1241 counter++; 1242 1243 // integer pattern derived from number pattern 1244 // We need to convert a C string literal to a UChar string for u_strcspn. 1245 static const char c_decSep[] = "."; 1246 UChar decSep[sizeof(c_decSep)]; 1247 u_charsToUChars(c_decSep, decSep, sizeof(c_decSep)); 1248 decSepOffset = u_strcspn(pattern, decSep); 1249 tmpPattern = (jchar *) malloc((decSepOffset + 1) * sizeof(jchar)); 1250 u_strncpy(tmpPattern, pattern, decSepOffset); 1251 integerPattern = env->NewString(tmpPattern, decSepOffset); 1252 free(tmpPattern); 1253 counter++; 1254 1255 // currency pattern 1256 pattern = ures_getStringByIndex(rootElems, 1, &patternLength, &status); 1257 if(U_FAILURE(status)) { 1258 status = U_ZERO_ERROR; 1259 ures_close(rootElems); 1260 goto zones; 1261 } 1262 currencyPattern = env->NewString(pattern, patternLength); 1263 counter++; 1264 1265 // percent pattern 1266 pattern = ures_getStringByIndex(rootElems, 2, &patternLength, &status); 1267 if(U_FAILURE(status)) { 1268 status = U_ZERO_ERROR; 1269 ures_close(rootElems); 1270 goto zones; 1271 } 1272 percentPattern = env->NewString(pattern, patternLength); 1273 counter++; 1274 1275 ures_close(rootElems); 1276 1277zones: 1278 1279 ures_close(root); 1280 1281 1282 if(needsTZ == JNI_TRUE) { 1283 counter++; //add empty timezone 1284 } 1285 1286 1287 1288 // collect all content and put it into an array 1289 result = env->NewObjectArray(counter, obj_class, NULL); 1290 1291 int index = 0; 1292 1293 if(needsTZ == JNI_TRUE) { 1294 addObject(env, result, "timezones", NULL, index++); 1295 } 1296 if(firstDayOfWeek != NULL && index < counter) { 1297 addObject(env, result, "First_Day", firstDayOfWeek, index++); 1298 } 1299 if(minimalDaysInFirstWeek != NULL && index < counter) { 1300 addObject(env, result, "Minimal_Days", minimalDaysInFirstWeek, index++); 1301 } 1302 if(amPmMarkers != NULL && index < counter) { 1303 addObject(env, result, "ampm", amPmMarkers, index++); 1304 } 1305 if(eras != NULL && index < counter) { 1306 addObject(env, result, "eras", eras, index++); 1307 } 1308 if(localPatternChars != NULL && index < counter) { 1309 addObject(env, result, "LocalPatternChars", localPatternChars, index++); 1310 } 1311 if(weekdays != NULL && index < counter) { 1312 addObject(env, result, "weekdays", weekdays, index++); 1313 } 1314 if(shortWeekdays != NULL && index < counter) { 1315 addObject(env, result, "shortWeekdays", shortWeekdays, index++); 1316 } 1317 if(months != NULL && index < counter) { 1318 addObject(env, result, "months", months, index++); 1319 } 1320 if(shortMonths != NULL && index < counter) { 1321 addObject(env, result, "shortMonths", shortMonths, index++); 1322 } 1323 if(time_SHORT != NULL && index < counter) { 1324 addObject(env, result, "Time_SHORT", time_SHORT, index++); 1325 } 1326 if(time_MEDIUM != NULL && index < counter) { 1327 addObject(env, result, "Time_MEDIUM", time_MEDIUM, index++); 1328 } 1329 if(time_LONG != NULL && index < counter) { 1330 addObject(env, result, "Time_LONG", time_LONG, index++); 1331 } 1332 if(time_FULL != NULL && index < counter) { 1333 addObject(env, result, "Time_FULL", time_FULL, index++); 1334 } 1335 if(date_SHORT != NULL && index < counter) { 1336 addObject(env, result, "Date_SHORT", date_SHORT, index++); 1337 } 1338 if(date_MEDIUM != NULL && index < counter) { 1339 addObject(env, result, "Date_MEDIUM", date_MEDIUM, index++); 1340 } 1341 if(date_LONG != NULL && index < counter) { 1342 addObject(env, result, "Date_LONG", date_LONG, index++); 1343 } 1344 if(date_FULL != NULL && index < counter) { 1345 addObject(env, result, "Date_FULL", date_FULL, index++); 1346 } 1347 if(decimalPatternChars != NULL && index < counter) { 1348 addObject(env, result, "DecimalPatternChars", decimalPatternChars, index++); 1349 } 1350 if(naN != NULL && index < counter) { 1351 addObject(env, result, "NaN", naN, index++); 1352 } 1353 if(infinity != NULL && index < counter) { 1354 addObject(env, result, "Infinity", infinity, index++); 1355 } 1356 if(currencySymbol != NULL && index < counter) { 1357 addObject(env, result, "CurrencySymbol", currencySymbol, index++); 1358 } 1359 if(intCurrencySymbol != NULL && index < counter) { 1360 addObject(env, result, "IntCurrencySymbol", intCurrencySymbol, index++); 1361 } 1362 if(numberPattern != NULL && index < counter) { 1363 addObject(env, result, "Number", numberPattern, index++); 1364 } 1365 if(integerPattern != NULL && index < counter) { 1366 addObject(env, result, "Integer", integerPattern, index++); 1367 } 1368 if(currencyPattern != NULL && index < counter) { 1369 addObject(env, result, "Currency", currencyPattern, index++); 1370 } 1371 if(percentPattern != NULL && index < counter) { 1372 addObject(env, result, "Percent", percentPattern, index++); 1373 } 1374 1375 return result; 1376 1377} 1378 1379static JNINativeMethod gMethods[] = { 1380 /* name, signature, funcPtr */ 1381 {"getFractionDigitsNative", "(Ljava/lang/String;)I", 1382 (void*) getFractionDigitsNative}, 1383 {"getCurrencyCodeNative", "(Ljava/lang/String;)Ljava/lang/String;", 1384 (void*) getCurrencyCodeNative}, 1385 {"getCurrencySymbolNative", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1386 (void*) getCurrencySymbolNative}, 1387 {"getDisplayCountryNative", 1388 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1389 (void*) getDisplayCountryNative}, 1390 {"getDisplayLanguageNative", 1391 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1392 (void*) getDisplayLanguageNative}, 1393 {"getDisplayVariantNative", 1394 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1395 (void*) getDisplayVariantNative}, 1396 {"getISO3CountryNative", 1397 "(Ljava/lang/String;)Ljava/lang/String;", 1398 (void*) getISO3CountryNative}, 1399 {"getISO3LanguageNative", 1400 "(Ljava/lang/String;)Ljava/lang/String;", 1401 (void*) getISO3LanguageNative}, 1402 {"getISOCountriesNative", "()[Ljava/lang/String;", 1403 (void*) getISOCountriesNative}, 1404 {"getISOLanguagesNative", "()[Ljava/lang/String;", 1405 (void*) getISOLanguagesNative}, 1406 {"getAvailableLocalesNative", "()[Ljava/lang/String;", 1407 (void*) getAvailableLocalesNative}, 1408 {"getTimeZonesNative", 1409 "([[Ljava/lang/String;Ljava/lang/String;)V", 1410 (void*) getTimeZonesNative}, 1411 {"getDisplayTimeZoneNative", 1412 "(Ljava/lang/String;ZILjava/lang/String;)Ljava/lang/String;", 1413 (void*) getDisplayTimeZoneNative}, 1414 {"getContentImpl", 1415 "(Ljava/lang/String;Z)[[Ljava/lang/Object;", 1416 (void*) getContentImpl}, 1417}; 1418 1419int register_com_ibm_icu4jni_util_Resources(JNIEnv* env) { 1420 1421 // initializing String 1422 1423 jclass stringclass = env->FindClass("java/lang/String"); 1424 1425 if(stringclass == NULL) { 1426 LOGE("Can't find java/lang/String"); 1427 jniThrowException(env, "java/lang/ClassNotFoundException", "java.lang.String"); 1428 return -1; 1429 } 1430 1431 string_class = (jclass) env->NewGlobalRef(stringclass); 1432 1433 return jniRegisterNativeMethods(env, 1434 "com/ibm/icu4jni/util/Resources", gMethods, 1435 NELEM(gMethods)); 1436} 1437