Files
RidgeScout/app/src/main/java/com/ridgebotics/ridgescout/utility/ByteBuilder.java
T

254 lines
8.2 KiB
Java
Raw Normal View History

2024-09-15 22:47:45 -06:00
package com.ridgebotics.ridgescout.utility;
import static com.ridgebotics.ridgescout.utility.FileEditor.lengthHeaderBytes;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class ByteBuilder {
2024-07-16 21:25:34 -06:00
public static final int bool_id = 0;
public static final int int_id = 1;
public static final int string_id = 2;
public static final int int_arr_id = 3;
public static final int string_arr_id = 4;
2024-10-07 20:16:42 -06:00
public static final int long_id = 5;
ArrayList<byteType> bytesToBuild = new ArrayList<>();
public class buildingException extends Exception {
public buildingException() {}
public buildingException(String message) {
super(message);
}
}
private abstract static class byteType {
public abstract byte getType();
public abstract int length();
public abstract byte[] build();
}
2024-09-13 15:48:14 -06:00
public static String blankStrNull(String str){
if(str.isEmpty() || str.isEmpty()){
2024-09-14 18:02:31 -06:00
return "ƒ";
2024-09-13 15:48:14 -06:00
}
else return str;
}
2024-07-16 21:25:34 -06:00
private class boolType extends byteType {
public boolean val;
public byte getType(){return bool_id;}
public int length(){return 1;}
public byte[] build(){
return new byte[]{(byte) (val ? 1 : 0)};
}
}
public ByteBuilder addBool(boolean n) throws buildingException {
boolType boolType = new boolType();
boolType.val = n;
bytesToBuild.add(boolType);
return this;
}
private class intType extends byteType {
public int precision;
public int num;
public byte getType(){return int_id;}
public int length(){return precision;}
public byte[] build(){
2025-04-09 22:07:52 -06:00
return FileEditor.toBytes(num, precision, lengthHeaderBytes);
}
}
private int getLeastBytePrecision(int num){
if(num <= 1){return 1;}
return (int) Math.ceil(Math.log(Math.abs(num))/Math.log(8));
}
public ByteBuilder addInt(int num) throws buildingException {
// Get closest number of bytes
int precision = getLeastBytePrecision(num);
return addInt(num, precision);
}
public ByteBuilder addInt(int num, int precision) throws buildingException {
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
if(precision > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");}
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
if(num > Integer.MAX_VALUE){throw new buildingException("Integer overflow");}
if(num < Integer.MIN_VALUE){throw new buildingException("Integer overflow");}
intType intType = new intType();
intType.num = num;
intType.precision = precision;
bytesToBuild.add(intType);
return this;
}
private class stringType extends byteType {
public byte[] bytes;
public byte getType(){return string_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addString(String str) throws buildingException {
2024-09-13 15:48:14 -06:00
str = blankStrNull(str);
if(str.length() > Math.pow(lengthHeaderBytes,8)){throw new buildingException("String too long (greater than 16777216)");}
stringType stringType = new stringType();
// To get the length correctly, the string bytes need to be precalculated
stringType.bytes = str.getBytes(StandardCharsets.UTF_8);
bytesToBuild.add(stringType);
return this;
}
private class intArrayType extends byteType {
public byte[] bytes;
public byte getType(){return int_arr_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addIntArray(int[] arr) throws buildingException {
intArrayType intArrayType = new intArrayType();
ByteBuilder bb = new ByteBuilder();
for(int i = 0; i < arr.length; i++){
bb.addInt(arr[i]);
}
intArrayType.bytes = bb.build();
bytesToBuild.add(intArrayType);
return this;
}
private class stringArrayType extends byteType {
public byte[] bytes;
public byte getType(){return string_arr_id;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
// return str.getBytes(charset);
}
}
public ByteBuilder addStringArray(String[] arr) throws buildingException {
stringArrayType stringArrayType = new stringArrayType();
ByteBuilder bb = new ByteBuilder();
for(int i = 0; i < arr.length; i++){
bb.addString(arr[i]);
}
stringArrayType.bytes = bb.build();
bytesToBuild.add(stringArrayType);
return this;
}
2024-10-07 20:16:42 -06:00
private class longType extends byteType {
public int precision;
public long num;
public byte getType(){return long_id;}
public int length(){return precision;}
public byte[] build(){
2025-04-09 22:07:52 -06:00
return FileEditor.toBytes(num, precision, lengthHeaderBytes);
2024-10-07 20:16:42 -06:00
}
}
private int getLeastBytePrecision(long num){
if(num <= 1){return 1;}
return (int) Math.ceil(Math.log(Math.abs(num))/Math.log(8));
}
public ByteBuilder addLong(long num) throws buildingException {
// Get closest number of bytes
int precision = getLeastBytePrecision(num);
return addLong(num, precision);
}
public ByteBuilder addLong(long num, int precision) throws buildingException {
if(precision <= 0){throw new buildingException("Invalid precision: " + precision);}
if(precision > Math.pow(lengthHeaderBytes,8)){throw new buildingException("Precision too large (greter than 16777216)");}
2024-10-07 20:16:42 -06:00
if(precision < getLeastBytePrecision(num)){throw new buildingException("Precision too small");}
if(num > Long.MAX_VALUE){throw new buildingException("Long overflow");}
if(num < Long.MIN_VALUE){throw new buildingException("Long overflow");}
longType longType = new longType();
longType.num = num;
longType.precision = precision;
bytesToBuild.add(longType);
return this;
}
private class rawType extends byteType {
public int type;
public byte[] bytes;
public byte getType(){return (byte) type;}
public int length(){return bytes.length;}
public byte[] build(){
return bytes;
}
}
public ByteBuilder addRaw(int type, byte[] bytes) throws buildingException {
if(bytes.length > 16777216){throw new buildingException("Byte array length to long (greater than 16777216)");}
rawType rawType = new rawType();
rawType.type = type;
rawType.bytes = bytes;
bytesToBuild.add(rawType);
return this;
}
public byte[] build() throws buildingException {
if(bytesToBuild.size() == 0){throw new buildingException("Cannot build null data");}
int length = bytesToBuild.size() * (lengthHeaderBytes + 1);
for(byteType bt : bytesToBuild){
length += bt.length();
}
byte[] bytes = new byte[length];
int bytesFilled = 0;
for(byteType bt : bytesToBuild){
2025-04-09 22:07:52 -06:00
byte[] blockLength = FileEditor.toBytes(bt.length(), lengthHeaderBytes + 1, lengthHeaderBytes);
for(int i = 0; i < lengthHeaderBytes; i++) {
bytes[bytesFilled] = blockLength[i];
bytesFilled += 1;
}
bytes[bytesFilled] = bt.getType();
bytesFilled += 1;
// if(bt.length == 0)
// continue;
int i = 1;
byte[] newBytes = bt.build();
for(byte b : newBytes){
// Log.i("i", (bytesFilled+1) + "/" + length + " (" + i + "/" + bt.length() + ")");
bytes[bytesFilled] = b;
bytesFilled += 1;
i++;
}
}
return bytes;
}
}