|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * The Universal Permissive License (UPL), Version 1.0
|
|
51 | 51 | import com.oracle.graal.python.builtins.PythonBuiltinClassType;
|
52 | 52 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
53 | 53 | import com.oracle.graal.python.builtins.objects.PNone;
|
| 54 | +import com.oracle.graal.python.builtins.objects.array.PArray; |
54 | 55 | import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
|
55 | 56 | import com.oracle.graal.python.builtins.objects.bytes.PBytes;
|
56 | 57 | import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike;
|
57 | 58 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
|
| 59 | +import com.oracle.graal.python.builtins.objects.ints.PInt; |
| 60 | +import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; |
58 | 61 | import com.oracle.graal.python.builtins.objects.module.PythonModule;
|
59 | 62 | import com.oracle.graal.python.builtins.objects.type.PythonClass;
|
60 | 63 | import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
|
| 64 | +import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; |
61 | 65 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
62 | 66 | import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
|
63 | 67 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
|
| 68 | +import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; |
| 69 | +import com.oracle.graal.python.nodes.util.CastToIntegerFromIntNode; |
64 | 70 | import com.oracle.graal.python.runtime.PythonCore;
|
65 | 71 | import com.oracle.graal.python.runtime.exception.PException;
|
| 72 | +import static com.oracle.graal.python.runtime.exception.PythonErrorType.SystemError; |
66 | 73 | import com.oracle.truffle.api.CompilerDirectives;
|
67 | 74 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
68 | 75 | import com.oracle.truffle.api.dsl.Cached;
|
| 76 | +import com.oracle.truffle.api.dsl.Fallback; |
69 | 77 | import com.oracle.truffle.api.dsl.GenerateNodeFactory;
|
70 | 78 | import com.oracle.truffle.api.dsl.NodeFactory;
|
71 | 79 | import com.oracle.truffle.api.dsl.Specialization;
|
| 80 | +import com.oracle.truffle.api.dsl.TypeSystemReference; |
| 81 | +import com.oracle.truffle.api.profiles.ConditionProfile; |
72 | 82 | import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
|
73 | 83 |
|
74 | 84 | @CoreFunctions(defineModule = "binascii")
|
@@ -163,26 +173,124 @@ private ReadAttributeFromObjectNode getAttrNode() {
|
163 | 173 | }
|
164 | 174 |
|
165 | 175 | @Builtin(name = "b2a_base64", fixedNumOfPositionalArgs = 1, keywordArguments = {"newline"})
|
| 176 | + @TypeSystemReference(PythonArithmeticTypes.class) |
166 | 177 | @GenerateNodeFactory
|
167 | 178 | static abstract class B2aBase64Node extends PythonBinaryBuiltinNode {
|
168 |
| - @Specialization(guards = "isNoValue(newline)") |
169 |
| - @TruffleBoundary |
170 |
| - String b2a(PBytes data, @SuppressWarnings("unused") PNone newline, |
171 |
| - @Cached("create()") SequenceStorageNodes.ToByteArrayNode toByteArray) { |
172 |
| - return b2a(data, true, toByteArray); |
| 179 | + |
| 180 | + @Child private SequenceStorageNodes.ToByteArrayNode toByteArray; |
| 181 | + @Child private CastToIntegerFromIntNode castToIntNode; |
| 182 | + @Child private B2aBase64Node recursiveNode; |
| 183 | + |
| 184 | + private SequenceStorageNodes.ToByteArrayNode getToByteArrayNode() { |
| 185 | + if (toByteArray == null) { |
| 186 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 187 | + toByteArray = insert(SequenceStorageNodes.ToByteArrayNode.create()); |
| 188 | + } |
| 189 | + return toByteArray; |
| 190 | + } |
| 191 | + |
| 192 | + private CastToIntegerFromIntNode getCastToIntNode() { |
| 193 | + if (castToIntNode == null) { |
| 194 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 195 | + castToIntNode = insert(CastToIntegerFromIntNode.create(val -> { |
| 196 | + throw raise(PythonBuiltinClassType.TypeError, "an integer is required (got type %p)", val); |
| 197 | + })); |
| 198 | + } |
| 199 | + return castToIntNode; |
| 200 | + } |
| 201 | + |
| 202 | + private B2aBase64Node getRecursiveNode() { |
| 203 | + if (recursiveNode == null) { |
| 204 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 205 | + recursiveNode = insert(BinasciiModuleBuiltinsFactory.B2aBase64NodeFactory.create()); |
| 206 | + } |
| 207 | + return recursiveNode; |
173 | 208 | }
|
174 | 209 |
|
175 |
| - @Specialization |
176 | 210 | @TruffleBoundary
|
177 |
| - String b2a(PBytes data, boolean newline, |
178 |
| - @Cached("create()") SequenceStorageNodes.ToByteArrayNode toByteArray) { |
179 |
| - String encode = Base64.encode(toByteArray.execute(data.getSequenceStorage())); |
| 211 | + private PBytes b2a(byte[] data, boolean newline) { |
| 212 | + String encode = Base64.encode(data); |
180 | 213 | if (newline) {
|
181 |
| - return encode + "\n"; |
182 |
| - } else { |
183 |
| - return encode; |
| 214 | + return factory().createBytes((encode + "\n").getBytes()); |
184 | 215 | }
|
| 216 | + return factory().createBytes((encode).getBytes()); |
| 217 | + } |
| 218 | + |
| 219 | + @Specialization(guards = "isNoValue(newline)") |
| 220 | + PBytes b2aBytesLike(PIBytesLike data, @SuppressWarnings("unused") PNone newline) { |
| 221 | + return b2aBytesLike(data, 1); |
| 222 | + } |
| 223 | + |
| 224 | + @Specialization |
| 225 | + PBytes b2aBytesLike(PIBytesLike data, long newline) { |
| 226 | + return b2a(getToByteArrayNode().execute(data.getSequenceStorage()), newline != 0); |
| 227 | + } |
| 228 | + |
| 229 | + @Specialization |
| 230 | + PBytes b2aBytesLike(PIBytesLike data, PInt newline) { |
| 231 | + return b2a(getToByteArrayNode().execute(data.getSequenceStorage()), !newline.isZero()); |
| 232 | + } |
| 233 | + |
| 234 | + @Specialization |
| 235 | + PBytes b2aBytesLike(PIBytesLike data, Object newline) { |
| 236 | + return (PBytes) getRecursiveNode().execute(data, getCastToIntNode().execute(newline)); |
185 | 237 | }
|
| 238 | + |
| 239 | + @Specialization(guards = "isNoValue(newline)") |
| 240 | + PBytes b2aArray(PArray data, @SuppressWarnings("unused") PNone newline) { |
| 241 | + return b2aArray(data, 1); |
| 242 | + } |
| 243 | + |
| 244 | + @Specialization |
| 245 | + PBytes b2aArray(PArray data, long newline) { |
| 246 | + return b2a(getToByteArrayNode().execute(data.getSequenceStorage()), newline != 0); |
| 247 | + } |
| 248 | + |
| 249 | + @Specialization |
| 250 | + PBytes b2aArray(PArray data, PInt newline) { |
| 251 | + return b2a(getToByteArrayNode().execute(data.getSequenceStorage()), !newline.isZero()); |
| 252 | + } |
| 253 | + |
| 254 | + @Specialization |
| 255 | + PBytes b2aArray(PArray data, Object newline) { |
| 256 | + return (PBytes) getRecursiveNode().execute(data, getCastToIntNode().execute(newline)); |
| 257 | + } |
| 258 | + |
| 259 | + @Specialization(guards = "isNoValue(newline)") |
| 260 | + PBytes b2aMmeory(PMemoryView data, @SuppressWarnings("unused") PNone newline, |
| 261 | + @Cached("create(TOBYTES)") LookupAndCallUnaryNode toBytesNode, |
| 262 | + @Cached("createBinaryProfile()") ConditionProfile isBytesProfile) { |
| 263 | + return b2aMemory(data, 1, toBytesNode, isBytesProfile); |
| 264 | + } |
| 265 | + |
| 266 | + @Specialization |
| 267 | + PBytes b2aMemory(PMemoryView data, long newline, |
| 268 | + @Cached("create(TOBYTES)") LookupAndCallUnaryNode toBytesNode, |
| 269 | + @Cached("createBinaryProfile()") ConditionProfile isBytesProfile) { |
| 270 | + Object bytesObj = toBytesNode.executeObject(data); |
| 271 | + if (isBytesProfile.profile(bytesObj instanceof PBytes)) { |
| 272 | + return b2aBytesLike((PBytes) bytesObj, newline); |
| 273 | + } |
| 274 | + throw raise(SystemError, "could not get bytes of memoryview"); |
| 275 | + } |
| 276 | + |
| 277 | + @Specialization |
| 278 | + PBytes b2aMmeory(PMemoryView data, PInt newline, |
| 279 | + @Cached("create(TOBYTES)") LookupAndCallUnaryNode toBytesNode, |
| 280 | + @Cached("createBinaryProfile()") ConditionProfile isBytesProfile) { |
| 281 | + return b2aMemory(data, newline.isZero() ? 0 : 1, toBytesNode, isBytesProfile); |
| 282 | + } |
| 283 | + |
| 284 | + @Specialization |
| 285 | + PBytes b2aMmeory(PMemoryView data, Object newline) { |
| 286 | + return (PBytes) getRecursiveNode().execute(data, getCastToIntNode().execute(newline)); |
| 287 | + } |
| 288 | + |
| 289 | + @Fallback |
| 290 | + PBytes b2sGeneral(Object data, @SuppressWarnings("unused") Object newline) { |
| 291 | + throw raise(PythonBuiltinClassType.TypeError, "a bytes-like object is required, not '%p'", data); |
| 292 | + } |
| 293 | + |
186 | 294 | }
|
187 | 295 |
|
188 | 296 | @Builtin(name = "b2a_hex", fixedNumOfPositionalArgs = 1)
|
|
0 commit comments