Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/native/libjava/jni_util.c
41149 views
1
/*
2
* Copyright (c) 1997, 2021, 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 <stdlib.h>
27
#include <string.h>
28
29
#include "jvm.h"
30
#include "jni.h"
31
#include "jni_util.h"
32
#include "java_lang_String.h"
33
34
/* Due to a bug in the win32 C runtime library strings
35
* such as "z:" need to be appended with a "." so we
36
* must allocate at least 4 bytes to allow room for
37
* this expansion. See 4235353 for details.
38
*/
39
#define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1))
40
41
/**
42
* Throw a Java exception by name. Similar to SignalError.
43
*/
44
JNIEXPORT void JNICALL
45
JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg)
46
{
47
jclass cls = (*env)->FindClass(env, name);
48
49
if (cls != 0) /* Otherwise an exception has already been thrown */
50
(*env)->ThrowNew(env, cls, msg);
51
}
52
53
/* JNU_Throw common exceptions */
54
55
JNIEXPORT void JNICALL
56
JNU_ThrowNullPointerException(JNIEnv *env, const char *msg)
57
{
58
JNU_ThrowByName(env, "java/lang/NullPointerException", msg);
59
}
60
61
JNIEXPORT void JNICALL
62
JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg)
63
{
64
JNU_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
65
}
66
67
JNIEXPORT void JNICALL
68
JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg)
69
{
70
JNU_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
71
}
72
73
JNIEXPORT void JNICALL
74
JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg)
75
{
76
JNU_ThrowByName(env, "java/lang/IllegalArgumentException", msg);
77
}
78
79
JNIEXPORT void JNICALL
80
JNU_ThrowInternalError(JNIEnv *env, const char *msg)
81
{
82
JNU_ThrowByName(env, "java/lang/InternalError", msg);
83
}
84
85
JNIEXPORT void JNICALL
86
JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg)
87
{
88
JNU_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
89
}
90
91
JNIEXPORT void JNICALL
92
JNU_ThrowIOException(JNIEnv *env, const char *msg)
93
{
94
JNU_ThrowByName(env, "java/io/IOException", msg);
95
}
96
97
/*
98
* Throw an exception by name, using the string returned by
99
* getLastErrorString for the detail string. If the last-error
100
* string is NULL, use the given default detail string.
101
*/
102
JNIEXPORT void JNICALL
103
JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
104
const char *defaultDetail)
105
{
106
char buf[256];
107
size_t n = getLastErrorString(buf, sizeof(buf));
108
109
if (n > 0) {
110
jstring s = JNU_NewStringPlatform(env, buf);
111
if (s != NULL) {
112
jobject x = JNU_NewObjectByName(env, name,
113
"(Ljava/lang/String;)V", s);
114
if (x != NULL) {
115
(*env)->Throw(env, x);
116
}
117
}
118
}
119
if (!(*env)->ExceptionOccurred(env)) {
120
JNU_ThrowByName(env, name, defaultDetail);
121
}
122
}
123
124
/*
125
* Throw an exception by name, using a given message and the string
126
* returned by getLastErrorString to construct the detail string.
127
*/
128
JNIEXPORT void JNICALL
129
JNU_ThrowByNameWithMessageAndLastError
130
(JNIEnv *env, const char *name, const char *message)
131
{
132
char buf[256];
133
size_t n = getLastErrorString(buf, sizeof(buf));
134
size_t messagelen = message == NULL ? 0 : strlen(message);
135
136
if (n > 0) {
137
jstring s = JNU_NewStringPlatform(env, buf);
138
if (s != NULL) {
139
jobject x = NULL;
140
if (messagelen) {
141
jstring s2 = NULL;
142
size_t messageextlen = messagelen + 4;
143
char *str1 = (char *)malloc((messageextlen) * sizeof(char));
144
if (str1 == 0) {
145
JNU_ThrowOutOfMemoryError(env, 0);
146
return;
147
}
148
jio_snprintf(str1, messageextlen, " (%s)", message);
149
s2 = (*env)->NewStringUTF(env, str1);
150
free(str1);
151
JNU_CHECK_EXCEPTION(env);
152
if (s2 != NULL) {
153
jstring s3 = JNU_CallMethodByName(
154
env, NULL, s, "concat",
155
"(Ljava/lang/String;)Ljava/lang/String;",
156
s2).l;
157
(*env)->DeleteLocalRef(env, s2);
158
JNU_CHECK_EXCEPTION(env);
159
if (s3 != NULL) {
160
(*env)->DeleteLocalRef(env, s);
161
s = s3;
162
}
163
}
164
}
165
x = JNU_NewObjectByName(env, name, "(Ljava/lang/String;)V", s);
166
if (x != NULL) {
167
(*env)->Throw(env, x);
168
}
169
}
170
}
171
172
if (!(*env)->ExceptionOccurred(env)) {
173
if (messagelen) {
174
JNU_ThrowByName(env, name, message);
175
} else {
176
JNU_ThrowByName(env, name, "no further information");
177
}
178
}
179
}
180
181
/*
182
* Convenience method.
183
* Call JNU_ThrowByNameWithLastError for java.io.IOException.
184
*/
185
JNIEXPORT void JNICALL
186
JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail)
187
{
188
JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail);
189
}
190
191
192
JNIEXPORT jvalue JNICALL
193
JNU_CallStaticMethodByName(JNIEnv *env,
194
jboolean *hasException,
195
const char *class_name,
196
const char *name,
197
const char *signature,
198
...)
199
{
200
jclass clazz;
201
jmethodID mid;
202
va_list args;
203
jvalue result;
204
const char *p = signature;
205
206
/* find out the return type */
207
while (*p && *p != ')')
208
p++;
209
p++;
210
211
result.i = 0;
212
213
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
214
goto done2;
215
216
clazz = (*env)->FindClass(env, class_name);
217
if (clazz == 0)
218
goto done2;
219
mid = (*env)->GetStaticMethodID(env, clazz, name, signature);
220
if (mid == 0)
221
goto done1;
222
va_start(args, signature);
223
switch (*p) {
224
case 'V':
225
(*env)->CallStaticVoidMethodV(env, clazz, mid, args);
226
break;
227
case '[':
228
case 'L':
229
result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args);
230
break;
231
case 'Z':
232
result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args);
233
break;
234
case 'B':
235
result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args);
236
break;
237
case 'C':
238
result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args);
239
break;
240
case 'S':
241
result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args);
242
break;
243
case 'I':
244
result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args);
245
break;
246
case 'J':
247
result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args);
248
break;
249
case 'F':
250
result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args);
251
break;
252
case 'D':
253
result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args);
254
break;
255
default:
256
(*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature");
257
}
258
va_end(args);
259
260
done1:
261
(*env)->DeleteLocalRef(env, clazz);
262
done2:
263
if (hasException) {
264
*hasException = (*env)->ExceptionCheck(env);
265
}
266
return result;
267
}
268
269
JNIEXPORT jvalue JNICALL
270
JNU_CallMethodByName(JNIEnv *env,
271
jboolean *hasException,
272
jobject obj,
273
const char *name,
274
const char *signature,
275
...)
276
{
277
jvalue result;
278
va_list args;
279
280
va_start(args, signature);
281
result = JNU_CallMethodByNameV(env, hasException, obj, name, signature,
282
args);
283
va_end(args);
284
285
return result;
286
}
287
288
289
JNIEXPORT jvalue JNICALL
290
JNU_CallMethodByNameV(JNIEnv *env,
291
jboolean *hasException,
292
jobject obj,
293
const char *name,
294
const char *signature,
295
va_list args)
296
{
297
jclass clazz;
298
jmethodID mid;
299
jvalue result;
300
const char *p = signature;
301
302
/* find out the return type */
303
while (*p && *p != ')')
304
p++;
305
p++;
306
307
result.i = 0;
308
309
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
310
goto done2;
311
312
clazz = (*env)->GetObjectClass(env, obj);
313
mid = (*env)->GetMethodID(env, clazz, name, signature);
314
if (mid == 0)
315
goto done1;
316
317
switch (*p) {
318
case 'V':
319
(*env)->CallVoidMethodV(env, obj, mid, args);
320
break;
321
case '[':
322
case 'L':
323
result.l = (*env)->CallObjectMethodV(env, obj, mid, args);
324
break;
325
case 'Z':
326
result.z = (*env)->CallBooleanMethodV(env, obj, mid, args);
327
break;
328
case 'B':
329
result.b = (*env)->CallByteMethodV(env, obj, mid, args);
330
break;
331
case 'C':
332
result.c = (*env)->CallCharMethodV(env, obj, mid, args);
333
break;
334
case 'S':
335
result.s = (*env)->CallShortMethodV(env, obj, mid, args);
336
break;
337
case 'I':
338
result.i = (*env)->CallIntMethodV(env, obj, mid, args);
339
break;
340
case 'J':
341
result.j = (*env)->CallLongMethodV(env, obj, mid, args);
342
break;
343
case 'F':
344
result.f = (*env)->CallFloatMethodV(env, obj, mid, args);
345
break;
346
case 'D':
347
result.d = (*env)->CallDoubleMethodV(env, obj, mid, args);
348
break;
349
default:
350
(*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature");
351
}
352
done1:
353
(*env)->DeleteLocalRef(env, clazz);
354
done2:
355
if (hasException) {
356
*hasException = (*env)->ExceptionCheck(env);
357
}
358
return result;
359
}
360
361
JNIEXPORT jobject JNICALL
362
JNU_NewObjectByName(JNIEnv *env, const char *class_name,
363
const char *constructor_sig, ...)
364
{
365
jobject obj = NULL;
366
367
jclass cls = 0;
368
jmethodID cls_initMID;
369
va_list args;
370
371
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
372
goto done;
373
374
cls = (*env)->FindClass(env, class_name);
375
if (cls == 0) {
376
goto done;
377
}
378
cls_initMID = (*env)->GetMethodID(env, cls,
379
"<init>", constructor_sig);
380
if (cls_initMID == NULL) {
381
goto done;
382
}
383
va_start(args, constructor_sig);
384
obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
385
va_end(args);
386
387
done:
388
(*env)->DeleteLocalRef(env, cls);
389
return obj;
390
}
391
392
/* Optimized for charset ISO_8559_1 */
393
static jstring
394
newSizedString8859_1(JNIEnv *env, const char *str, const int len)
395
{
396
jchar buf[512];
397
jchar *str1;
398
jstring result;
399
int i;
400
401
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
402
return NULL;
403
404
if (len > 512) {
405
str1 = (jchar *)malloc(len * sizeof(jchar));
406
if (str1 == 0) {
407
JNU_ThrowOutOfMemoryError(env, 0);
408
return 0;
409
}
410
} else
411
str1 = buf;
412
413
for (i=0;i<len;i++)
414
str1[i] = (unsigned char)str[i];
415
result = (*env)->NewString(env, str1, len);
416
if (str1 != buf)
417
free(str1);
418
return result;
419
}
420
421
static jstring
422
newString8859_1(JNIEnv *env, const char *str)
423
{
424
int len = (int)strlen(str);
425
return newSizedString8859_1(env, str, len);
426
}
427
428
static const char*
429
getString8859_1Chars(JNIEnv *env, jstring jstr)
430
{
431
int i;
432
char *result;
433
jint len = (*env)->GetStringLength(env, jstr);
434
const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
435
if (str == 0) {
436
return 0;
437
}
438
439
result = MALLOC_MIN4(len);
440
if (result == 0) {
441
(*env)->ReleaseStringCritical(env, jstr, str);
442
JNU_ThrowOutOfMemoryError(env, 0);
443
return 0;
444
}
445
446
for (i=0; i<len; i++) {
447
jchar unicode = str[i];
448
if (unicode <= 0x00ff)
449
result[i] = (char)unicode;
450
else
451
result[i] = '?';
452
}
453
454
result[len] = 0;
455
(*env)->ReleaseStringCritical(env, jstr, str);
456
return result;
457
}
458
459
460
/* Optimized for charset ISO646-US (us-ascii) */
461
static jstring
462
newString646_US(JNIEnv *env, const char *str)
463
{
464
int len = (int)strlen(str);
465
jchar buf[512] = {0};
466
jchar *str1;
467
jstring result;
468
int i;
469
470
if (len > 512) {
471
str1 = (jchar *)malloc(len * sizeof(jchar));
472
if (str1 == 0) {
473
JNU_ThrowOutOfMemoryError(env, 0);
474
return 0;
475
}
476
} else
477
str1 = buf;
478
479
for (i=0; i<len; i++) {
480
unsigned char c = (unsigned char)str[i];
481
if (c <= 0x7f)
482
str1[i] = c;
483
else
484
str1[i] = '?';
485
}
486
487
result = (*env)->NewString(env, str1, len);
488
if (str1 != buf)
489
free(str1);
490
return result;
491
}
492
493
static const char*
494
getString646_USChars(JNIEnv *env, jstring jstr)
495
{
496
int i;
497
char *result;
498
jint len = (*env)->GetStringLength(env, jstr);
499
const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
500
if (str == 0) {
501
return 0;
502
}
503
504
result = MALLOC_MIN4(len);
505
if (result == 0) {
506
(*env)->ReleaseStringCritical(env, jstr, str);
507
JNU_ThrowOutOfMemoryError(env, 0);
508
return 0;
509
}
510
511
for (i=0; i<len; i++) {
512
jchar unicode = str[i];
513
if (unicode <= 0x007f )
514
result[i] = (char)unicode;
515
else
516
result[i] = '?';
517
}
518
519
result[len] = 0;
520
(*env)->ReleaseStringCritical(env, jstr, str);
521
return result;
522
}
523
524
/* enumeration of c1 row from Cp1252 */
525
static int cp1252c1chars[32] = {
526
0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
527
0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
528
0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
529
0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
530
};
531
532
/* Optimized for charset Cp1252 */
533
static jstring
534
newStringCp1252(JNIEnv *env, const char *str)
535
{
536
int len = (int) strlen(str);
537
jchar buf[512];
538
jchar *str1;
539
jstring result;
540
int i;
541
542
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
543
return NULL;
544
545
if (len > 512) {
546
str1 = (jchar *)malloc(len * sizeof(jchar));
547
if (str1 == 0) {
548
JNU_ThrowOutOfMemoryError(env, 0);
549
return 0;
550
}
551
} else
552
str1 = buf;
553
554
for (i=0; i<len; i++) {
555
unsigned char c = (unsigned char)str[i];
556
if ((c >= 0x80) && (c <= 0x9f))
557
str1[i] = cp1252c1chars[c-128];
558
else
559
str1[i] = c;
560
}
561
562
result = (*env)->NewString(env, str1, len);
563
if (str1 != buf)
564
free(str1);
565
return result;
566
}
567
568
static const char*
569
getStringCp1252Chars(JNIEnv *env, jstring jstr)
570
{
571
int i;
572
char *result;
573
jint len = (*env)->GetStringLength(env, jstr);
574
const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
575
if (str == 0) {
576
return 0;
577
}
578
579
result = MALLOC_MIN4(len);
580
if (result == 0) {
581
(*env)->ReleaseStringCritical(env, jstr, str);
582
JNU_ThrowOutOfMemoryError(env, 0);
583
return 0;
584
}
585
586
for (i=0; i<len; i++) {
587
jchar c = str[i];
588
if (c < 256) {
589
if ((c >= 0x80) && (c <= 0x9f)) {
590
result[i] = '?';
591
} else {
592
result[i] = (char)c;
593
}
594
} else switch(c) {
595
case 0x20AC: result[i] = (char)0x80; break;
596
case 0x201A: result[i] = (char)0x82; break;
597
case 0x0192: result[i] = (char)0x83; break;
598
case 0x201E: result[i] = (char)0x84; break;
599
case 0x2026: result[i] = (char)0x85; break;
600
case 0x2020: result[i] = (char)0x86; break;
601
case 0x2021: result[i] = (char)0x87; break;
602
case 0x02C6: result[i] = (char)0x88; break;
603
case 0x2030: result[i] = (char)0x89; break;
604
case 0x0160: result[i] = (char)0x8A; break;
605
case 0x2039: result[i] = (char)0x8B; break;
606
case 0x0152: result[i] = (char)0x8C; break;
607
case 0x017D: result[i] = (char)0x8E; break;
608
case 0x2018: result[i] = (char)0x91; break;
609
case 0x2019: result[i] = (char)0x92; break;
610
case 0x201C: result[i] = (char)0x93; break;
611
case 0x201D: result[i] = (char)0x94; break;
612
case 0x2022: result[i] = (char)0x95; break;
613
case 0x2013: result[i] = (char)0x96; break;
614
case 0x2014: result[i] = (char)0x97; break;
615
case 0x02DC: result[i] = (char)0x98; break;
616
case 0x2122: result[i] = (char)0x99; break;
617
case 0x0161: result[i] = (char)0x9A; break;
618
case 0x203A: result[i] = (char)0x9B; break;
619
case 0x0153: result[i] = (char)0x9C; break;
620
case 0x017E: result[i] = (char)0x9E; break;
621
case 0x0178: result[i] = (char)0x9F; break;
622
default: result[i] = '?'; break;
623
}
624
}
625
626
result[len] = 0;
627
(*env)->ReleaseStringCritical(env, jstr, str);
628
return result;
629
}
630
631
static int fastEncoding = NO_ENCODING_YET;
632
static jstring jnuEncoding = NULL;
633
634
/* Cached method IDs */
635
static jmethodID String_init_ID; /* String(byte[], enc) */
636
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
637
638
/* Cached field IDs */
639
static jfieldID String_coder_ID; /* String.coder */
640
static jfieldID String_value_ID; /* String.value */
641
642
static jboolean isJNUEncodingSupported = JNI_FALSE;
643
static jboolean jnuEncodingSupported(JNIEnv *env) {
644
jboolean exe;
645
if (isJNUEncodingSupported == JNI_TRUE) {
646
return JNI_TRUE;
647
}
648
isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
649
env, &exe,
650
"java/nio/charset/Charset",
651
"isSupported",
652
"(Ljava/lang/String;)Z",
653
jnuEncoding).z;
654
return isJNUEncodingSupported;
655
}
656
657
/* Create a new string by converting str to a heap-allocated byte array and
658
* calling the appropriate String constructor.
659
*/
660
static jstring
661
newSizedStringJava(JNIEnv *env, const char *str, const int len)
662
{
663
jstring result = NULL;
664
jbyteArray bytes = 0;
665
666
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
667
return NULL;
668
669
bytes = (*env)->NewByteArray(env, len);
670
if (bytes != NULL) {
671
jclass strClazz = JNU_ClassString(env);
672
CHECK_NULL_RETURN(strClazz, 0);
673
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
674
if (jnuEncodingSupported(env)) {
675
result = (*env)->NewObject(env, strClazz,
676
String_init_ID, bytes, jnuEncoding);
677
} else {
678
/*If the encoding specified in sun.jnu.encoding is not endorsed
679
by "Charset.isSupported" we have to fall back to use String(byte[])
680
explicitly here without specifying the encoding name, in which the
681
StringCoding class will pickup the iso-8859-1 as the fallback
682
converter for us.
683
*/
684
jmethodID mid = (*env)->GetMethodID(env, strClazz,
685
"<init>", "([B)V");
686
if (mid != NULL) {
687
result = (*env)->NewObject(env, strClazz, mid, bytes);
688
}
689
}
690
(*env)->DeleteLocalRef(env, bytes);
691
return result;
692
}
693
return NULL;
694
}
695
696
static jstring
697
newStringJava(JNIEnv *env, const char *str)
698
{
699
int len = (int)strlen(str);
700
return newSizedStringJava(env, str, len);
701
}
702
703
/* Optimized for charset UTF-8 */
704
static jstring
705
newStringUTF8(JNIEnv *env, const char *str)
706
{
707
int len;
708
const unsigned char *p;
709
unsigned char asciiCheck;
710
for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
711
asciiCheck |= *p;
712
}
713
len = (int)((const char*)p - str);
714
715
if (asciiCheck < 0x80) {
716
// ascii fast-path
717
return newSizedString8859_1(env, str, len);
718
}
719
720
return newSizedStringJava(env, str, len);
721
}
722
723
/* Initialize the fast encoding from the encoding name.
724
* Export InitializeEncoding so that the VM can initialize it if required.
725
*/
726
JNIEXPORT void
727
InitializeEncoding(JNIEnv *env, const char *encname)
728
{
729
jclass strClazz = NULL;
730
731
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
732
return;
733
734
strClazz = JNU_ClassString(env);
735
CHECK_NULL(strClazz);
736
737
if (encname) {
738
/*
739
* On Solaris with nl_langinfo() called in GetJavaProperties():
740
*
741
* locale undefined -> NULL -> hardcoded default
742
* "C" locale -> "" -> hardcoded default (on 2.6)
743
* "C" locale -> "ISO646-US" (on Sol 7/8)
744
* "en_US" locale -> "ISO8859-1"
745
* "en_GB" locale -> "ISO8859-1" (on Sol 7/8)
746
* "en_UK" locale -> "ISO8859-1" (on 2.6)
747
*/
748
if ((strcmp(encname, "8859_1") == 0) ||
749
(strcmp(encname, "ISO8859-1") == 0) ||
750
(strcmp(encname, "ISO8859_1") == 0) ||
751
(strcmp(encname, "ISO-8859-1") == 0)) {
752
fastEncoding = FAST_8859_1;
753
} else if (strcmp(encname, "UTF-8") == 0) {
754
jstring enc = (*env)->NewStringUTF(env, encname);
755
if (enc == NULL)
756
return;
757
fastEncoding = FAST_UTF_8;
758
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
759
(*env)->DeleteLocalRef(env, enc);
760
} else if (strcmp(encname, "ISO646-US") == 0) {
761
fastEncoding = FAST_646_US;
762
} else if (strcmp(encname, "Cp1252") == 0 ||
763
/* This is a temporary fix until we move */
764
/* to wide character versions of all Windows */
765
/* calls. */
766
strcmp(encname, "utf-16le") == 0) {
767
fastEncoding = FAST_CP1252;
768
} else {
769
jstring enc = (*env)->NewStringUTF(env, encname);
770
if (enc == NULL)
771
return;
772
fastEncoding = NO_FAST_ENCODING;
773
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
774
(*env)->DeleteLocalRef(env, enc);
775
}
776
} else {
777
JNU_ThrowInternalError(env, "platform encoding undefined");
778
return;
779
}
780
781
/* Initialize method-id cache */
782
String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
783
"getBytes", "(Ljava/lang/String;)[B");
784
CHECK_NULL(String_getBytes_ID);
785
String_init_ID = (*env)->GetMethodID(env, strClazz,
786
"<init>", "([BLjava/lang/String;)V");
787
CHECK_NULL(String_init_ID);
788
String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
789
CHECK_NULL(String_coder_ID);
790
String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
791
CHECK_NULL(String_value_ID);
792
}
793
794
JNIEXPORT jstring JNICALL
795
JNU_NewStringPlatform(JNIEnv *env, const char *str)
796
{
797
if (fastEncoding == FAST_UTF_8)
798
return newStringUTF8(env, str);
799
if (fastEncoding == FAST_8859_1)
800
return newString8859_1(env, str);
801
if (fastEncoding == FAST_646_US)
802
return newString646_US(env, str);
803
if (fastEncoding == FAST_CP1252)
804
return newStringCp1252(env, str);
805
if (fastEncoding == NO_ENCODING_YET) {
806
JNU_ThrowInternalError(env, "platform encoding not initialized");
807
return NULL;
808
}
809
return newStringJava(env, str);
810
}
811
812
JNIEXPORT const char *
813
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
814
{
815
return JNU_GetStringPlatformChars(env, jstr, isCopy);
816
}
817
818
static const char* getStringBytes(JNIEnv *env, jstring jstr) {
819
char *result = NULL;
820
jbyteArray hab = 0;
821
822
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
823
return 0;
824
825
if (jnuEncodingSupported(env)) {
826
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
827
} else {
828
jmethodID mid;
829
jclass strClazz = JNU_ClassString(env);
830
CHECK_NULL_RETURN(strClazz, 0);
831
mid = (*env)->GetMethodID(env, strClazz,
832
"getBytes", "()[B");
833
if (mid != NULL) {
834
hab = (*env)->CallObjectMethod(env, jstr, mid);
835
}
836
}
837
838
if (!(*env)->ExceptionCheck(env)) {
839
jint len = (*env)->GetArrayLength(env, hab);
840
result = MALLOC_MIN4(len);
841
if (result == 0) {
842
JNU_ThrowOutOfMemoryError(env, 0);
843
(*env)->DeleteLocalRef(env, hab);
844
return 0;
845
}
846
(*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
847
result[len] = 0; /* NULL-terminate */
848
}
849
850
(*env)->DeleteLocalRef(env, hab);
851
return result;
852
}
853
854
static const char*
855
getStringUTF8(JNIEnv *env, jstring jstr)
856
{
857
int i;
858
char *result;
859
jbyteArray value;
860
jint len;
861
jbyte *str;
862
jint rlen;
863
int ri;
864
jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
865
if (coder != java_lang_String_LATIN1) {
866
return getStringBytes(env, jstr);
867
}
868
if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
869
return NULL;
870
}
871
value = (*env)->GetObjectField(env, jstr, String_value_ID);
872
if (value == NULL)
873
return NULL;
874
len = (*env)->GetArrayLength(env, value);
875
str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
876
if (str == NULL) {
877
return NULL;
878
}
879
880
rlen = len;
881
// we need two bytes for each latin-1 char above 127 (negative jbytes)
882
for (i = 0; i < len; i++) {
883
if (str[i] < 0) {
884
rlen++;
885
}
886
}
887
888
result = MALLOC_MIN4(rlen);
889
if (result == NULL) {
890
(*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
891
JNU_ThrowOutOfMemoryError(env, 0);
892
return NULL;
893
}
894
895
for (ri = 0, i = 0; i < len; i++) {
896
jbyte c = str[i];
897
if (c < 0) {
898
result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
899
result[ri++] = (char)(0x80 | (c & 0x3f));
900
} else {
901
result[ri++] = c;
902
}
903
}
904
(*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
905
result[rlen] = '\0';
906
return result;
907
}
908
909
JNIEXPORT const char * JNICALL
910
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
911
{
912
913
if (isCopy)
914
*isCopy = JNI_TRUE;
915
916
if (fastEncoding == FAST_UTF_8)
917
return getStringUTF8(env, jstr);
918
if (fastEncoding == FAST_8859_1)
919
return getString8859_1Chars(env, jstr);
920
if (fastEncoding == FAST_646_US)
921
return getString646_USChars(env, jstr);
922
if (fastEncoding == FAST_CP1252)
923
return getStringCp1252Chars(env, jstr);
924
if (fastEncoding == NO_ENCODING_YET) {
925
JNU_ThrowInternalError(env, "platform encoding not initialized");
926
return 0;
927
} else
928
return getStringBytes(env, jstr);
929
}
930
931
JNIEXPORT void JNICALL
932
JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
933
{
934
free((void *)str);
935
}
936
937
JNIEXPORT jclass JNICALL
938
JNU_ClassString(JNIEnv *env)
939
{
940
static jclass cls = 0;
941
if (cls == 0) {
942
jclass c;
943
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
944
return 0;
945
c = (*env)->FindClass(env, "java/lang/String");
946
CHECK_NULL_RETURN(c, NULL);
947
cls = (*env)->NewGlobalRef(env, c);
948
(*env)->DeleteLocalRef(env, c);
949
}
950
return cls;
951
}
952
953
JNIEXPORT jint JNICALL
954
JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
955
jint count)
956
{
957
int i;
958
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
959
return -1;
960
for (i=0; i<count; i++) {
961
jstring p = (*env)->GetObjectArrayElement(env, src, i);
962
(*env)->SetObjectArrayElement(env, dst, i, p);
963
(*env)->DeleteLocalRef(env, p);
964
}
965
return 0;
966
}
967
968
JNIEXPORT void * JNICALL
969
JNU_GetEnv(JavaVM *vm, jint version)
970
{
971
void *env;
972
(*vm)->GetEnv(vm, &env, version);
973
return env;
974
}
975
976
JNIEXPORT jint JNICALL
977
JNU_IsInstanceOfByName(JNIEnv *env, jobject object, const char* classname)
978
{
979
jclass cls;
980
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
981
return JNI_ERR;
982
cls = (*env)->FindClass(env, classname);
983
if (cls != NULL) {
984
jint result = (*env)->IsInstanceOf(env, object, cls);
985
(*env)->DeleteLocalRef(env, cls);
986
return result;
987
}
988
return JNI_ERR;
989
}
990
991
/************************************************************************
992
* Debugging utilities
993
*/
994
995
JNIEXPORT jstring JNICALL
996
JNU_ToString(JNIEnv *env, jobject object)
997
{
998
if (object == NULL) {
999
return (*env)->NewStringUTF(env, "NULL");
1000
} else {
1001
return (jstring)JNU_CallMethodByName(env,
1002
NULL,
1003
object,
1004
"toString",
1005
"()Ljava/lang/String;").l;
1006
}
1007
}
1008
1009
JNIEXPORT jvalue JNICALL
1010
JNU_GetFieldByName(JNIEnv *env,
1011
jboolean *hasException,
1012
jobject obj,
1013
const char *name,
1014
const char *signature)
1015
{
1016
jclass cls;
1017
jfieldID fid;
1018
jvalue result;
1019
1020
result.i = 0;
1021
1022
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1023
goto done2;
1024
1025
cls = (*env)->GetObjectClass(env, obj);
1026
fid = (*env)->GetFieldID(env, cls, name, signature);
1027
if (fid == 0)
1028
goto done1;
1029
1030
switch (*signature) {
1031
case '[':
1032
case 'L':
1033
result.l = (*env)->GetObjectField(env, obj, fid);
1034
break;
1035
case 'Z':
1036
result.z = (*env)->GetBooleanField(env, obj, fid);
1037
break;
1038
case 'B':
1039
result.b = (*env)->GetByteField(env, obj, fid);
1040
break;
1041
case 'C':
1042
result.c = (*env)->GetCharField(env, obj, fid);
1043
break;
1044
case 'S':
1045
result.s = (*env)->GetShortField(env, obj, fid);
1046
break;
1047
case 'I':
1048
result.i = (*env)->GetIntField(env, obj, fid);
1049
break;
1050
case 'J':
1051
result.j = (*env)->GetLongField(env, obj, fid);
1052
break;
1053
case 'F':
1054
result.f = (*env)->GetFloatField(env, obj, fid);
1055
break;
1056
case 'D':
1057
result.d = (*env)->GetDoubleField(env, obj, fid);
1058
break;
1059
1060
default:
1061
(*env)->FatalError(env, "JNU_GetFieldByName: illegal signature");
1062
}
1063
1064
done1:
1065
(*env)->DeleteLocalRef(env, cls);
1066
done2:
1067
if (hasException) {
1068
*hasException = (*env)->ExceptionCheck(env);
1069
}
1070
return result;
1071
}
1072
1073
JNIEXPORT void JNICALL
1074
JNU_SetFieldByName(JNIEnv *env,
1075
jboolean *hasException,
1076
jobject obj,
1077
const char *name,
1078
const char *signature,
1079
...)
1080
{
1081
jclass cls;
1082
jfieldID fid;
1083
va_list args;
1084
1085
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1086
goto done2;
1087
1088
cls = (*env)->GetObjectClass(env, obj);
1089
fid = (*env)->GetFieldID(env, cls, name, signature);
1090
if (fid == 0)
1091
goto done1;
1092
1093
va_start(args, signature);
1094
switch (*signature) {
1095
case '[':
1096
case 'L':
1097
(*env)->SetObjectField(env, obj, fid, va_arg(args, jobject));
1098
break;
1099
case 'Z':
1100
(*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int));
1101
break;
1102
case 'B':
1103
(*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int));
1104
break;
1105
case 'C':
1106
(*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int));
1107
break;
1108
case 'S':
1109
(*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int));
1110
break;
1111
case 'I':
1112
(*env)->SetIntField(env, obj, fid, va_arg(args, jint));
1113
break;
1114
case 'J':
1115
(*env)->SetLongField(env, obj, fid, va_arg(args, jlong));
1116
break;
1117
case 'F':
1118
(*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble));
1119
break;
1120
case 'D':
1121
(*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble));
1122
break;
1123
1124
default:
1125
(*env)->FatalError(env, "JNU_SetFieldByName: illegal signature");
1126
}
1127
va_end(args);
1128
1129
done1:
1130
(*env)->DeleteLocalRef(env, cls);
1131
done2:
1132
if (hasException) {
1133
*hasException = (*env)->ExceptionCheck(env);
1134
}
1135
}
1136
1137
JNIEXPORT jvalue JNICALL
1138
JNU_GetStaticFieldByName(JNIEnv *env,
1139
jboolean *hasException,
1140
const char *classname,
1141
const char *name,
1142
const char *signature)
1143
{
1144
jclass cls;
1145
jfieldID fid;
1146
jvalue result;
1147
1148
result.i = 0;
1149
1150
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1151
goto done2;
1152
1153
cls = (*env)->FindClass(env, classname);
1154
if (cls == 0)
1155
goto done2;
1156
1157
fid = (*env)->GetStaticFieldID(env, cls, name, signature);
1158
if (fid == 0)
1159
goto done1;
1160
1161
switch (*signature) {
1162
case '[':
1163
case 'L':
1164
result.l = (*env)->GetStaticObjectField(env, cls, fid);
1165
break;
1166
case 'Z':
1167
result.z = (*env)->GetStaticBooleanField(env, cls, fid);
1168
break;
1169
case 'B':
1170
result.b = (*env)->GetStaticByteField(env, cls, fid);
1171
break;
1172
case 'C':
1173
result.c = (*env)->GetStaticCharField(env, cls, fid);
1174
break;
1175
case 'S':
1176
result.s = (*env)->GetStaticShortField(env, cls, fid);
1177
break;
1178
case 'I':
1179
result.i = (*env)->GetStaticIntField(env, cls, fid);
1180
break;
1181
case 'J':
1182
result.j = (*env)->GetStaticLongField(env, cls, fid);
1183
break;
1184
case 'F':
1185
result.f = (*env)->GetStaticFloatField(env, cls, fid);
1186
break;
1187
case 'D':
1188
result.d = (*env)->GetStaticDoubleField(env, cls, fid);
1189
break;
1190
1191
default:
1192
(*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature");
1193
}
1194
1195
done1:
1196
(*env)->DeleteLocalRef(env, cls);
1197
done2:
1198
if (hasException) {
1199
*hasException = (*env)->ExceptionCheck(env);
1200
}
1201
return result;
1202
}
1203
1204