40
40
*/
41
41
package com .oracle .graal .python .builtins .modules ;
42
42
43
+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .BinasciiError ;
43
44
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
44
- import static com .oracle .graal .python .builtins .PythonBuiltinClassType .ValueError ;
45
45
import static com .oracle .graal .python .runtime .exception .PythonErrorType .SystemError ;
46
46
47
+ import java .nio .charset .StandardCharsets ;
48
+ import java .util .Arrays ;
49
+ import java .util .Base64 ;
47
50
import java .util .List ;
48
51
import java .util .zip .CRC32 ;
49
52
53
56
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
54
57
import com .oracle .graal .python .builtins .PythonBuiltins ;
55
58
import com .oracle .graal .python .builtins .objects .PNone ;
56
- import com .oracle .graal .python .builtins .objects .bytes .BytesUtils ;
57
59
import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
58
60
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes ;
59
- import com .oracle .graal .python .builtins .objects .module .PythonModule ;
60
61
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
61
- import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
62
62
import com .oracle .graal .python .nodes .ErrorMessages ;
63
- import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
64
- import com .oracle .graal .python .nodes .call .CallNode ;
65
63
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
66
64
import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
67
65
import com .oracle .graal .python .nodes .function .builtins .PythonClinicBuiltinNode ;
68
66
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
69
67
import com .oracle .graal .python .nodes .function .builtins .clinic .ArgumentClinicProvider ;
70
- import com .oracle .graal .python .nodes .statement .RaiseNode ;
71
- import com .oracle .graal .python .nodes .statement .RaiseNodeGen ;
72
- import com .oracle .graal .python .runtime .PythonCore ;
73
- import com .oracle .graal .python .runtime .exception .PException ;
74
68
import com .oracle .truffle .api .CompilerDirectives ;
75
69
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
76
70
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
81
75
import com .oracle .truffle .api .dsl .Specialization ;
82
76
import com .oracle .truffle .api .interop .UnsupportedMessageException ;
83
77
import com .oracle .truffle .api .library .CachedLibrary ;
84
- import com .sun .org .apache .xerces .internal .impl .dv .util .Base64 ;
85
78
86
79
@ CoreFunctions (defineModule = "binascii" )
87
80
public class BinasciiModuleBuiltins extends PythonBuiltins {
88
- private static final String INCOMPLETE = "Incomplete" ;
89
- private static final String ERROR = "Error" ;
90
81
91
82
@ Override
92
83
protected List <? extends NodeFactory <? extends PythonBuiltinBaseNode >> getNodeFactories () {
93
84
return BinasciiModuleBuiltinsFactory .getFactories ();
94
85
}
95
86
96
- @ Override
97
- public void initialize (PythonCore core ) {
98
- super .initialize (core );
99
- String pre = "binascii." ;
100
- PythonAbstractClass [] errorBases = new PythonAbstractClass []{core .lookupType (PythonBuiltinClassType .ValueError )};
101
- builtinConstants .put (ERROR , core .factory ().createPythonClass (PythonBuiltinClassType .PythonClass , pre + ERROR , errorBases ));
102
- PythonAbstractClass [] incompleteBases = new PythonAbstractClass []{core .lookupType (PythonBuiltinClassType .Exception )};
103
- builtinConstants .put (INCOMPLETE , core .factory ().createPythonClass (PythonBuiltinClassType .PythonClass , pre + INCOMPLETE , incompleteBases ));
104
- }
105
-
106
87
@ Builtin (name = "a2b_base64" , minNumOfPositionalArgs = 1 )
107
88
@ GenerateNodeFactory
108
89
abstract static class A2bBase64Node extends PythonUnaryBuiltinNode {
@@ -122,124 +103,98 @@ PBytes doBuffer(Object data,
122
103
}
123
104
124
105
@ TruffleBoundary
125
- private static byte [] b64decode (String data ) {
126
- return Base64 . decode (data );
106
+ private byte [] b64decode (String data ) {
107
+ return b64decode (data . getBytes ( StandardCharsets . US_ASCII ) );
127
108
}
128
109
129
110
@ TruffleBoundary
130
111
private byte [] b64decode (byte [] data ) {
131
- byte [] asciis = Base64 .decode (BytesUtils .createASCIIString (data ));
132
- if (asciis != null ) {
133
- return asciis ;
112
+ try {
113
+ // Using MIME decoder because that one skips over anything that is not the alphabet,
114
+ // just like CPython does
115
+ return Base64 .getMimeDecoder ().decode (data );
116
+ } catch (IllegalArgumentException e ) {
117
+ throw raise (BinasciiError , e );
134
118
}
135
- throw raise (ValueError );
136
119
}
137
120
}
138
121
139
- @ Builtin (name = "a2b_hex" , minNumOfPositionalArgs = 2 , declaresExplicitSelf = true )
122
+ @ Builtin (name = "a2b_hex" , minNumOfPositionalArgs = 1 )
140
123
@ GenerateNodeFactory
141
- abstract static class A2bHexNode extends PythonBinaryBuiltinNode {
142
- @ Child private ReadAttributeFromObjectNode readAttrNode ;
143
- @ Child private RaiseNode raiseNode ;
144
- @ Child private CallNode callExceptionConstructor ;
124
+ abstract static class A2bHexNode extends PythonUnaryBuiltinNode {
145
125
146
126
@ Specialization
147
127
@ TruffleBoundary
148
- PBytes a2b (PythonModule self , String data ) {
128
+ PBytes a2b (String data ) {
149
129
int length = data .length ();
150
130
if (length % 2 != 0 ) {
151
- throw oddLengthError ( self );
131
+ throw raise ( BinasciiError , ErrorMessages . ODD_LENGTH_STRING );
152
132
}
153
133
byte [] output = new byte [length / 2 ];
154
134
for (int i = 0 ; i < length / 2 ; i ++) {
155
135
try {
156
- output [i ] = (byte ) (digitValue (self , data .charAt (i * 2 )) * 16 + digitValue (self , data .charAt (i * 2 + 1 )));
136
+ output [i ] = (byte ) (digitValue (data .charAt (i * 2 )) * 16 + digitValue (data .charAt (i * 2 + 1 )));
157
137
} catch (NumberFormatException e ) {
158
- throw nonHexError ( self );
138
+ throw raise ( BinasciiError , ErrorMessages . NON_HEX_DIGIT_FOUND );
159
139
}
160
140
}
161
141
return factory ().createBytes (output );
162
142
}
163
143
164
144
@ Specialization (guards = "bufferLib.isBuffer(buffer)" , limit = "2" )
165
- PBytes a2b (PythonModule self , Object buffer ,
145
+ PBytes a2b (Object buffer ,
166
146
@ CachedLibrary ("buffer" ) PythonObjectLibrary bufferLib ) {
167
147
try {
168
- return a2b (self , bufferLib .getBufferBytes (buffer ));
148
+ return a2b (bufferLib .getBufferBytes (buffer ));
169
149
} catch (UnsupportedMessageException e ) {
170
150
throw CompilerDirectives .shouldNotReachHere ();
171
151
}
172
152
}
173
153
174
154
@ TruffleBoundary
175
- private PBytes a2b (PythonModule self , byte [] bytes ) {
155
+ private PBytes a2b (byte [] bytes ) {
176
156
int length = bytes .length ;
177
157
if (length % 2 != 0 ) {
178
- throw oddLengthError ( self );
158
+ throw raise ( BinasciiError , ErrorMessages . ODD_LENGTH_STRING );
179
159
}
180
160
byte [] output = new byte [length / 2 ];
181
161
for (int i = 0 ; i < length / 2 ; i ++) {
182
- output [i ] = (byte ) (digitValue (self , (char ) bytes [i * 2 ]) * 16 + digitValue (self , (char ) bytes [i * 2 + 1 ]));
162
+ output [i ] = (byte ) (digitValue ((char ) bytes [i * 2 ]) * 16 + digitValue ((char ) bytes [i * 2 + 1 ]));
183
163
}
184
164
return factory ().createBytes (output );
185
165
}
186
166
187
- private int digitValue (PythonModule self , char b ) {
167
+ private int digitValue (char b ) {
188
168
if (b >= '0' && b <= '9' ) {
189
169
return b - '0' ;
190
170
} else if (b >= 'a' && b <= 'f' ) {
191
171
return b - 'a' + 10 ;
192
172
} else if (b >= 'A' && b <= 'F' ) {
193
173
return b - 'A' + 10 ;
194
174
} else {
195
- throw nonHexError (self );
196
- }
197
- }
198
-
199
- private PException oddLengthError (PythonModule self ) {
200
- raiseObject (getAttrNode ().execute (self , ERROR ), ErrorMessages .ODD_LENGTH_STRING );
201
- CompilerDirectives .transferToInterpreterAndInvalidate ();
202
- throw new IllegalStateException ("should not be reached" );
203
- }
204
-
205
- private PException nonHexError (PythonModule self ) {
206
- raiseObject (getAttrNode ().execute (self , ERROR ), ErrorMessages .NON_HEX_DIGIT_FOUND );
207
- CompilerDirectives .transferToInterpreterAndInvalidate ();
208
- throw new IllegalStateException ("should not be reached" );
209
- }
210
-
211
- private ReadAttributeFromObjectNode getAttrNode () {
212
- if (readAttrNode == null ) {
213
- CompilerDirectives .transferToInterpreterAndInvalidate ();
214
- readAttrNode = insert (ReadAttributeFromObjectNode .create ());
175
+ throw raise (BinasciiError , ErrorMessages .NON_HEX_DIGIT_FOUND );
215
176
}
216
- return readAttrNode ;
217
177
}
218
178
219
- private void raiseObject (Object exceptionObject , String message ) {
220
- if (callExceptionConstructor == null ) {
221
- CompilerDirectives .transferToInterpreterAndInvalidate ();
222
- callExceptionConstructor = insert (CallNode .create ());
223
- }
224
- if (raiseNode == null ) {
225
- CompilerDirectives .transferToInterpreterAndInvalidate ();
226
- raiseNode = insert (RaiseNodeGen .create (null , null ));
227
- }
228
- raiseNode .execute (callExceptionConstructor .execute (exceptionObject , message ), PNone .NO_VALUE );
229
- }
230
179
}
231
180
232
181
@ Builtin (name = "b2a_base64" , minNumOfPositionalArgs = 1 , numOfPositionalOnlyArgs = 1 , parameterNames = {"data" }, keywordOnlyNames = {"newline" })
233
182
@ ArgumentClinic (name = "newline" , conversion = ArgumentClinic .ClinicConversion .Int , defaultValue = "1" , useDefaultForNone = true )
234
183
@ GenerateNodeFactory
235
184
abstract static class B2aBase64Node extends PythonClinicBuiltinNode {
236
185
@ TruffleBoundary
237
- private static byte [] b2a (byte [] data , int newline ) {
238
- String encode = Base64 .encode (data );
186
+ private byte [] b2a (byte [] data , int newline ) {
187
+ byte [] encoded ;
188
+ try {
189
+ encoded = Base64 .getEncoder ().encode (data );
190
+ } catch (IllegalArgumentException e ) {
191
+ throw raise (BinasciiError , e );
192
+ }
239
193
if (newline != 0 ) {
240
- return (encode + "\n " ).getBytes ();
194
+ encoded = Arrays .copyOf (encoded , encoded .length + 1 );
195
+ encoded [encoded .length - 1 ] = '\n' ;
241
196
}
242
- return encode . getBytes () ;
197
+ return encoded ;
243
198
}
244
199
245
200
@ Specialization (guards = "bufferLib.isBuffer(data)" , limit = "3" )
@@ -318,7 +273,7 @@ private static long getCrcValue(byte[] bytes) {
318
273
abstract static class HexlifyNode extends B2aHexNode {
319
274
}
320
275
321
- @ Builtin (name = "unhexlify" , minNumOfPositionalArgs = 2 , declaresExplicitSelf = true )
276
+ @ Builtin (name = "unhexlify" , minNumOfPositionalArgs = 1 )
322
277
@ GenerateNodeFactory
323
278
abstract static class UnhexlifyNode extends A2bHexNode {
324
279
}
0 commit comments