< prev index next >

src/java.base/share/native/libjava/jni_util.c

Print this page
rev 17358 : 8181147: JNI_GetStringPlatformChars should have a fast path for UTF-8
Reviewed-by: martin, erikj, sherman


 425         goto done;
 426 
 427     cls = (*env)->FindClass(env, class_name);
 428     if (cls == 0) {
 429         goto done;
 430     }
 431     cls_initMID  = (*env)->GetMethodID(env, cls,
 432                                        "<init>", constructor_sig);
 433     if (cls_initMID == NULL) {
 434         goto done;
 435     }
 436     va_start(args, constructor_sig);
 437     obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
 438     va_end(args);
 439 
 440  done:
 441     (*env)->DeleteLocalRef(env, cls);
 442     return obj;
 443 }
 444 
 445 /* Optimized for char set ISO_8559_1 */
 446 static jstring
 447 newString8859_1(JNIEnv *env, const char *str)
 448 {
 449     int len = (int)strlen(str);
 450     jchar buf[512];
 451     jchar *str1;
 452     jstring result;
 453     int i;
 454 
 455     if (len > 512) {
 456         str1 = (jchar *)malloc(len * sizeof(jchar));
 457         if (str1 == 0) {
 458             JNU_ThrowOutOfMemoryError(env, 0);
 459             return 0;
 460         }
 461     } else
 462         str1 = buf;
 463 
 464     for (i=0;i<len;i++)
 465         str1[i] = (unsigned char)str[i];
 466     result = (*env)->NewString(env, str1, len);
 467     if (str1 != buf)
 468         free(str1);
 469     return result;
 470 }
 471 







 472 static const char*
 473 getString8859_1Chars(JNIEnv *env, jstring jstr)
 474 {
 475     int i;
 476     char *result;
 477     jint len = (*env)->GetStringLength(env, jstr);
 478     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
 479     if (str == 0) {
 480         return 0;
 481     }
 482 
 483     result = MALLOC_MIN4(len);
 484     if (result == 0) {
 485         (*env)->ReleaseStringCritical(env, jstr, str);
 486         JNU_ThrowOutOfMemoryError(env, 0);
 487         return 0;
 488     }
 489 
 490     for (i=0; i<len; i++) {
 491         jchar unicode = str[i];
 492         if (unicode <= 0x00ff)
 493             result[i] = (char)unicode;
 494         else
 495             result[i] = '?';
 496     }
 497 
 498     result[len] = 0;
 499     (*env)->ReleaseStringCritical(env, jstr, str);
 500     return result;
 501 }
 502 
 503 
 504 /* Optimized for char set ISO646-US (us-ascii) */
 505 static jstring
 506 newString646_US(JNIEnv *env, const char *str)
 507 {
 508     int len = (int)strlen(str);
 509     jchar buf[512];
 510     jchar *str1;
 511     jstring result;
 512     int i;
 513 
 514     if (len > 512) {
 515         str1 = (jchar *)malloc(len * sizeof(jchar));
 516         if (str1 == 0) {
 517             JNU_ThrowOutOfMemoryError(env, 0);
 518             return 0;
 519         }
 520     } else
 521         str1 = buf;
 522 
 523     for (i=0; i<len; i++) {
 524         unsigned char c = (unsigned char)str[i];


 556         jchar unicode = str[i];
 557         if (unicode <= 0x007f )
 558             result[i] = (char)unicode;
 559         else
 560             result[i] = '?';
 561     }
 562 
 563     result[len] = 0;
 564     (*env)->ReleaseStringCritical(env, jstr, str);
 565     return result;
 566 }
 567 
 568 /* enumeration of c1 row from Cp1252 */
 569 static int cp1252c1chars[32] = {
 570     0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
 571     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
 572     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
 573     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
 574 };
 575 
 576 /* Optimized for char set Cp1252 */
 577 static jstring
 578 newStringCp1252(JNIEnv *env, const char *str)
 579 {
 580     int len = (int) strlen(str);
 581     jchar buf[512];
 582     jchar *str1;
 583     jstring result;
 584     int i;
 585     if (len > 512) {
 586         str1 = (jchar *)malloc(len * sizeof(jchar));
 587         if (str1 == 0) {
 588             JNU_ThrowOutOfMemoryError(env, 0);
 589             return 0;
 590         }
 591     } else
 592         str1 = buf;
 593 
 594     for (i=0; i<len; i++) {
 595         unsigned char c = (unsigned char)str[i];
 596         if ((c >= 0x80) && (c <= 0x9f))


 654             case 0x203A: result[i] = (char)0x9B; break;
 655             case 0x0153: result[i] = (char)0x9C; break;
 656             case 0x017E: result[i] = (char)0x9E; break;
 657             case 0x0178: result[i] = (char)0x9F; break;
 658             default:     result[i] = '?';  break;
 659         }
 660     }
 661 
 662     result[len] = 0;
 663     (*env)->ReleaseStringCritical(env, jstr, str);
 664     return result;
 665 }
 666 
 667 static int fastEncoding = NO_ENCODING_YET;
 668 static jstring jnuEncoding = NULL;
 669 
 670 /* Cached method IDs */
 671 static jmethodID String_init_ID;        /* String(byte[], enc) */
 672 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
 673 
 674 int getFastEncoding() {
 675     return fastEncoding;

















































































 676 }
 677 
 678 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
 679  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
 680  */
 681 void
 682 initializeEncoding(JNIEnv *env)
 683 {
 684     jstring propname = 0;
 685     jstring enc = 0;
 686     jclass strClazz = NULL;
 687 
 688     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
 689         return;
 690 
 691     strClazz = JNU_ClassString(env);
 692     CHECK_NULL(strClazz);
 693 
 694     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
 695     if (propname) {


 701                         "getProperty",
 702                         "(Ljava/lang/String;)Ljava/lang/String;",
 703                         propname).l;
 704         if (!exc) {
 705             if (enc) {
 706                 const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
 707                 if (encname) {
 708            /*
 709             * On Solaris with nl_langinfo() called in GetJavaProperties():
 710             *
 711             *   locale undefined -> NULL -> hardcoded default
 712             *   "C" locale       -> "" -> hardcoded default     (on 2.6)
 713             *   "C" locale       -> "ISO646-US"                 (on Sol 7/8)
 714             *   "en_US" locale -> "ISO8859-1"
 715             *   "en_GB" locale -> "ISO8859-1"                   (on Sol 7/8)
 716             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
 717             */
 718                     if ((strcmp(encname, "8859_1") == 0) ||
 719                         (strcmp(encname, "ISO8859-1") == 0) ||
 720                         (strcmp(encname, "ISO8859_1") == 0) ||
 721                         (strcmp(encname, "ISO-8859-1") == 0))
 722                         fastEncoding = FAST_8859_1;
 723                     else if (strcmp(encname, "ISO646-US") == 0)



 724                         fastEncoding = FAST_646_US;
 725                     else if (strcmp(encname, "Cp1252") == 0 ||
 726                              /* This is a temporary fix until we move */
 727                              /* to wide character versions of all Windows */
 728                              /* calls. */
 729                              strcmp(encname, "utf-16le") == 0)
 730                         fastEncoding = FAST_CP1252;
 731                     else {
 732                         fastEncoding = NO_FAST_ENCODING;
 733                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 734                     }
 735                     (*env)->ReleaseStringUTFChars(env, enc, encname);
 736                 }
 737             }
 738         } else {
 739             (*env)->ExceptionClear(env);
 740         }
 741     } else {
 742         (*env)->ExceptionClear(env);
 743     }
 744     (*env)->DeleteLocalRef(env, propname);
 745     (*env)->DeleteLocalRef(env, enc);
 746 
 747     /* Initialize method-id cache */
 748     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
 749                                              "getBytes", "(Ljava/lang/String;)[B");
 750     CHECK_NULL(String_getBytes_ID);
 751     String_init_ID = (*env)->GetMethodID(env, strClazz,
 752                                          "<init>", "([BLjava/lang/String;)V");


 753 }
 754 
 755 static jboolean isJNUEncodingSupported = JNI_FALSE;
 756 static jboolean jnuEncodingSupported(JNIEnv *env) {
 757     jboolean exe;
 758     if (isJNUEncodingSupported == JNI_TRUE) {
 759         return JNI_TRUE;
 760     }
 761     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
 762                                     env, &exe,
 763                                     "java/nio/charset/Charset",
 764                                     "isSupported",
 765                                     "(Ljava/lang/String;)Z",
 766                                     jnuEncoding).z;
 767     return isJNUEncodingSupported;
 768 }
 769 
 770 
 771 JNIEXPORT jstring
 772 NewStringPlatform(JNIEnv *env, const char *str)
 773 {
 774     return JNU_NewStringPlatform(env, str);
 775 }
 776 
 777 JNIEXPORT jstring JNICALL
 778 JNU_NewStringPlatform(JNIEnv *env, const char *str)
 779 {
 780     jstring result = NULL;
 781     jbyteArray hab = 0;
 782     int len;
 783 
 784     if (fastEncoding == NO_ENCODING_YET) {
 785         initializeEncoding(env);
 786         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 787     }
 788 
 789     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 790         return newString8859_1(env, str);
 791     if (fastEncoding == FAST_646_US)
 792         return newString646_US(env, str);
 793     if (fastEncoding == FAST_CP1252)
 794         return newStringCp1252(env, str);
 795 
 796     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 797         return NULL;
 798 
 799     len = (int)strlen(str);
 800     hab = (*env)->NewByteArray(env, len);
 801     if (hab != 0) {
 802         jclass strClazz = JNU_ClassString(env);
 803         CHECK_NULL_RETURN(strClazz, 0);
 804         (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
 805         if (jnuEncodingSupported(env)) {
 806             result = (*env)->NewObject(env, strClazz,
 807                                        String_init_ID, hab, jnuEncoding);
 808         } else {
 809             /*If the encoding specified in sun.jnu.encoding is not endorsed
 810               by "Charset.isSupported" we have to fall back to use String(byte[])
 811               explicitly here without specifying the encoding name, in which the
 812               StringCoding class will pickup the iso-8859-1 as the fallback
 813               converter for us.
 814              */
 815             jmethodID mid = (*env)->GetMethodID(env, strClazz,
 816                                                 "<init>", "([B)V");
 817             if (mid != NULL) {
 818                 result = (*env)->NewObject(env, strClazz, mid, hab);
 819             }
 820         }
 821         (*env)->DeleteLocalRef(env, hab);
 822         return result;
 823     }
 824     return NULL;
 825 }
 826 
 827 JNIEXPORT const char *
 828 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 829 {
 830     return JNU_GetStringPlatformChars(env, jstr, isCopy);
 831 }
 832 
 833 JNIEXPORT const char * JNICALL
 834 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 835 {
 836     char *result = NULL;
 837     jbyteArray hab = 0;
 838 
 839     if (isCopy)
 840         *isCopy = JNI_TRUE;
 841 
 842     if (fastEncoding == NO_ENCODING_YET) {
 843         initializeEncoding(env);
 844         JNU_CHECK_EXCEPTION_RETURN(env, 0);
 845     }
 846 
 847     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 848         return getString8859_1Chars(env, jstr);
 849     if (fastEncoding == FAST_646_US)
 850         return getString646_USChars(env, jstr);
 851     if (fastEncoding == FAST_CP1252)
 852         return getStringCp1252Chars(env, jstr);
 853 
 854     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 855         return 0;
 856 
 857     if (jnuEncodingSupported(env)) {
 858         hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
 859     } else {
 860         jmethodID mid;
 861         jclass strClazz = JNU_ClassString(env);
 862         CHECK_NULL_RETURN(strClazz, 0);
 863         mid = (*env)->GetMethodID(env, strClazz,
 864                                        "getBytes", "()[B");
 865         if (mid != NULL) {
 866             hab = (*env)->CallObjectMethod(env, jstr, mid);
 867         }
 868     }
 869 
 870     if (!(*env)->ExceptionCheck(env)) {
 871         jint len = (*env)->GetArrayLength(env, hab);
 872         result = MALLOC_MIN4(len);
 873         if (result == 0) {
 874             JNU_ThrowOutOfMemoryError(env, 0);
 875             (*env)->DeleteLocalRef(env, hab);
 876             return 0;
 877         }
 878         (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
 879         result[len] = 0; /* NULL-terminate */
 880     }
 881 
 882     (*env)->DeleteLocalRef(env, hab);
 883     return result;
 884 }
 885 










































































 886 JNIEXPORT void JNICALL
 887 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
 888 {
 889     free((void *)str);
 890 }
 891 
 892 /*
 893  * Export the platform dependent path canonicalization so that
 894  * VM can find it when loading system classes.
 895  * This function is also used by the instrumentation agent.
 896  */
 897 extern int canonicalize(char *path, const char *out, int len);
 898 
 899 JNIEXPORT int
 900 Canonicalize(JNIEnv *unused, char *orig, char *out, int len)
 901 {
 902     /* canonicalize an already natived path */
 903     return canonicalize(orig, out, len);
 904 }
 905 




 425         goto done;
 426 
 427     cls = (*env)->FindClass(env, class_name);
 428     if (cls == 0) {
 429         goto done;
 430     }
 431     cls_initMID  = (*env)->GetMethodID(env, cls,
 432                                        "<init>", constructor_sig);
 433     if (cls_initMID == NULL) {
 434         goto done;
 435     }
 436     va_start(args, constructor_sig);
 437     obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
 438     va_end(args);
 439 
 440  done:
 441     (*env)->DeleteLocalRef(env, cls);
 442     return obj;
 443 }
 444 
 445 /* Optimized for charset ISO_8559_1 */
 446 static jstring
 447 newSizedString8859_1(JNIEnv *env, const char *str, const int len)
 448 {

 449     jchar buf[512];
 450     jchar *str1;
 451     jstring result;
 452     int i;
 453 
 454     if (len > 512) {
 455         str1 = (jchar *)malloc(len * sizeof(jchar));
 456         if (str1 == 0) {
 457             JNU_ThrowOutOfMemoryError(env, 0);
 458             return 0;
 459         }
 460     } else
 461         str1 = buf;
 462 
 463     for (i=0;i<len;i++)
 464         str1[i] = (unsigned char)str[i];
 465     result = (*env)->NewString(env, str1, len);
 466     if (str1 != buf)
 467         free(str1);
 468     return result;
 469 }
 470 
 471 static jstring
 472 newString8859_1(JNIEnv *env, const char *str)
 473 {
 474     int len = (int)strlen(str);
 475     return newSizedString8859_1(env, str, len);
 476 }
 477 
 478 static const char*
 479 getString8859_1Chars(JNIEnv *env, jstring jstr)
 480 {
 481     int i;
 482     char *result;
 483     jint len = (*env)->GetStringLength(env, jstr);
 484     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
 485     if (str == 0) {
 486         return 0;
 487     }
 488 
 489     result = MALLOC_MIN4(len);
 490     if (result == 0) {
 491         (*env)->ReleaseStringCritical(env, jstr, str);
 492         JNU_ThrowOutOfMemoryError(env, 0);
 493         return 0;
 494     }
 495 
 496     for (i=0; i<len; i++) {
 497         jchar unicode = str[i];
 498         if (unicode <= 0x00ff)
 499             result[i] = (char)unicode;
 500         else
 501             result[i] = '?';
 502     }
 503 
 504     result[len] = 0;
 505     (*env)->ReleaseStringCritical(env, jstr, str);
 506     return result;
 507 }
 508 
 509 
 510 /* Optimized for charset ISO646-US (us-ascii) */
 511 static jstring
 512 newString646_US(JNIEnv *env, const char *str)
 513 {
 514     int len = (int)strlen(str);
 515     jchar buf[512];
 516     jchar *str1;
 517     jstring result;
 518     int i;
 519 
 520     if (len > 512) {
 521         str1 = (jchar *)malloc(len * sizeof(jchar));
 522         if (str1 == 0) {
 523             JNU_ThrowOutOfMemoryError(env, 0);
 524             return 0;
 525         }
 526     } else
 527         str1 = buf;
 528 
 529     for (i=0; i<len; i++) {
 530         unsigned char c = (unsigned char)str[i];


 562         jchar unicode = str[i];
 563         if (unicode <= 0x007f )
 564             result[i] = (char)unicode;
 565         else
 566             result[i] = '?';
 567     }
 568 
 569     result[len] = 0;
 570     (*env)->ReleaseStringCritical(env, jstr, str);
 571     return result;
 572 }
 573 
 574 /* enumeration of c1 row from Cp1252 */
 575 static int cp1252c1chars[32] = {
 576     0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
 577     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
 578     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
 579     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
 580 };
 581 
 582 /* Optimized for charset Cp1252 */
 583 static jstring
 584 newStringCp1252(JNIEnv *env, const char *str)
 585 {
 586     int len = (int) strlen(str);
 587     jchar buf[512];
 588     jchar *str1;
 589     jstring result;
 590     int i;
 591     if (len > 512) {
 592         str1 = (jchar *)malloc(len * sizeof(jchar));
 593         if (str1 == 0) {
 594             JNU_ThrowOutOfMemoryError(env, 0);
 595             return 0;
 596         }
 597     } else
 598         str1 = buf;
 599 
 600     for (i=0; i<len; i++) {
 601         unsigned char c = (unsigned char)str[i];
 602         if ((c >= 0x80) && (c <= 0x9f))


 660             case 0x203A: result[i] = (char)0x9B; break;
 661             case 0x0153: result[i] = (char)0x9C; break;
 662             case 0x017E: result[i] = (char)0x9E; break;
 663             case 0x0178: result[i] = (char)0x9F; break;
 664             default:     result[i] = '?';  break;
 665         }
 666     }
 667 
 668     result[len] = 0;
 669     (*env)->ReleaseStringCritical(env, jstr, str);
 670     return result;
 671 }
 672 
 673 static int fastEncoding = NO_ENCODING_YET;
 674 static jstring jnuEncoding = NULL;
 675 
 676 /* Cached method IDs */
 677 static jmethodID String_init_ID;        /* String(byte[], enc) */
 678 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
 679 
 680 /* Cached field IDs */
 681 static jfieldID String_coder_ID;        /* String.coder */
 682 static jfieldID String_value_ID;        /* String.value */
 683 
 684 static jboolean isJNUEncodingSupported = JNI_FALSE;
 685 static jboolean jnuEncodingSupported(JNIEnv *env) {
 686     jboolean exe;
 687     if (isJNUEncodingSupported == JNI_TRUE) {
 688         return JNI_TRUE;
 689     }
 690     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
 691                                     env, &exe,
 692                                     "java/nio/charset/Charset",
 693                                     "isSupported",
 694                                     "(Ljava/lang/String;)Z",
 695                                     jnuEncoding).z;
 696     return isJNUEncodingSupported;
 697 }
 698 
 699 /* Create a new string by converting str to a heap-allocated byte array and
 700  * calling the appropriate String constructor.
 701  */
 702 static jstring
 703 newSizedStringJava(JNIEnv *env, const char *str, const int len)
 704 {
 705     jstring result = NULL;
 706     jbyteArray bytes = 0;
 707 
 708     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 709         return NULL;
 710 
 711     bytes = (*env)->NewByteArray(env, len);
 712     if (bytes != NULL) {
 713         jclass strClazz = JNU_ClassString(env);
 714         CHECK_NULL_RETURN(strClazz, 0);
 715         (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
 716         if (jnuEncodingSupported(env)) {
 717             result = (*env)->NewObject(env, strClazz,
 718                                        String_init_ID, bytes, jnuEncoding);
 719         } else {
 720             /*If the encoding specified in sun.jnu.encoding is not endorsed
 721               by "Charset.isSupported" we have to fall back to use String(byte[])
 722               explicitly here without specifying the encoding name, in which the
 723               StringCoding class will pickup the iso-8859-1 as the fallback
 724               converter for us.
 725              */
 726             jmethodID mid = (*env)->GetMethodID(env, strClazz,
 727                                                 "<init>", "([B)V");
 728             if (mid != NULL) {
 729                 result = (*env)->NewObject(env, strClazz, mid, bytes);
 730             }
 731         }
 732         (*env)->DeleteLocalRef(env, bytes);
 733         return result;
 734     }
 735     return NULL;
 736 }
 737 
 738 static jstring
 739 newStringJava(JNIEnv *env, const char *str)
 740 {
 741     int len = (int)strlen(str);
 742     return newSizedStringJava(env, str, len);
 743 }
 744 
 745 /* Optimized for charset UTF-8 */
 746 static jstring
 747 newStringUTF8(JNIEnv *env, const char *str)
 748 {
 749     int len;
 750     const unsigned char *p;
 751     unsigned char asciiCheck;
 752     for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
 753         asciiCheck |= *p;
 754     }
 755     len = (int)((const char*)p - str);
 756 
 757     if (asciiCheck < 0x80) {
 758         // ascii fast-path
 759         return newSizedString8859_1(env, str, len);
 760     }
 761 
 762     return newSizedStringJava(env, str, len);
 763 }
 764 
 765 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
 766  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
 767  */
 768 void
 769 initializeEncoding(JNIEnv *env)
 770 {
 771     jstring propname = 0;
 772     jstring enc = 0;
 773     jclass strClazz = NULL;
 774 
 775     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
 776         return;
 777 
 778     strClazz = JNU_ClassString(env);
 779     CHECK_NULL(strClazz);
 780 
 781     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
 782     if (propname) {


 788                         "getProperty",
 789                         "(Ljava/lang/String;)Ljava/lang/String;",
 790                         propname).l;
 791         if (!exc) {
 792             if (enc) {
 793                 const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
 794                 if (encname) {
 795            /*
 796             * On Solaris with nl_langinfo() called in GetJavaProperties():
 797             *
 798             *   locale undefined -> NULL -> hardcoded default
 799             *   "C" locale       -> "" -> hardcoded default     (on 2.6)
 800             *   "C" locale       -> "ISO646-US"                 (on Sol 7/8)
 801             *   "en_US" locale -> "ISO8859-1"
 802             *   "en_GB" locale -> "ISO8859-1"                   (on Sol 7/8)
 803             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
 804             */
 805                     if ((strcmp(encname, "8859_1") == 0) ||
 806                         (strcmp(encname, "ISO8859-1") == 0) ||
 807                         (strcmp(encname, "ISO8859_1") == 0) ||
 808                         (strcmp(encname, "ISO-8859-1") == 0)) {
 809                         fastEncoding = FAST_8859_1;
 810                     } else if (strcmp(encname, "UTF-8") == 0) {
 811                         fastEncoding = FAST_UTF_8;
 812                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 813                     } else if (strcmp(encname, "ISO646-US") == 0) {
 814                         fastEncoding = FAST_646_US;
 815                     } else if (strcmp(encname, "Cp1252") == 0 ||
 816                              /* This is a temporary fix until we move */
 817                              /* to wide character versions of all Windows */
 818                              /* calls. */
 819                              strcmp(encname, "utf-16le") == 0) {
 820                         fastEncoding = FAST_CP1252;
 821                     } else {
 822                         fastEncoding = NO_FAST_ENCODING;
 823                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 824                     }
 825                     (*env)->ReleaseStringUTFChars(env, enc, encname);
 826                 }
 827             }
 828         } else {
 829             (*env)->ExceptionClear(env);
 830         }
 831     } else {
 832         (*env)->ExceptionClear(env);
 833     }
 834     (*env)->DeleteLocalRef(env, propname);
 835     (*env)->DeleteLocalRef(env, enc);
 836 
 837     /* Initialize method-id cache */
 838     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
 839                                              "getBytes", "(Ljava/lang/String;)[B");
 840     CHECK_NULL(String_getBytes_ID);
 841     String_init_ID = (*env)->GetMethodID(env, strClazz,
 842                                          "<init>", "([BLjava/lang/String;)V");
 843     String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
 844     String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
 845 }
 846 
















 847 JNIEXPORT jstring
 848 NewStringPlatform(JNIEnv *env, const char *str)
 849 {
 850     return JNU_NewStringPlatform(env, str);
 851 }
 852 
 853 JNIEXPORT jstring JNICALL
 854 JNU_NewStringPlatform(JNIEnv *env, const char *str)
 855 {




 856     if (fastEncoding == NO_ENCODING_YET) {
 857         initializeEncoding(env);
 858         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 859     }
 860 
 861     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 862         return newString8859_1(env, str);
 863     if (fastEncoding == FAST_646_US)
 864         return newString646_US(env, str);
 865     if (fastEncoding == FAST_CP1252)
 866         return newStringCp1252(env, str);
 867     if (fastEncoding == FAST_UTF_8)
 868         return newStringUTF8(env, str);
 869     return newStringJava(env, str);



























 870 }
 871 
 872 JNIEXPORT const char *
 873 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 874 {
 875     return JNU_GetStringPlatformChars(env, jstr, isCopy);
 876 }
 877 
 878 static const char* getStringBytes(JNIEnv *env, jstring jstr) {


 879     char *result = NULL;
 880     jbyteArray hab = 0;
 881 















 882     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 883         return 0;
 884 
 885     if (jnuEncodingSupported(env)) {
 886         hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
 887     } else {
 888         jmethodID mid;
 889         jclass strClazz = JNU_ClassString(env);
 890         CHECK_NULL_RETURN(strClazz, 0);
 891         mid = (*env)->GetMethodID(env, strClazz,
 892                                        "getBytes", "()[B");
 893         if (mid != NULL) {
 894             hab = (*env)->CallObjectMethod(env, jstr, mid);
 895         }
 896     }
 897 
 898     if (!(*env)->ExceptionCheck(env)) {
 899         jint len = (*env)->GetArrayLength(env, hab);
 900         result = MALLOC_MIN4(len);
 901         if (result == 0) {
 902             JNU_ThrowOutOfMemoryError(env, 0);
 903             (*env)->DeleteLocalRef(env, hab);
 904             return 0;
 905         }
 906         (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
 907         result[len] = 0; /* NULL-terminate */
 908     }
 909 
 910     (*env)->DeleteLocalRef(env, hab);
 911     return result;
 912 }
 913 
 914 static const char*
 915 getStringUTF8(JNIEnv *env, jstring jstr)
 916 {
 917     int i;
 918     char *result;
 919     jarray value;
 920     jint len;
 921     const jbyte *str;
 922     jint rlen;
 923     int ri;
 924     jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
 925     if (coder != LATIN1) {
 926         return getStringBytes(env, jstr);
 927     }
 928     value = (jarray)(*env)->GetObjectField(env, jstr, String_value_ID);
 929     len = (*env)->GetArrayLength(env, value);
 930     str = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, value, NULL);
 931 
 932     if (str == NULL) {
 933         return NULL;
 934     }
 935 
 936     rlen = len;
 937     // we need two bytes for each latin-1 char above 127 (negative jbytes)
 938     for (i = 0; i < len; i++) {
 939         if (str[i] < 0) {
 940             rlen++;
 941         }
 942     }
 943 
 944     result = MALLOC_MIN4(rlen);
 945     if (result == NULL) {
 946         (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
 947         JNU_ThrowOutOfMemoryError(env, 0);
 948         return NULL;
 949     }
 950 
 951     for (ri = 0, i = 0; i < len; i++) {
 952         jbyte c = str[i];
 953         if (c < 0) {
 954             result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
 955             result[ri++] = (char)(0x80 | (c & 0x3f));
 956         } else {
 957             result[ri++] = c;
 958         }
 959     }
 960     result[rlen] = '\0';
 961     (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
 962     return result;
 963 }
 964 
 965 JNIEXPORT const char * JNICALL
 966 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 967 {
 968 
 969     if (isCopy)
 970         *isCopy = JNI_TRUE;
 971 
 972     if (fastEncoding == NO_ENCODING_YET) {
 973         initializeEncoding(env);
 974         JNU_CHECK_EXCEPTION_RETURN(env, 0);
 975     }
 976 
 977     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 978         return getString8859_1Chars(env, jstr);
 979     if (fastEncoding == FAST_646_US)
 980         return getString646_USChars(env, jstr);
 981     if (fastEncoding == FAST_CP1252)
 982         return getStringCp1252Chars(env, jstr);
 983     if (fastEncoding == FAST_UTF_8)
 984         return getStringUTF8(env, jstr);
 985     else
 986         return getStringBytes(env, jstr);
 987 }
 988 JNIEXPORT void JNICALL
 989 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
 990 {
 991     free((void *)str);
 992 }
 993 
 994 /*
 995  * Export the platform dependent path canonicalization so that
 996  * VM can find it when loading system classes.
 997  * This function is also used by the instrumentation agent.
 998  */
 999 extern int canonicalize(char *path, const char *out, int len);
1000 
1001 JNIEXPORT int
1002 Canonicalize(JNIEnv *unused, char *orig, char *out, int len)
1003 {
1004     /* canonicalize an already natived path */
1005     return canonicalize(orig, out, len);
1006 }
1007 


< prev index next >