Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8247488: Add support for string helpers in CSupport (decoding support) #207

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@
package jdk.incubator.foreign;

import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemoryAddressImpl;
import jdk.internal.foreign.NativeMemorySegmentImpl;
import jdk.internal.foreign.Utils;
import jdk.internal.foreign.abi.SharedUtils;

@@ -43,7 +45,7 @@ public class CSupport {
* Obtain a linker that uses the de facto C ABI of the current system to do it's linking.
* <p>
* This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
* @return a linker for this system.
* @throws IllegalAccessError if the runtime property {@code foreign.restricted} is not set to either
@@ -635,10 +637,15 @@ public static MemoryAddress toCString(String str, Charset charset, NativeScope s
}

/**
* Convert a null-terminated C string stored at given address into a Java string.
* Convert a null-terminated C string stored at given address into a Java string, using the platform's default charset.
* <p>
* This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
* <p>
* This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
* @param addr the address at which the string is stored.
* @return a Java string with the contents of the null-terminated C string at given address.
@@ -647,11 +654,38 @@ public static MemoryAddress toCString(String str, Charset charset, NativeScope s
*/
public static String toJavaStringRestricted(MemoryAddress addr) {
Utils.checkRestrictedAccess("CSupport.toJavaStringRestricted");
return toJavaStringInternal(addr.rebase(AbstractMemorySegmentImpl.EVERYTHING));
return toJavaStringInternal(addr.rebase(AbstractMemorySegmentImpl.EVERYTHING), Charset.defaultCharset());
}

/**
* Convert a null-terminated C string stored at given address into a Java string, using the given {@linkplain java.nio.charset.Charset charset}.
* <p>
* This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
* <p>
* This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
* @param addr the address at which the string is stored.
* @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the Java string.
* @return a Java string with the contents of the null-terminated C string at given address.
* @throws NullPointerException if {@code addr == null}
* @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
*/
public static String toJavaStringRestricted(MemoryAddress addr, Charset charset) {
Utils.checkRestrictedAccess("CSupport.toJavaStringRestricted");
return toJavaStringInternal(addr.rebase(AbstractMemorySegmentImpl.EVERYTHING), charset);
}

/**
* Convert a null-terminated C string stored at given address into a Java string.
* Convert a null-terminated C string stored at given address into a Java string, using the platform's default charset.
* <p>
* This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
* @param addr the address at which the string is stored.
* @return a Java string with the contents of the null-terminated C string at given address.
* @throws NullPointerException if {@code addr == null}
@@ -660,18 +694,43 @@ public static String toJavaStringRestricted(MemoryAddress addr) {
* associated with {@code addr}, or if {@code addr} is associated with a segment that is </em>not alive<em>.
*/
public static String toJavaString(MemoryAddress addr) {
return toJavaStringInternal(addr);
return toJavaStringInternal(addr, Charset.defaultCharset());
}

/**
* Convert a null-terminated C string stored at given address into a Java string, using the given {@linkplain java.nio.charset.Charset charset}.
* <p>
* This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
* @param addr the address at which the string is stored.
* @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the Java string.
* @return a Java string with the contents of the null-terminated C string at given address.
* @throws NullPointerException if {@code addr == null}
* @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
* @throws IllegalStateException if the size of the native string is greater than the size of the segment
* associated with {@code addr}, or if {@code addr} is associated with a segment that is </em>not alive<em>.
*/
public static String toJavaString(MemoryAddress addr, Charset charset) {
return toJavaStringInternal(addr, charset);
}

private static String toJavaStringInternal(MemoryAddress addr, Charset charset) {
int len = strlen(addr);
byte[] bytes = new byte[len];
MemorySegment.ofArray(bytes)
.copyFrom(NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, len, null, null, null));
return new String(bytes, charset);
}

private static String toJavaStringInternal(MemoryAddress addr) {
StringBuilder buf = new StringBuilder();
private static int strlen(MemoryAddress address) {
// iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
for (int offset = 0 ; offset >= 0 ; offset++) {
byte curr = (byte) byteArrHandle.get(addr, (long)offset);
for (int offset = 0; offset >= 0; offset++) {
byte curr = (byte) byteArrHandle.get(address, (long) offset);
if (curr == 0) {
return buf.toString();
return offset;
}
buf.append((char) curr);
}
throw new IllegalArgumentException("String too large");
}
Original file line number Diff line number Diff line change
@@ -611,7 +611,7 @@ static MemorySegment allocateNative(long bytesSize, long alignmentBytes) {
* (see {@link #ALL_ACCESS}).
* <p>
* This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
*
* @param addr the desired base address
2 changes: 1 addition & 1 deletion test/jdk/java/foreign/StdLibTest.java
Original file line number Diff line number Diff line change
@@ -316,7 +316,7 @@ int yday() {
}
boolean isdst() {
byte b = (byte)byteHandle.get(base.addOffset(32));
return b == 0 ? false : true;
return b != 0;
}
}