mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 00:37:59 -06:00
255 lines
8.2 KiB
Java
255 lines
8.2 KiB
Java
package com.ridgebotics.ridgescout.utility;
|
|
|
|
import static com.ridgebotics.ridgescout.utility.FileEditor.lengthHeaderBytes;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
|
|
// Class to encode the raw types from any of the scouting files
|
|
public class ByteBuilder {
|
|
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;
|
|
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();
|
|
}
|
|
|
|
public static String blankStrNull(String str){
|
|
if(str.isEmpty() || str.isEmpty()){
|
|
return "ƒ";
|
|
}
|
|
else return str;
|
|
}
|
|
|
|
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(){
|
|
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 {
|
|
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;
|
|
}
|
|
|
|
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(){
|
|
return FileEditor.toBytes(num, precision, lengthHeaderBytes);
|
|
}
|
|
}
|
|
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)");}
|
|
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){
|
|
|
|
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;
|
|
}
|
|
}
|