Skip to content

Commit 7510fd6

Browse files
committed
basic implementation of format 'es'/'et'
1 parent 51db451 commit 7510fd6

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ const char* PyTruffle_StringToCstr(void* o, int32_t strLen) {
487487

488488
written = polyglot_as_string(o, buffer, bufsize, SRC_CS) + 1;
489489

490-
str = (const char*) malloc(written * sizeof(char));
490+
str = (const char*) PyMem_RawMalloc(written * sizeof(char));
491491
memcpy(str, buffer, written * sizeof(char));
492492
free(buffer);
493493

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
import com.oracle.graal.python.builtins.modules.PythonCextBuiltins;
6262
import com.oracle.graal.python.builtins.objects.PNone;
6363
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
64+
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
65+
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
6466
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
6567
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
6668
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
@@ -1477,10 +1479,26 @@ Object doString(String str,
14771479
return callStringToCstrNode.call(FUN_PY_TRUFFLE_STRING_TO_CSTR, str, str.length());
14781480
}
14791481

1482+
@Specialization
1483+
Object doBytes(PBytes bytes,
1484+
@CachedContext(PythonLanguage.class) PythonContext context,
1485+
@Shared("toBytes") @Cached SequenceStorageNodes.ToByteArrayNode toBytesNode,
1486+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
1487+
return doByteArray(toBytesNode.execute(bytes.getSequenceStorage()), context, callByteArrayToNativeNode);
1488+
}
1489+
1490+
@Specialization
1491+
Object doBytes(PByteArray bytes,
1492+
@CachedContext(PythonLanguage.class) PythonContext context,
1493+
@Shared("toBytes") @Cached SequenceStorageNodes.ToByteArrayNode toBytesNode,
1494+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
1495+
return doByteArray(toBytesNode.execute(bytes.getSequenceStorage()), context, callByteArrayToNativeNode);
1496+
}
1497+
14801498
@Specialization
14811499
Object doByteArray(byte[] arr,
14821500
@CachedContext(PythonLanguage.class) PythonContext context,
1483-
@Exclusive @Cached PCallCapiFunction callByteArrayToNativeNode) {
1501+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
14841502
return callByteArrayToNativeNode.call(FUN_PY_TRUFFLE_BYTE_ARRAY_TO_NATIVE, context.getEnv().asGuestValue(arr), arr.length);
14851503
}
14861504

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/common/CExtParseArgumentsNode.java

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ private static void doParsingExploded(String funName, PTuple argv, Object kwds,
197197

198198
private static ParserState convertArg(ParserState state, Object kwds, char[] format, int format_idx, Object kwdnames, Object varargs, ConvertArgNode convertArgNode,
199199
PRaiseNativeNode raiseNode) throws InteropException, ParseArgumentsException {
200+
if (state.skip) {
201+
return state.skipped();
202+
}
200203
char c = format[format_idx];
201204
switch (c) {
202205
case FORMAT_LOWER_S:
@@ -300,42 +303,52 @@ static char[] getChars(String format) {
300303
static final class ParserState {
301304
private final String funName;
302305
private final int outIndex;
306+
private final boolean skip; // skip the next format char
303307
private final boolean restOptional;
304308
private final boolean restKeywordsOnly;
305309
private final PositionalArgStack v;
306310
private final CExtContext nativeContext;
307311

308312
ParserState(String funName, PositionalArgStack v, CExtContext nativeContext) {
309-
this(funName, 0, false, false, v, nativeContext);
313+
this(funName, 0, false, false, false, v, nativeContext);
310314
}
311315

312-
private ParserState(String funName, int outIndex, boolean restOptional, boolean restKeywordsOnly, PositionalArgStack v, CExtContext nativeContext) {
316+
private ParserState(String funName, int outIndex, boolean skip, boolean restOptional, boolean restKeywordsOnly, PositionalArgStack v, CExtContext nativeContext) {
313317
this.funName = funName;
314318
this.outIndex = outIndex;
319+
this.skip = skip;
315320
this.restOptional = restOptional;
316321
this.restKeywordsOnly = restKeywordsOnly;
317322
this.v = v;
318323
this.nativeContext = nativeContext;
319324
}
320325

321326
ParserState incrementOutIndex() {
322-
return new ParserState(funName, outIndex + 1, restOptional, restKeywordsOnly, v, nativeContext);
327+
return new ParserState(funName, outIndex + 1, false, restOptional, restKeywordsOnly, v, nativeContext);
323328
}
324329

325330
ParserState restOptional() {
326-
return new ParserState(funName, outIndex, true, restKeywordsOnly, v, nativeContext);
331+
return new ParserState(funName, outIndex, false, true, restKeywordsOnly, v, nativeContext);
327332
}
328333

329334
ParserState restKeywordsOnly() {
330-
return new ParserState(funName, outIndex, restOptional, true, v, nativeContext);
335+
return new ParserState(funName, outIndex, false, restOptional, true, v, nativeContext);
331336
}
332337

333338
ParserState open(PositionalArgStack nestedArgs) {
334-
return new ParserState(funName, outIndex, restOptional, false, nestedArgs, nativeContext);
339+
return new ParserState(funName, outIndex, false, restOptional, false, nestedArgs, nativeContext);
340+
}
341+
342+
ParserState skip() {
343+
return new ParserState(funName, outIndex, true, restOptional, restKeywordsOnly, v, nativeContext);
344+
}
345+
346+
ParserState skipped() {
347+
return new ParserState(funName, outIndex, false, restOptional, restKeywordsOnly, v, nativeContext);
335348
}
336349

337350
ParserState close() {
338-
return new ParserState(funName, outIndex, restOptional, false, v.prev, nativeContext);
351+
return new ParserState(funName, outIndex, false, restOptional, false, v.prev, nativeContext);
339352
}
340353

341354
}
@@ -514,17 +527,39 @@ static ParserState doUnicode(ParserState state, Object kwds, @SuppressWarnings("
514527
return state.incrementOutIndex();
515528
}
516529

530+
@SuppressWarnings("unused")
517531
@Specialization(guards = "c == FORMAT_LOWER_E")
518-
static ParserState doEncodedString(ParserState state, Object kwds, @SuppressWarnings("unused") char c, @SuppressWarnings("unused") char[] format, @SuppressWarnings("unused") int format_idx,
532+
static ParserState doEncodedString(ParserState stateIn, Object kwds, @SuppressWarnings("unused") char c, @SuppressWarnings("unused") char[] format, @SuppressWarnings("unused") int format_idx,
519533
Object kwdnames, @SuppressWarnings("unused") Object varargs,
534+
@Cached AsCharPointerNode asCharPointerNode,
535+
@Cached GetVaArgsNode getVaArgNode,
536+
@Cached(value = "createTJ(stateIn)", uncached = "getUncachedTJ(stateIn)") CExtToJavaNode argToJavaNode,
537+
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
520538
@Shared("getArgNode") @Cached GetArgNode getArgNode,
539+
@Shared("writeOutVarNode") @Cached WriteOutVarNode writeOutVarNode,
521540
@Shared("raiseNode") @Cached PRaiseNativeNode raiseNode) throws InteropException, ParseArgumentsException {
522-
541+
ParserState state = stateIn;
523542
Object arg = getArgNode.execute(state, kwds, kwdnames, state.restKeywordsOnly);
524543
if (!skipOptionalArg(arg, state.restOptional)) {
525-
throw raise(raiseNode, TypeError, ErrorMessages.ESTAR_FORMAT_SPECIFIERS_NOT_ALLOWED, arg);
544+
Object encoding = getVaArgNode.getCharPtr(varargs, state.outIndex);
545+
state = state.incrementOutIndex();
546+
final boolean recodeStrings;
547+
if (isLookahead(format, format_idx, 's')) {
548+
recodeStrings = true;
549+
} else if (isLookahead(format, format_idx, 't')) {
550+
recodeStrings = false;
551+
} else {
552+
throw raise(raiseNode, TypeError, ErrorMessages.ESTAR_FORMAT_SPECIFIERS_NOT_ALLOWED, arg);
553+
}
554+
// XXX: TODO: actual support for the en-/re-coding of objects, proper error handling
555+
writeOutVarNode.writePyObject(varargs, state.outIndex, asCharPointerNode.execute(arg));
556+
if (isLookahead(format, format_idx + 1, '#')) {
557+
final int size = lib.length(argToJavaNode.execute(state.nativeContext, arg));
558+
state = state.incrementOutIndex();
559+
writeOutVarNode.writeInt64(varargs, state.outIndex, size);
560+
}
526561
}
527-
return state;
562+
return state.incrementOutIndex().skip(); // e is always followed by 's' or 't', which me must skip
528563
}
529564

530565
@Specialization(guards = "c == FORMAT_LOWER_B")

0 commit comments

Comments
 (0)