Skip to content

Commit 902c732

Browse files
committed
Implement interop buffer API for CStringWrapper
1 parent c865a11 commit 902c732

File tree

1 file changed

+100
-11
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/common

1 file changed

+100
-11
lines changed

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

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -62,6 +62,8 @@
6262
import com.oracle.truffle.api.interop.InteropLibrary;
6363
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
6464
import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
65+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
66+
import com.oracle.truffle.api.library.CachedLibrary;
6567
import com.oracle.truffle.api.library.ExportLibrary;
6668
import com.oracle.truffle.api.library.ExportMessage;
6769
import com.oracle.truffle.api.nodes.Node;
@@ -173,19 +175,24 @@ public void free() {
173175
* wrapper let's a TruffleString look like a {@code char*}.
174176
*/
175177
@ExportLibrary(InteropLibrary.class)
178+
@SuppressWarnings("truffle-abstract-export")
176179
public static final class CStringWrapper extends CArrayWrapper {
177180

178181
public CStringWrapper(TruffleString delegate) {
179182
super(delegate);
180183
}
181184

182185
public TruffleString getString() {
183-
return ((TruffleString) getDelegate());
186+
TruffleString s = (TruffleString) getDelegate();
187+
// TODO GR-37217: use sys.getdefaultencoding if the string contains non-latin1
188+
// codepoints
189+
assert s.getCodeRangeUncached(TS_ENCODING) == TruffleString.CodeRange.ASCII;
190+
return s;
184191
}
185192

186193
@ExportMessage
187194
long getArraySize(
188-
@Shared("cpLen") @Cached TruffleString.CodePointLengthNode codePointLengthNode) {
195+
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode) {
189196
return codePointLengthNode.execute(getString(), TS_ENCODING) + 1;
190197
}
191198

@@ -196,15 +203,12 @@ boolean hasArrayElements() {
196203
}
197204

198205
@ExportMessage
199-
final byte readArrayElement(long index,
200-
@Shared("cpLen") @Cached TruffleString.CodePointLengthNode codePointLengthNode,
201-
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) throws InvalidArrayIndexException {
206+
byte readArrayElement(long index,
207+
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode,
208+
@Shared @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) throws InvalidArrayIndexException {
202209
try {
203210
int idx = PInt.intValueExact(index);
204211
TruffleString s = getString();
205-
// TODO GR-37217: use sys.getdefaultencoding if the string contains non-latin1
206-
// codepoints
207-
assert s.getCodeRangeUncached(TS_ENCODING) == TruffleString.CodeRange.ASCII;
208212
int len = codePointLengthNode.execute(s, TS_ENCODING);
209213
if (idx >= 0 && idx < len) {
210214
return (byte) codePointAtIndexNode.execute(s, idx, TS_ENCODING);
@@ -219,8 +223,8 @@ final byte readArrayElement(long index,
219223
}
220224

221225
@ExportMessage
222-
final boolean isArrayElementReadable(long identifier,
223-
@Shared("cpLen") @Cached TruffleString.CodePointLengthNode codePointLengthNode) {
226+
boolean isArrayElementReadable(long identifier,
227+
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode) {
224228
return 0 <= identifier && identifier < getArraySize(codePointLengthNode);
225229
}
226230

@@ -236,6 +240,91 @@ void toNative(
236240
setNativePointer(stringToNativeUtf8Bytes(getString(), switchEncodingNode, copyToByteArrayNode));
237241
}
238242
}
243+
244+
@ExportMessage
245+
@SuppressWarnings("static-method")
246+
boolean hasBufferElements() {
247+
return true;
248+
}
249+
250+
@ExportMessage
251+
long getBufferSize(
252+
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode) {
253+
return codePointLengthNode.execute(getString(), TS_ENCODING) + 1;
254+
}
255+
256+
@ExportMessage
257+
byte readBufferByte(long byteOffset,
258+
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode,
259+
@Shared @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) throws InvalidBufferOffsetException {
260+
TruffleString s = getString();
261+
int len = codePointLengthNode.execute(s, TS_ENCODING);
262+
if (byteOffset >= 0 && byteOffset < len) {
263+
return (byte) codePointAtIndexNode.execute(s, (int) byteOffset, TS_ENCODING);
264+
} else if (byteOffset == len) {
265+
return 0;
266+
} else {
267+
throw InvalidBufferOffsetException.create(byteOffset, len);
268+
}
269+
}
270+
271+
@ExportMessage
272+
short readBufferShort(ByteOrder byteOrder, long byteOffset,
273+
@CachedLibrary("this") InteropLibrary thisLib) throws UnsupportedMessageException, InvalidBufferOffsetException {
274+
byte b1 = thisLib.readBufferByte(this, byteOffset);
275+
byte b2 = thisLib.readBufferByte(this, byteOffset + 1);
276+
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
277+
return (short) (((b2 & 0xFF) << 8) | (b1 & 0xFF));
278+
} else {
279+
return (short) (((b1 & 0xFF) << 8) | (b2 & 0xFF));
280+
}
281+
}
282+
283+
@ExportMessage
284+
int readBufferInt(ByteOrder byteOrder, long byteOffset,
285+
@CachedLibrary("this") InteropLibrary thisLib) throws UnsupportedMessageException, InvalidBufferOffsetException {
286+
byte b1 = thisLib.readBufferByte(this, byteOffset);
287+
byte b2 = thisLib.readBufferByte(this, byteOffset + 1);
288+
byte b3 = thisLib.readBufferByte(this, byteOffset + 2);
289+
byte b4 = thisLib.readBufferByte(this, byteOffset + 3);
290+
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
291+
return ((b4 & 0xFF) << 8 * 3) | ((b3 & 0xFF) << 8 * 2) | ((b2 & 0xFF) << 8) | ((b1 & 0xFF));
292+
} else {
293+
return ((b1 & 0xFF) << 8 * 3) | ((b2 & 0xFF) << 8 * 2) | ((b3 & 0xFF) << 8) | ((b4 & 0xFF));
294+
}
295+
}
296+
297+
@ExportMessage
298+
long readBufferLong(ByteOrder byteOrder, long byteOffset,
299+
@CachedLibrary("this") InteropLibrary thisLib) throws UnsupportedMessageException, InvalidBufferOffsetException {
300+
byte b1 = thisLib.readBufferByte(this, byteOffset);
301+
byte b2 = thisLib.readBufferByte(this, byteOffset + 1);
302+
byte b3 = thisLib.readBufferByte(this, byteOffset + 2);
303+
byte b4 = thisLib.readBufferByte(this, byteOffset + 3);
304+
byte b5 = thisLib.readBufferByte(this, byteOffset + 4);
305+
byte b6 = thisLib.readBufferByte(this, byteOffset + 5);
306+
byte b7 = thisLib.readBufferByte(this, byteOffset + 6);
307+
byte b8 = thisLib.readBufferByte(this, byteOffset + 7);
308+
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
309+
return ((b8 & 0xFFL) << (8 * 7)) | ((b7 & 0xFFL) << (8 * 6)) | ((b6 & 0xFFL) << (8 * 5)) | ((b5 & 0xFFL) << (8 * 4)) |
310+
((b4 & 0xFFL) << (8 * 3)) | ((b3 & 0xFFL) << (8 * 2)) | ((b2 & 0xFFL) << 8) | ((b1 & 0xFFL));
311+
} else {
312+
return ((b1 & 0xFFL) << (8 * 7)) | ((b2 & 0xFFL) << (8 * 6)) | ((b3 & 0xFFL) << (8 * 5)) | ((b4 & 0xFFL) << (8 * 4)) |
313+
((b5 & 0xFFL) << (8 * 3)) | ((b6 & 0xFFL) << (8 * 2)) | ((b7 & 0xFFL) << 8) | ((b8 & 0xFFL));
314+
}
315+
}
316+
317+
@ExportMessage
318+
float readBufferFloat(ByteOrder byteOrder, long byteOffset,
319+
@CachedLibrary("this") InteropLibrary thisLib) throws UnsupportedMessageException, InvalidBufferOffsetException {
320+
return Float.intBitsToFloat(thisLib.readBufferInt(this, byteOrder, byteOffset));
321+
}
322+
323+
@ExportMessage
324+
double readBufferDouble(ByteOrder byteOrder, long byteOffset,
325+
@CachedLibrary("this") InteropLibrary thisLib) throws UnsupportedMessageException, InvalidBufferOffsetException {
326+
return Double.longBitsToDouble(thisLib.readBufferLong(this, byteOrder, byteOffset));
327+
}
239328
}
240329

241330
/**

0 commit comments

Comments
 (0)