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

fix #30 #254

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
27 changes: 25 additions & 2 deletions src/main/java/jnr/ffi/provider/jffi/DirectMemoryIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

class DirectMemoryIO extends AbstractMemoryIO {
static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
Expand Down Expand Up @@ -186,8 +187,30 @@ public String getString(long offset) {


public String getString(long offset, int maxLength, Charset cs) {
final byte[] bytes = IO.getZeroTerminatedByteArray(address() + offset, maxLength);
return cs.decode(ByteBuffer.wrap(bytes)).toString();
if(cs == StandardCharsets.UTF_8){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat according to more common Java formatting standards:

if (cond) {
...
} else {
...
for (stuff) {
...

Otherwise we get a mix of formats and future patches will likely include unhelpful formatting updates.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic could apply to any Charset that has a minimum character width of 1 byte, correct? All such encodings should use a single-byte \0 for C string termination I think?

At the very least this should include the ISO-8859 encodings, which are all single-byte (their CharsetEncoder.maxBytesPerChar will all be 1.0).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree that I should include other single byte terminator charsets, but CharsetEncoder.maxBytesPerChar won't be sufficient because it does not resolve to 1.0 for utf-8

final byte[] bytes = IO.getZeroTerminatedByteArray(address() + offset, maxLength);
return cs.decode(ByteBuffer.wrap(bytes)).toString();
}else{
byte[] bytes = new byte[maxLength];
IO.getByteArray(address() + offset, bytes, 0, maxLength);
final byte[] nullCharBytes = new String("\0").getBytes(cs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could possibly be cached for common encodings (UTF-16, UTF-32) or it might be valid to just use a width of \0 equal to the encoding's CharsetEncoder.maxBytesPerChar value.

int nullIndex = maxLength;
int matchingBytesCount = 0;
for(int i = 0; i < (int)bytes.length; i++){
if(bytes[i] == nullCharBytes[matchingBytesCount]){
matchingBytesCount++;
} else {
matchingBytesCount = 0;
}

if(matchingBytesCount == nullCharBytes.length){
nullIndex = i;
break;
}
}

return new String(bytes, 0, nullIndex, cs);
}
}

public void putString(long offset, String string, int maxLength, Charset cs) {
Expand Down