49
49
import java .io .PrintWriter ;
50
50
import java .math .BigInteger ;
51
51
import java .nio .ByteBuffer ;
52
- import java .nio .ByteOrder ;
53
52
import java .nio .CharBuffer ;
54
53
import java .nio .charset .CharacterCodingException ;
55
54
import java .nio .charset .Charset ;
110
109
import com .oracle .graal .python .builtins .objects .cext .PythonNativeWrapperLibrary ;
111
110
import com .oracle .graal .python .builtins .objects .cext .UnicodeObjectNodes .UnicodeAsWideCharNode ;
112
111
import com .oracle .graal .python .builtins .objects .cext .common .CExtAsPythonObjectNode ;
112
+ import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .Charsets ;
113
113
import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .EncodeNativeStringNode ;
114
114
import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .PCallCExtFunction ;
115
+ import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .UnicodeFromWcharNode ;
115
116
import com .oracle .graal .python .builtins .objects .cext .common .CExtContext ;
116
117
import com .oracle .graal .python .builtins .objects .cext .common .CExtParseArgumentsNode ;
117
118
import com .oracle .graal .python .builtins .objects .cext .common .VaListWrapper ;
137
138
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
138
139
import com .oracle .graal .python .builtins .objects .set .PBaseSet ;
139
140
import com .oracle .graal .python .builtins .objects .str .PString ;
140
- import com .oracle .graal .python .builtins .objects .str .StringNodesFactory .StringLenNodeGen ;
141
141
import com .oracle .graal .python .builtins .objects .traceback .PTraceback ;
142
142
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
143
143
import com .oracle .graal .python .builtins .objects .type .LazyPythonClass ;
190
190
import com .oracle .graal .python .runtime .ExecutionContext .IndirectCallContext ;
191
191
import com .oracle .graal .python .runtime .PythonContext ;
192
192
import com .oracle .graal .python .runtime .PythonCore ;
193
- import com .oracle .graal .python .runtime .PythonOptions ;
194
193
import com .oracle .graal .python .runtime .exception .ExceptionUtils ;
195
194
import com .oracle .graal .python .runtime .exception .PException ;
196
195
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
200
199
import com .oracle .graal .python .runtime .sequence .storage .MroSequenceStorage ;
201
200
import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
202
201
import com .oracle .truffle .api .Assumption ;
203
- import com .oracle .truffle .api .CompilerAsserts ;
204
202
import com .oracle .truffle .api .CompilerDirectives ;
205
203
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
206
204
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
228
226
import com .oracle .truffle .api .interop .UnsupportedMessageException ;
229
227
import com .oracle .truffle .api .interop .UnsupportedTypeException ;
230
228
import com .oracle .truffle .api .library .CachedLibrary ;
231
- import com .oracle .truffle .api .nodes .ExplodeLoop ;
232
- import com .oracle .truffle .api .nodes .ExplodeLoop .LoopExplosionKind ;
233
229
import com .oracle .truffle .api .nodes .Node ;
234
230
import com .oracle .truffle .api .nodes .NodeVisitor ;
235
231
import com .oracle .truffle .api .nodes .RootNode ;
@@ -961,43 +957,6 @@ private PRaiseNativeNode ensureRaiseNativeNode() {
961
957
}
962
958
963
959
abstract static class NativeUnicodeBuiltin extends NativeBuiltin {
964
- private static final int NATIVE_ORDER = 0 ;
965
- private static Charset UTF32 ;
966
- private static Charset UTF32LE ;
967
- private static Charset UTF32BE ;
968
-
969
- @ TruffleBoundary
970
- protected static Charset getUTF32Charset (int byteorder ) {
971
- String utf32Name = getUTF32Name (byteorder );
972
- if (byteorder == NativeUnicodeBuiltin .NATIVE_ORDER ) {
973
- if (UTF32 == null ) {
974
- UTF32 = Charset .forName (utf32Name );
975
- }
976
- return UTF32 ;
977
- } else if (byteorder < NativeUnicodeBuiltin .NATIVE_ORDER ) {
978
- if (UTF32LE == null ) {
979
- UTF32LE = Charset .forName (utf32Name );
980
- }
981
- return UTF32LE ;
982
- }
983
- if (UTF32BE == null ) {
984
- UTF32BE = Charset .forName (utf32Name );
985
- }
986
- return UTF32BE ;
987
- }
988
-
989
- protected static String getUTF32Name (int byteorder ) {
990
- String csName ;
991
- if (byteorder == 0 ) {
992
- csName = "UTF-32" ;
993
- } else if (byteorder < 0 ) {
994
- csName = "UTF-32LE" ;
995
- } else {
996
- csName = "UTF-32BE" ;
997
- }
998
- return csName ;
999
- }
1000
-
1001
960
@ TruffleBoundary
1002
961
protected static CharBuffer allocateCharBuffer (int cap ) {
1003
962
return CharBuffer .allocate (cap );
@@ -1012,7 +971,6 @@ protected static String toString(CharBuffer cb) {
1012
971
protected static int remaining (ByteBuffer cb ) {
1013
972
return cb .remaining ();
1014
973
}
1015
-
1016
974
}
1017
975
1018
976
@ Builtin (name = "TrufflePInt_AsPrimitive" , minNumOfPositionalArgs = 3 )
@@ -1130,109 +1088,17 @@ private PRaiseNativeNode ensureRaiseNativeNode() {
1130
1088
1131
1089
@ Builtin (name = "PyTruffle_Unicode_FromWchar" , minNumOfPositionalArgs = 4 )
1132
1090
@ GenerateNodeFactory
1133
- @ TypeSystemReference (PythonArithmeticTypes .class )
1134
- @ ImportStatic (PythonOptions .class )
1135
1091
abstract static class PyTruffle_Unicode_FromWchar extends NativeUnicodeBuiltin {
1136
- @ Specialization (guards = "elementSize == cachedElementSize" , limit = "getVariableArgumentInlineCacheLimit()" )
1137
- Object doBytes (VirtualFrame frame , Object arr , long n , long elementSize , Object errorMarker ,
1138
- @ Cached CExtNodes .ToSulongNode toSulongNode ,
1139
- @ Cached ("elementSize" ) long cachedElementSize ,
1140
- @ CachedLibrary ("arr" ) InteropLibrary lib ,
1141
- @ CachedLibrary (limit = "1" ) InteropLibrary elemLib ) {
1142
- try {
1143
- ByteBuffer bytes ;
1144
- if (cachedElementSize == 1L || cachedElementSize == 2L || cachedElementSize == 4L ) {
1145
- if (!lib .hasArrayElements (arr )) {
1146
- return raiseNative (frame , errorMarker , PythonErrorType .SystemError , "provided object is not an array" , elementSize );
1147
- }
1148
- bytes = readWithSize (lib , elemLib , arr , PInt .intValueExact (n ), (int ) cachedElementSize );
1149
- bytes .flip ();
1150
- } else {
1151
- return raiseNative (frame , errorMarker , PythonErrorType .ValueError , "unsupported 'wchar_t' size; was: %d" , elementSize );
1152
- }
1153
- return toSulongNode .execute (decode (bytes ));
1154
- } catch (ArithmeticException e ) {
1155
- return raiseNative (frame , errorMarker , PythonErrorType .ValueError , "array size too large" );
1156
- } catch (CharacterCodingException e ) {
1157
- return raiseNative (frame , errorMarker , PythonErrorType .UnicodeError , "%m" , e );
1158
- } catch (IllegalArgumentException e ) {
1159
- return raiseNative (frame , errorMarker , PythonErrorType .LookupError , "%m" , e );
1160
- } catch (InteropException e ) {
1161
- return raiseNative (frame , errorMarker , PythonErrorType .TypeError , "%m" , e );
1162
- } catch (IllegalElementTypeException e ) {
1163
- return raiseNative (frame , errorMarker , PythonErrorType .UnicodeDecodeError , "Invalid input element type '%p'" , e .elem );
1164
- }
1165
- }
1166
-
1167
- @ Specialization (limit = "getVariableArgumentInlineCacheLimit()" )
1168
- Object doBytes (VirtualFrame frame , Object arr , PInt n , PInt elementSize , Object errorMarker ,
1092
+ @ Specialization
1093
+ static Object doBytes (VirtualFrame frame , Object arr , long n , long elementSize , Object errorMarker ,
1094
+ @ Cached UnicodeFromWcharNode unicodeFromWcharNode ,
1169
1095
@ Cached CExtNodes .ToSulongNode toSulongNode ,
1170
- @ CachedLibrary ("arr" ) InteropLibrary lib ,
1171
- @ CachedLibrary (limit = "1" ) InteropLibrary elemLib ) {
1096
+ @ Cached TransformExceptionToNativeNode transformExceptionToNativeNode ) {
1172
1097
try {
1173
- long es = elementSize .longValueExact ();
1174
- return doBytes (frame , arr , n .longValueExact (), es , errorMarker , toSulongNode , es , lib , elemLib );
1175
- } catch (ArithmeticException e ) {
1176
- return raiseNative (frame , errorMarker , PythonErrorType .ValueError , "invalid parameters" );
1177
- }
1178
- }
1179
-
1180
- @ TruffleBoundary
1181
- private static String decode (ByteBuffer bytes ) throws CharacterCodingException {
1182
- return getUTF32Charset (0 ).newDecoder ().decode (bytes ).toString ();
1183
- }
1184
-
1185
- private static ByteBuffer readWithSize (InteropLibrary arrLib , InteropLibrary elemLib , Object o , int size , int elementSize )
1186
- throws UnsupportedMessageException , InvalidArrayIndexException , IllegalElementTypeException {
1187
- ByteBuffer buf = allocate (size * Integer .BYTES );
1188
- for (int i = 0 ; i < size ; i += elementSize ) {
1189
- putInt (buf , readElement (arrLib , elemLib , o , i , elementSize ));
1190
- }
1191
- return buf ;
1192
- }
1193
-
1194
- @ ExplodeLoop (kind = LoopExplosionKind .FULL_EXPLODE_UNTIL_RETURN )
1195
- private static int readElement (InteropLibrary arrLib , InteropLibrary elemLib , Object arr , int i , int elementSize )
1196
- throws InvalidArrayIndexException , UnsupportedMessageException , IllegalElementTypeException {
1197
- byte [] barr = new byte [4 ];
1198
- CompilerAsserts .partialEvaluationConstant (elementSize );
1199
- for (int j = 0 ; j < elementSize ; j ++) {
1200
- Object elem = arrLib .readArrayElement (arr , i + j );
1201
- // The array object could be one of our wrappers (e.g. 'PySequenceArrayWrapper').
1202
- // Since the Interop library does not allow to specify how many bytes we want to
1203
- // read when we do readArrayElement, our wrappers always return long. So, we check
1204
- // for 'long' here and cast down to 'byte'.
1205
- if (elemLib .fitsInLong (elem )) {
1206
- barr [j ] = (byte ) elemLib .asLong (elem );
1207
- } else {
1208
- CompilerDirectives .transferToInterpreter ();
1209
- throw new IllegalElementTypeException (elem );
1210
- }
1211
- }
1212
- return toInt (barr );
1213
- }
1214
-
1215
- @ TruffleBoundary (allowInlining = true )
1216
- private static int toInt (byte [] barr ) {
1217
- return ByteBuffer .wrap (barr ).order (ByteOrder .LITTLE_ENDIAN ).getInt ();
1218
- }
1219
-
1220
- @ TruffleBoundary (allowInlining = true )
1221
- private static ByteBuffer allocate (int cap ) {
1222
- return ByteBuffer .allocate (cap );
1223
- }
1224
-
1225
- @ TruffleBoundary (allowInlining = true )
1226
- private static void putInt (ByteBuffer buf , int element ) {
1227
- buf .putInt (element );
1228
- }
1229
-
1230
- private static final class IllegalElementTypeException extends Exception {
1231
- private static final long serialVersionUID = 0L ;
1232
- private final Object elem ;
1233
-
1234
- IllegalElementTypeException (Object elem ) {
1235
- this .elem = elem ;
1098
+ return toSulongNode .execute (unicodeFromWcharNode .execute (arr , n , elementSize ));
1099
+ } catch (PException e ) {
1100
+ transformExceptionToNativeNode .execute (frame , e );
1101
+ return errorMarker ;
1236
1102
}
1237
1103
}
1238
1104
}
@@ -1288,20 +1154,6 @@ Object doUnicode(VirtualFrame frame, PString s, String errors, Object error_mark
1288
1154
Object doUnicode (VirtualFrame frame , @ SuppressWarnings ("unused" ) Object s , @ SuppressWarnings ("unused" ) Object errors , Object errorMarker ) {
1289
1155
return raiseBadArgument (frame , errorMarker );
1290
1156
}
1291
-
1292
- @ TruffleBoundary (transferToInterpreterOnException = false )
1293
- private byte [] doEncode (PString s , String errors ) throws CharacterCodingException {
1294
- CharsetEncoder encoder = charset .newEncoder ();
1295
- CodingErrorAction action = BytesBuiltins .toCodingErrorAction (errors , this );
1296
- encoder .onMalformedInput (action ).onUnmappableCharacter (action );
1297
- CharBuffer buf = CharBuffer .allocate (StringLenNodeGen .getUncached ().execute (s ));
1298
- buf .put (s .getValue ());
1299
- buf .flip ();
1300
- ByteBuffer encoded = encoder .encode (buf );
1301
- byte [] barr = new byte [encoded .remaining ()];
1302
- encoded .get (barr );
1303
- return barr ;
1304
- }
1305
1157
}
1306
1158
1307
1159
@ Builtin (name = "_PyUnicode_AsUTF8String" , minNumOfPositionalArgs = 3 )
@@ -1365,7 +1217,7 @@ Object doUnicode(VirtualFrame frame, TruffleObject o, long size, String errors,
1365
1217
} catch (CharacterCodingException e ) {
1366
1218
return raiseNative (frame , errorMarker , PythonErrorType .UnicodeEncodeError , "%m" , e );
1367
1219
} catch (IllegalArgumentException e ) {
1368
- String csName = getUTF32Name (byteorder );
1220
+ String csName = Charsets . getUTF32Name (byteorder );
1369
1221
return raiseNative (frame , errorMarker , PythonErrorType .LookupError , "unknown encoding: " + csName );
1370
1222
} catch (InteropException e ) {
1371
1223
return raiseNative (frame , errorMarker , PythonErrorType .TypeError , "%m" , e );
@@ -1374,7 +1226,7 @@ Object doUnicode(VirtualFrame frame, TruffleObject o, long size, String errors,
1374
1226
1375
1227
@ TruffleBoundary
1376
1228
private String decodeUTF32 (byte [] data , int size , String errors , int byteorder ) throws CharacterCodingException {
1377
- CharsetDecoder decoder = getUTF32Charset (byteorder ).newDecoder ();
1229
+ CharsetDecoder decoder = Charsets . getUTF32Charset (byteorder ).newDecoder ();
1378
1230
CodingErrorAction action = BytesBuiltins .toCodingErrorAction (errors , this );
1379
1231
CharBuffer decode = decoder .onMalformedInput (action ).onUnmappableCharacter (action ).decode (wrap (data , 0 , size ));
1380
1232
return decode .toString ();
0 commit comments