@ -194,6 +194,22 @@ public class TbUtils {
byte [ ] . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesToFloat" ,
byte [ ] . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
List . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
List . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
List . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
List . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
byte [ ] . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
byte [ ] . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
byte [ ] . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesIntToFloat" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesIntToFloat" ,
byte [ ] . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "parseLittleEndianHexToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseLittleEndianHexToDouble" ,
String . class ) ) ) ;
parserConfig . addImport ( "parseBigEndianHexToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBigEndianHexToDouble" ,
@ -218,6 +234,22 @@ public class TbUtils {
byte [ ] . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesToDouble" ,
byte [ ] . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
List . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
List . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
List . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
List . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
byte [ ] . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
byte [ ] . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
byte [ ] . class , int . class , int . class ) ) ) ;
parserConfig . addImport ( "parseBytesLongToDouble" , new MethodStub ( TbUtils . class . getMethod ( "parseBytesLongToDouble" ,
byte [ ] . class , int . class , int . class , boolean . class ) ) ) ;
parserConfig . addImport ( "toFixed" , new MethodStub ( TbUtils . class . getMethod ( "toFixed" ,
double . class , int . class ) ) ) ;
parserConfig . addImport ( "toFixed" , new MethodStub ( TbUtils . class . getMethod ( "toFixed" ,
@ -292,6 +324,9 @@ public class TbUtils {
String . class ) ) ) ;
parserConfig . addImport ( "isHexadecimal" , new MethodStub ( TbUtils . class . getMethod ( "isHexadecimal" ,
String . class ) ) ) ;
parserConfig . addImport ( "byteArrayToExecutionArrayList" , new MethodStub ( TbUtils . class . getMethod ( "byteArrayToExecutionArrayList" ,
ExecutionContext . class , byte [ ] . class ) ) ) ;
}
public static String btoa ( String input ) {
@ -753,7 +788,7 @@ public class TbUtils {
long bits = Double . doubleToRawLongBits ( d ) ;
// Format the integer bits as a hexadecimal string
String result = String . format ( "0x%16X" , bits ) ;
String result = String . format ( "0x%0 16X" , bits ) ;
return bigEndian ? result : reverseHexStringByOrder ( result ) ;
}
@ -770,15 +805,15 @@ public class TbUtils {
}
public static int parseBytesToInt ( List < Byte > data ) {
return parseBytesToInt ( Bytes . toArray ( data ) ) ;
return parseBytesToInt ( data , 0 ) ;
}
public static int parseBytesToInt ( List < Byte > data , int offset ) {
return parseBytesToInt ( Bytes . toArray ( data ) , offset ) ;
return parseBytesToInt ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_INT_MAX ) ) ;
}
public static int parseBytesToInt ( List < Byte > data , int offset , int length ) {
return parseBytesToInt ( Bytes . toArray ( data ) , offset , length ) ;
return parseBytesToInt ( data , offset , length , true ) ;
}
public static int parseBytesToInt ( List < Byte > data , int offset , int length , boolean bigEndian ) {
@ -798,15 +833,7 @@ public class TbUtils {
}
public static int parseBytesToInt ( byte [ ] data , int offset , int length , boolean bigEndian ) {
if ( offset > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " is out of bounds for array with length: " + data . length + "!" ) ;
}
if ( length > BYTES_LEN_INT_MAX ) {
throw new IllegalArgumentException ( "Length: " + length + " is too large. Maximum 4 bytes is allowed!" ) ;
}
if ( offset + length > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
validationNumberByLength ( data , offset , length , BYTES_LEN_INT_MAX ) ;
var bb = ByteBuffer . allocate ( 4 ) ;
if ( ! bigEndian ) {
bb . order ( ByteOrder . LITTLE_ENDIAN ) ;
@ -818,15 +845,15 @@ public class TbUtils {
}
public static long parseBytesToLong ( List < Byte > data ) {
return parseBytesToLong ( Bytes . toArray ( data ) ) ;
return parseBytesToLong ( data , 0 ) ;
}
public static long parseBytesToLong ( List < Byte > data , int offset ) {
return parseBytesToLong ( Bytes . toArray ( data ) , offset ) ;
return parseBytesToLong ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_LONG_MAX ) ) ;
}
public static long parseBytesToLong ( List < Byte > data , int offset , int length ) {
return parseBytesToLong ( Bytes . toArray ( data ) , offset , length ) ;
return parseBytesToLong ( data , offset , length , true ) ;
}
public static long parseBytesToLong ( List < Byte > data , int offset , int length , boolean bigEndian ) {
@ -846,15 +873,7 @@ public class TbUtils {
}
public static long parseBytesToLong ( byte [ ] data , int offset , int length , boolean bigEndian ) {
if ( offset > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " is out of bounds for array with length: " + data . length + "!" ) ;
}
if ( length > BYTES_LEN_LONG_MAX ) {
throw new IllegalArgumentException ( "Length: " + length + " is too large. Maximum " + BYTES_LEN_LONG_MAX + " bytes is allowed!" ) ;
}
if ( offset + length > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
validationNumberByLength ( data , offset , length , BYTES_LEN_LONG_MAX ) ;
var bb = ByteBuffer . allocate ( BYTES_LEN_LONG_MAX ) ;
if ( ! bigEndian ) {
bb . order ( ByteOrder . LITTLE_ENDIAN ) ;
@ -866,15 +885,15 @@ public class TbUtils {
}
public static float parseBytesToFloat ( List data ) {
return parseBytesToFloat ( Bytes . toArray ( data ) , 0 ) ;
return parseBytesToFloat ( data , 0 ) ;
}
public static float parseBytesToFloat ( List data , int offset ) {
return parseBytesToFloat ( Bytes . toArray ( data ) , offset , BYTES_LEN_INT_MAX ) ;
return parseBytesToFloat ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_INT_MAX ) ) ;
}
public static float parseBytesToFloat ( List data , int offset , int length ) {
return parseBytesToFloat ( Bytes . toArray ( data ) , offset , length , true ) ;
return parseBytesToFloat ( data , offset , length , true ) ;
}
public static float parseBytesToFloat ( List data , int offset , int length , boolean bigEndian ) {
@ -886,7 +905,7 @@ public class TbUtils {
}
public static float parseBytesToFloat ( byte [ ] data , int offset ) {
return parseBytesToFloat ( data , offset , BYTES_LEN_INT_MAX ) ;
return parseBytesToFloat ( data , offset , validateLength ( data . length , offset , BYTES_LEN_INT_MAX ) ) ;
}
public static float parseBytesToFloat ( byte [ ] data , int offset , int length ) {
@ -894,39 +913,65 @@ public class TbUtils {
}
public static float parseBytesToFloat ( byte [ ] data , int offset , int length , boolean bigEndian ) {
if ( length > BYTES_LEN_INT_MAX ) {
throw new IllegalArgumentException ( "Length: " + length + " is too large. Maximum " + BYTES_LEN_INT_MAX + " bytes is allowed!" ) ;
}
if ( offset + length > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
byte [ ] bytesToNumber = prepareBytesToNumber ( data , offset , length , bigEndian ) ;
if ( bytesToNumber . length < BYTES_LEN_INT_MAX ) {
byte [ ] extendedBytes = new byte [ BYTES_LEN_INT_MAX ] ;
Arrays . fill ( extendedBytes , ( byte ) 0 ) ;
System . arraycopy ( bytesToNumber , 0 , extendedBytes , 0 , bytesToNumber . length ) ;
bytesToNumber = extendedBytes ;
var bb = ByteBuffer . allocate ( BYTES_LEN_INT_MAX ) ;
if ( ! bigEndian ) {
bb . order ( ByteOrder . LITTLE_ENDIAN ) ;
}
float floatValue = ByteBuffer . wrap ( bytesToNumber ) . getFloat ( ) ;
if ( ! Float . isNaN ( floatValue ) ) {
return floatValue ;
} else {
long longValue = parseBytesToLong ( bytesToNumber , 0 , BYTES_LEN_INT_MAX ) ;
BigDecimal bigDecimalValue = new BigDecimal ( longValue ) ;
return bigDecimalValue . floatValue ( ) ;
bb . position ( bigEndian ? BYTES_LEN_INT_MAX - length : 0 ) ;
bb . put ( data , offset , length ) ;
bb . position ( 0 ) ;
float floatValue = bb . getFloat ( ) ;
if ( Float . isNaN ( floatValue ) ) {
throw new NumberFormatException ( "byte[] 0x" + bytesToHex ( data ) + " is a Not-a-Number (NaN) value" ) ;
}
return floatValue ;
}
public static float parseBytesIntToFloat ( List data ) {
return parseBytesIntToFloat ( data , 0 ) ;
}
public static float parseBytesIntToFloat ( List data , int offset ) {
return parseBytesIntToFloat ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_INT_MAX ) ) ;
}
public static float parseBytesIntToFloat ( List data , int offset , int length ) {
return parseBytesIntToFloat ( data , offset , length , true ) ;
}
public static float parseBytesIntToFloat ( List data , int offset , int length , boolean bigEndian ) {
return parseBytesIntToFloat ( Bytes . toArray ( data ) , offset , length , bigEndian ) ;
}
public static float parseBytesIntToFloat ( byte [ ] data ) {
return parseBytesIntToFloat ( data , 0 ) ;
}
public static float parseBytesIntToFloat ( byte [ ] data , int offset ) {
return parseBytesIntToFloat ( data , offset , validateLength ( data . length , offset , BYTES_LEN_INT_MAX ) ) ;
}
public static float parseBytesIntToFloat ( byte [ ] data , int offset , int length ) {
return parseBytesIntToFloat ( data , offset , length , true ) ;
}
public static float parseBytesIntToFloat ( byte [ ] data , int offset , int length , boolean bigEndian ) {
byte [ ] bytesToNumber = prepareBytesToNumber ( data , offset , length , bigEndian , BYTES_LEN_INT_MAX ) ;
long longValue = parseBytesToLong ( bytesToNumber , 0 , length ) ;
BigDecimal bigDecimalValue = new BigDecimal ( longValue ) ;
return bigDecimalValue . floatValue ( ) ;
}
public static double parseBytesToDouble ( List data ) {
return parseBytesToDouble ( Bytes . toArray ( data ) ) ;
return parseBytesToDouble ( data , 0 ) ;
}
public static double parseBytesToDouble ( List data , int offset ) {
return parseBytesToDouble ( Bytes . toArray ( data ) , offset ) ;
return parseBytesToDouble ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_LONG_MAX ) ) ;
}
public static double parseBytesToDouble ( List data , int offset , int length ) {
return parseBytesToDouble ( Bytes . toArray ( data ) , offset , length ) ;
return parseBytesToDouble ( data , offset , length , true ) ;
}
public static double parseBytesToDouble ( List data , int offset , int length , boolean bigEndian ) {
@ -938,7 +983,7 @@ public class TbUtils {
}
public static double parseBytesToDouble ( byte [ ] data , int offset ) {
return parseBytesToDouble ( data , offset , BYTES_LEN_LONG_MAX ) ;
return parseBytesToDouble ( data , offset , validateLength ( data . length , offset , BYTES_LEN_LONG_MAX ) ) ;
}
public static double parseBytesToDouble ( byte [ ] data , int offset , int length ) {
@ -946,36 +991,58 @@ public class TbUtils {
}
public static double parseBytesToDouble ( byte [ ] data , int offset , int length , boolean bigEndian ) {
if ( length > BYTES_LEN_LONG_MAX ) {
throw new IllegalArgumentException ( "Length: " + length + " is too large. Maximum " + BYTES_LEN_LONG_MAX + " bytes is allowed!" ) ;
}
if ( offset + length > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
byte [ ] bytesToNumber = prepareBytesToNumber ( data , offset , length , bigEndian ) ;
if ( bytesToNumber . length < BYTES_LEN_LONG_MAX ) {
byte [ ] extendedBytes = new byte [ BYTES_LEN_LONG_MAX ] ;
Arrays . fill ( extendedBytes , ( byte ) 0 ) ;
System . arraycopy ( bytesToNumber , 0 , extendedBytes , 0 , bytesToNumber . length ) ;
bytesToNumber = extendedBytes ;
var bb = ByteBuffer . allocate ( BYTES_LEN_LONG_MAX ) ;
if ( ! bigEndian ) {
bb . order ( ByteOrder . LITTLE_ENDIAN ) ;
}
double doubleValue = ByteBuffer . wrap ( bytesToNumber ) . getDouble ( ) ;
if ( ! Double . isNaN ( doubleValue ) ) {
return doubleValue ;
} else {
BigInteger bigInt = new BigInteger ( 1 , bytesToNumber ) ;
BigDecimal bigDecimalValue = new BigDecimal ( bigInt ) ;
return bigDecimalValue . doubleValue ( ) ;
bb . position ( bigEndian ? BYTES_LEN_LONG_MAX - length : 0 ) ;
bb . put ( data , offset , length ) ;
bb . position ( 0 ) ;
double doubleValue = bb . getDouble ( ) ;
if ( Double . isNaN ( doubleValue ) ) {
throw new NumberFormatException ( "byte[] 0x" + bytesToHex ( data ) + " is a Not-a-Number (NaN) value" ) ;
}
return doubleValue ;
}
private static byte [ ] prepareBytesToNumber ( byte [ ] data , int offset , int length , boolean bigEndian ) {
if ( offset > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " is out of bounds for array with length: " + data . length + "!" ) ;
}
if ( ( offset + length ) > data . length ) {
throw new IllegalArgumentException ( "Default length is always " + length + " bytes. Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
public static double parseBytesLongToDouble ( List data ) {
return parseBytesLongToDouble ( data , 0 ) ;
}
public static double parseBytesLongToDouble ( List data , int offset ) {
return parseBytesLongToDouble ( data , offset , validateLength ( data . size ( ) , offset , BYTES_LEN_LONG_MAX ) ) ;
}
public static double parseBytesLongToDouble ( List data , int offset , int length ) {
return parseBytesLongToDouble ( data , offset , length , true ) ;
}
public static double parseBytesLongToDouble ( List data , int offset , int length , boolean bigEndian ) {
return parseBytesLongToDouble ( Bytes . toArray ( data ) , offset , length , bigEndian ) ;
}
public static double parseBytesLongToDouble ( byte [ ] data ) {
return parseBytesLongToDouble ( data , 0 ) ;
}
public static double parseBytesLongToDouble ( byte [ ] data , int offset ) {
return parseBytesLongToDouble ( data , offset , validateLength ( data . length , offset , BYTES_LEN_LONG_MAX ) ) ;
}
public static double parseBytesLongToDouble ( byte [ ] data , int offset , int length ) {
return parseBytesLongToDouble ( data , offset , length , true ) ;
}
public static double parseBytesLongToDouble ( byte [ ] data , int offset , int length , boolean bigEndian ) {
byte [ ] bytesToNumber = prepareBytesToNumber ( data , offset , length , bigEndian , BYTES_LEN_LONG_MAX ) ;
BigInteger bigInt = new BigInteger ( 1 , bytesToNumber ) ;
BigDecimal bigDecimalValue = new BigDecimal ( bigInt ) ;
return bigDecimalValue . doubleValue ( ) ;
}
private static byte [ ] prepareBytesToNumber ( byte [ ] data , int offset , int length , boolean bigEndian ,
int bytesLenMax ) {
validationNumberByLength ( data , offset , length , bytesLenMax ) ;
byte [ ] dataBytesArray = Arrays . copyOfRange ( data , offset , ( offset + length ) ) ;
if ( ! bigEndian ) {
ArrayUtils . reverse ( dataBytesArray ) ;
@ -1168,6 +1235,15 @@ public class TbUtils {
return str . matches ( "^-?(0[xX])?[0-9a-fA-F]+$" ) ? HEX_RADIX : - 1 ;
}
public static List byteArrayToExecutionArrayList ( ExecutionContext ctx , byte [ ] byteArray ) {
List < Byte > byteList = new ArrayList < > ( ) ;
for ( byte b : byteArray ) {
byteList . add ( b ) ;
}
List list = new ExecutionArrayList ( byteList , ctx ) ;
return list ;
}
private static byte isValidIntegerToByte ( Integer val ) {
if ( val > 255 | | val < - 128 ) {
throw new NumberFormatException ( "The value '" + val + "' could not be correctly converted to a byte. " +
@ -1194,5 +1270,23 @@ public class TbUtils {
String result = reversedHex . toString ( ) ;
return isHexPref ? "0x" + result : result ;
}
private static void validationNumberByLength ( byte [ ] data , int offset , int length , int bytesLenMax ) {
if ( offset > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " is out of bounds for array with length: " + data . length + "!" ) ;
}
if ( offset + length > data . length ) {
throw new IllegalArgumentException ( "Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data . length + "!" ) ;
}
if ( length > bytesLenMax ) {
throw new IllegalArgumentException ( "Length: " + length + " is too large. Maximum " + bytesLenMax + " bytes is allowed!" ) ;
}
}
private static int validateLength ( int dataLength , int offset , int bytesLenMax ) {
return ( dataLength < offset ) ? dataLength : Math . min ( ( dataLength - offset ) , bytesLenMax ) ;
}
}