@@ -80,6 +80,8 @@ static JNIEnv* jniEnv;
80
80
UPCALL(NumberCheck, SIG_HPY, SIG_INT) \
81
81
UPCALL(Length, SIG_HPY, SIG_SIZE_T) \
82
82
UPCALL(ListCheck, SIG_HPY, SIG_INT) \
83
+ UPCALL(UnicodeFromWideChar, SIG_PTR SIG_SIZE_T, SIG_HPY) \
84
+ UPCALL(UnicodeFromJCharArray, SIG_JCHARARRAY, SIG_HPY) \
83
85
84
86
#define UPCALL (name , jniSigArgs , jniSigRet ) static jmethodID jniMethod_ ## name;
85
87
ALL_UPCALLS
@@ -164,6 +166,10 @@ static HPy ctx_TypeGenericNew_jni(HPyContext ctx, HPy type, _HPyPtr args, HPy_ss
164
166
return DO_UPCALL_HPY (CONTEXT_INSTANCE (ctx ), TypeGenericNew , HPY_UP (type ));
165
167
}
166
168
169
+ static HPy ctx_Unicode_FromWideChar_jni (HPyContext ctx , const wchar_t * arr , HPy_ssize_t idx ) {
170
+ return DO_UPCALL_HPY (CONTEXT_INSTANCE (ctx ), UnicodeFromWideChar , (PTR_UP ) arr , (SIZE_T_UP ) idx );
171
+ }
172
+
167
173
//*************************
168
174
// BOXING
169
175
@@ -234,7 +240,7 @@ static HPy (*original_LongFromLong)(HPyContext ctx, long l);
234
240
static int (* original_ListCheck )(HPyContext ctx , HPy h );
235
241
static int (* original_NumberCheck )(HPyContext ctx , HPy h );
236
242
static void (* original_Close )(HPyContext ctx , HPy h );
237
- static void * ( * original_TrackerNew )(HPyContext ctx , HPy_ssize_t size );
243
+ static HPy ( * original_UnicodeFromWideChar )(HPyContext ctx , const wchar_t * arr , HPy_ssize_t size );
238
244
239
245
static void * augment_Cast (HPyContext ctx , HPy h ) {
240
246
uint64_t bits = toBits (h );
@@ -313,6 +319,80 @@ static int augment_ListCheck(HPyContext ctx, HPy obj) {
313
319
}
314
320
}
315
321
322
+
323
+ static HPy augment_UnicodeFromWideChar (HPyContext ctx , const wchar_t * u , HPy_ssize_t size ) {
324
+ if (u == NULL && size != 0 ) {
325
+ return HPy_NULL ;
326
+ }
327
+
328
+ if (size == -1 ) {
329
+ size = wcslen (u );
330
+ }
331
+
332
+ if (size > INT32_MAX ) {
333
+ /* TODO(fa): error message */
334
+ return HPy_NULL ;
335
+ }
336
+
337
+ /* If the Unicode data is known at construction time, we can apply
338
+ some optimizations which share commonly used objects. */
339
+
340
+ /* Optimization for empty strings */
341
+ /* TODO(fa)
342
+ if (size == 0)
343
+ _Py_RETURN_UNICODE_EMPTY();
344
+ */
345
+
346
+ /* Single character Unicode objects in the Latin-1 range are
347
+ shared when using this constructor */
348
+ /* TODO(fa)
349
+ if (size == 1 && (Py_UCS4)*u < 256)
350
+ return get_latin1_char((unsigned char)*u);
351
+ */
352
+
353
+ /* If not empty and not single character, copy the Unicode data
354
+ into the new object */
355
+ uint32_t maxchar = 0 ;
356
+ wchar_t ch ;
357
+ for (HPy_ssize_t i = 0 ; i < size ; i ++ ) {
358
+ #if SIZEOF_WCHAR_T == 2
359
+ if (Py_UNICODE_IS_HIGH_SURROGATE (iter [0 ])
360
+ && (iter + 1 ) < end
361
+ && Py_UNICODE_IS_LOW_SURROGATE (iter [1 ]))
362
+ {
363
+ ch = Py_UNICODE_JOIN_SURROGATES (iter [0 ], iter [1 ]);
364
+ ++ (* num_surrogates );
365
+ iter += 2 ;
366
+ }
367
+ else
368
+ #endif
369
+ ch = u [i ];
370
+ if (ch > maxchar ) {
371
+ maxchar = ch ;
372
+ /* TODO(fa): error
373
+ if (*maxchar > MAX_UNICODE) {
374
+ PyErr_Format(PyExc_ValueError,
375
+ "character U+%x is not in range [U+0000; U+10ffff]",
376
+ ch);
377
+ return -1;
378
+ }
379
+ */
380
+ }
381
+ }
382
+
383
+ if (maxchar < 65536 ) {
384
+ jarray jCharArray = (* jniEnv )-> NewCharArray (jniEnv , (jsize ) size );
385
+ jchar * content = (* jniEnv )-> GetPrimitiveArrayCritical (jniEnv , jCharArray , 0 );
386
+ for (HPy_ssize_t i = 0 ; i < size ; i ++ ) {
387
+ content [i ] = (jchar ) u [i ];
388
+ }
389
+ (* jniEnv )-> ReleasePrimitiveArrayCritical (jniEnv , jCharArray , content , 0 );
390
+ return DO_UPCALL_HPY (CONTEXT_INSTANCE (ctx ), UnicodeFromJCharArray , jCharArray );
391
+ } else {
392
+ return original_UnicodeFromWideChar (ctx , u , size );
393
+ }
394
+ }
395
+
316
396
void initDirectFastPaths (HPyContext context ) {
317
397
LOG ("%p" , context );
318
398
context -> name = "augmented!" ;
@@ -343,6 +423,9 @@ void initDirectFastPaths(HPyContext context) {
343
423
344
424
original_ListCheck = context -> ctx_List_Check ;
345
425
context -> ctx_List_Check = augment_ListCheck ;
426
+
427
+ original_UnicodeFromWideChar = context -> ctx_Unicode_FromWideChar ;
428
+ context -> ctx_Unicode_FromWideChar = augment_UnicodeFromWideChar ;
346
429
}
347
430
348
431
void setHPyContextNativeSpace (HPyContext context , void * * nativeSpace ) {
@@ -381,6 +464,8 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
381
464
context -> ctx_SetItem_i = ctx_SetItemi_jni ;
382
465
context -> ctx_SetItem = ctx_SetItem_jni ;
383
466
467
+ context -> ctx_Unicode_FromWideChar = ctx_Unicode_FromWideChar_jni ;
468
+
384
469
context -> ctx_Tracker_New = ctx_Tracker_New ;
385
470
context -> ctx_Tracker_Add = ctx_Tracker_Add ;
386
471
context -> ctx_Tracker_ForgetAll = ctx_Tracker_ForgetAll ;
@@ -397,6 +482,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
397
482
#define SIG_LONG "J"
398
483
#define SIG_DOUBLE "D"
399
484
#define SIG_TRACKER "J"
485
+ #define SIG_JCHARARRAY "[C"
400
486
401
487
#define UPCALL (name , jniSigArgs , jniSigRet ) \
402
488
jniMethod_ ## name = (*env)->GetMethodID(env, clazz, "ctx" #name, "(" jniSigArgs ")" jniSigRet); \
0 commit comments