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
6262import com .oracle .truffle .api .interop .InteropLibrary ;
6363import com .oracle .truffle .api .interop .InvalidArrayIndexException ;
6464import com .oracle .truffle .api .interop .InvalidBufferOffsetException ;
65+ import com .oracle .truffle .api .interop .UnsupportedMessageException ;
66+ import com .oracle .truffle .api .library .CachedLibrary ;
6567import com .oracle .truffle .api .library .ExportLibrary ;
6668import com .oracle .truffle .api .library .ExportMessage ;
6769import 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