io.github.aleksas.pystruct.ByteBufferStruct Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arduino-simple-rpc Show documentation
Show all versions of arduino-simple-rpc Show documentation
Arduino simpleRPC API client library
package io.github.aleksas.pystruct;
import static java.nio.ByteBuffer.wrap;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Map;
public class ByteBufferStruct {
private static final String FAILED_TO_READ_TYPE_COMPLETELY = "Failed to read type completely";
public static Map ORDER = Map.of(
'<', ByteOrder.LITTLE_ENDIAN,
'>', ByteOrder.BIG_ENDIAN,
'@', ByteOrder.nativeOrder(),
'=', ByteOrder.nativeOrder(),
'!', ByteOrder.BIG_ENDIAN
);
public static Map TYPE_SIZES = Map.ofEntries(
Map.entry('c', 1), // char
Map.entry('b', 1), // signed char
Map.entry('B', 1), // unsigned char
Map.entry('?', 1), // Bool
Map.entry('h', 2), // short
Map.entry('H', 2), // unsigned short
Map.entry('i', 4), // int
Map.entry('I', 4), // unsigned int
Map.entry('l', 4), // long
Map.entry('L', 4), // unsigned long
Map.entry('q', 8), // long long
Map.entry('Q', 8), // unsigned long long
Map.entry('f', 4), // float
Map.entry('d', 8) // double
);
private static BigInteger toUnsignedBigInteger(long i) {
if (i >= 0L) {
return BigInteger.valueOf(i);
} else {
int upper = (int) (i >>> 32);
int lower = (int) i;
// return (upper << 32) + lower
return BigInteger.valueOf(Integer.toUnsignedLong(upper))
.shiftLeft(32)
.add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
}
}
public static ByteBuffer Pack(String format, Object[] object) {
byte[] bytes = new byte[CalcSize(format)];
ByteBuffer buffer = wrap(bytes);
buffer.rewind();
buffer.order(GetByteOrder(format));
int offset = 0;
for (int i = 0; i < format.length(); i++) {
char c = format.charAt(i);
if (i == 0 && ORDER.keySet().contains(c)) {
offset = 1;
continue;
}
int pos = i - offset;
switch (c) {
case 'c':
buffer.put((byte) ((Character) object[pos]).charValue());
break;
case 'b':
buffer.put((byte) object[pos]);
break;
case 'B':
buffer.put((byte) (((int) object[pos]) & 0xff));
break;
case '?':
buffer.put((byte)(((boolean) object[pos])?1:0));
break;
case 'h':
buffer.putShort((Short)object[pos]);
break;
case 'H':
buffer.putShort((short) (((int) object[pos]) & 0xffff));
break;
case 'i':
case 'l':
buffer.putInt((int) object[pos]);
break;
case 'I':
case 'L':
buffer.putInt((int) (((long) object[pos]) & 0xffffffffL));
break;
case 'q':
buffer.putLong((long) object[pos]);
break;
case 'Q':
buffer.putLong(((BigInteger) object[pos]).longValue() & 0xffffffffffffffffL);
break;
case 'f':
buffer.putFloat((float) object[pos]);
break;
case 'd':
buffer.putDouble((float) object[pos]);
break;
default:
throw new RuntimeException(String.format("Not supported format: %c", c));
}
}
buffer.rewind();
return buffer;
}
public static Object[] Unpack(String format, InputStream stream) {
ArrayList