TBEL: new methods (#11129)
* tbel: number to string by radix * Revert "tbel: number to string by radix" This reverts commit 0fd285d76b5f25002f84768ab490e750539509d0. * tbel: number to string by radix and new Error * tbel: number to Hexadecimal must be even-length. * tbel: add tests isBinary...isHexadecimal * tbel: Comments 1 * tbel: Comments 2 * tbel: Comments 3
This commit is contained in:
		
							parent
							
								
									caaeefa41f
								
							
						
					
					
						commit
						99d4eb0d9c
					
				@ -46,11 +46,23 @@ import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
 | 
			
		||||
import static java.lang.Character.MAX_RADIX;
 | 
			
		||||
import static java.lang.Character.MIN_RADIX;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class TbUtils {
 | 
			
		||||
 | 
			
		||||
    private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
 | 
			
		||||
 | 
			
		||||
    private static final int ZERO_RADIX = 0;
 | 
			
		||||
    private static final int OCTAL_RADIX = 8;
 | 
			
		||||
    private static final int DEC_RADIX = 10;
 | 
			
		||||
    private static final int HEX_RADIX = 16;
 | 
			
		||||
    private static final int HEX_LEN_MIN = -1;
 | 
			
		||||
    private static final int HEX_LEN_INT_MAX = 8;
 | 
			
		||||
    private static final int HEX_LEN_LONG_MAX = 16;
 | 
			
		||||
    private static final int BYTES_LEN_LONG_MAX = 8;
 | 
			
		||||
 | 
			
		||||
    private static final LinkedHashMap<String, String> mdnEncodingReplacements = new LinkedHashMap<>();
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
@ -103,6 +115,8 @@ public class TbUtils {
 | 
			
		||||
                String.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("parseFloat", new MethodStub(TbUtils.class.getMethod("parseFloat",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseFloat", new MethodStub(TbUtils.class.getMethod("parseFloat",
 | 
			
		||||
                String.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("parseDouble", new MethodStub(TbUtils.class.getMethod("parseDouble",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseLittleEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseLittleEndianHexToInt",
 | 
			
		||||
@ -175,6 +189,40 @@ public class TbUtils {
 | 
			
		||||
                float.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
 | 
			
		||||
                ExecutionContext.class, String.class)));
 | 
			
		||||
        parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
 | 
			
		||||
                Integer.class)));
 | 
			
		||||
        parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
 | 
			
		||||
                Integer.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
 | 
			
		||||
                Integer.class, boolean.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("intToHex", new MethodStub(TbUtils.class.getMethod("intToHex",
 | 
			
		||||
                Integer.class, boolean.class, boolean.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
 | 
			
		||||
                Long.class)));
 | 
			
		||||
        parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
 | 
			
		||||
                Long.class, boolean.class)));
 | 
			
		||||
       parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
 | 
			
		||||
                Long.class, boolean.class, boolean.class)));
 | 
			
		||||
       parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
 | 
			
		||||
                Long.class, boolean.class, boolean.class, int.class)));
 | 
			
		||||
       parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
 | 
			
		||||
                Long.class)));
 | 
			
		||||
       parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
 | 
			
		||||
                Long.class, int.class)));
 | 
			
		||||
       parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
 | 
			
		||||
                Long.class, int.class, boolean.class)));
 | 
			
		||||
       parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
 | 
			
		||||
                Long.class, int.class, boolean.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("floatToHex", new MethodStub(TbUtils.class.getMethod("floatToHex",
 | 
			
		||||
                Float.class)));
 | 
			
		||||
        parserConfig.addImport("floatToHex", new MethodStub(TbUtils.class.getMethod("floatToHex",
 | 
			
		||||
                Float.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("doubleToHex", new MethodStub(TbUtils.class.getMethod("doubleToHex",
 | 
			
		||||
                Double.class)));
 | 
			
		||||
        parserConfig.addImport("doubleToHex", new MethodStub(TbUtils.class.getMethod("doubleToHex",
 | 
			
		||||
                Double.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("printUnsignedBytes", new MethodStub(TbUtils.class.getMethod("printUnsignedBytes",
 | 
			
		||||
                ExecutionContext.class, List.class)));
 | 
			
		||||
        parserConfig.addImport("base64ToHex", new MethodStub(TbUtils.class.getMethod("base64ToHex",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("base64ToBytes", new MethodStub(TbUtils.class.getMethod("base64ToBytes",
 | 
			
		||||
@ -197,6 +245,18 @@ public class TbUtils {
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("decodeURI", new MethodStub(TbUtils.class.getMethod("decodeURI",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("raiseError", new MethodStub(TbUtils.class.getMethod("raiseError",
 | 
			
		||||
                String.class, Object.class)));
 | 
			
		||||
        parserConfig.addImport("raiseError", new MethodStub(TbUtils.class.getMethod("raiseError",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("isBinary", new MethodStub(TbUtils.class.getMethod("isBinary",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("isOctal", new MethodStub(TbUtils.class.getMethod("isOctal",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("isDecimal", new MethodStub(TbUtils.class.getMethod("isDecimal",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("isHexadecimal", new MethodStub(TbUtils.class.getMethod("isHexadecimal",
 | 
			
		||||
                String.class)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String btoa(String input) {
 | 
			
		||||
@ -210,6 +270,7 @@ public class TbUtils {
 | 
			
		||||
    public static Object decodeToJson(ExecutionContext ctx, List<Byte> bytesList) throws IOException {
 | 
			
		||||
        return TbJson.parse(ctx, bytesToString(bytesList));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Object decodeToJson(ExecutionContext ctx, String jsonStr) throws IOException {
 | 
			
		||||
        return TbJson.parse(ctx, jsonStr);
 | 
			
		||||
    }
 | 
			
		||||
@ -269,88 +330,127 @@ public class TbUtils {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Integer parseInt(String value) {
 | 
			
		||||
        int radix = getRadix(value);
 | 
			
		||||
        return parseInt(value, radix);
 | 
			
		||||
        return parseInt(value, ZERO_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Integer parseInt(String value, int radix) {
 | 
			
		||||
        if (StringUtils.isNotBlank(value)) {
 | 
			
		||||
            try {
 | 
			
		||||
                String valueP = prepareNumberString(value);
 | 
			
		||||
                isValidRadix(valueP, radix);
 | 
			
		||||
                try {
 | 
			
		||||
                    return Integer.parseInt(valueP, radix);
 | 
			
		||||
                } catch (NumberFormatException e) {
 | 
			
		||||
                    BigInteger bi = new BigInteger(valueP, radix);
 | 
			
		||||
                    if (bi.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0)
 | 
			
		||||
                        throw new NumberFormatException("Value \"" + value + "\" is greater than the maximum Integer value " + Integer.MAX_VALUE + " !");
 | 
			
		||||
                    if (bi.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0)
 | 
			
		||||
                        throw new NumberFormatException("Value \"" + value + "\" is less than the minimum Integer value " + Integer.MIN_VALUE + " !");
 | 
			
		||||
                    Float f = parseFloat(valueP);
 | 
			
		||||
                    if (f != null) {
 | 
			
		||||
                        return f.intValue();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        throw new NumberFormatException(e.getMessage());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
                throw new NumberFormatException(e.getMessage());
 | 
			
		||||
            String valueP = prepareNumberString(value);
 | 
			
		||||
            int radixValue = isValidStringAndRadix(valueP, radix, value);
 | 
			
		||||
            if (radixValue  >= 25 && radixValue  <= MAX_RADIX) {
 | 
			
		||||
                return (Integer) compareIntLongValueMinMax(valueP, radixValue, Integer.MAX_VALUE, Integer.MIN_VALUE);
 | 
			
		||||
            }
 | 
			
		||||
            return switch (radixValue) {
 | 
			
		||||
                case MIN_RADIX -> parseBinaryStringAsSignedInteger(valueP);
 | 
			
		||||
                case OCTAL_RADIX, DEC_RADIX, HEX_RADIX -> Integer.parseInt(valueP, radixValue);
 | 
			
		||||
                default -> throw new IllegalArgumentException("Invalid radix: [" + radix + "]");
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Long parseLong(String value) {
 | 
			
		||||
        int radix = getRadix(value);
 | 
			
		||||
        return parseLong(value, radix);
 | 
			
		||||
        return parseLong(value, ZERO_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Long parseLong(String value, int radix) {
 | 
			
		||||
        if (StringUtils.isNotBlank(value)) {
 | 
			
		||||
            try {
 | 
			
		||||
                String valueP = prepareNumberString(value);
 | 
			
		||||
                isValidRadix(valueP, radix);
 | 
			
		||||
                try {
 | 
			
		||||
                    return Long.parseLong(valueP, radix);
 | 
			
		||||
                } catch (NumberFormatException e) {
 | 
			
		||||
                    BigInteger bi = new BigInteger(valueP, radix);
 | 
			
		||||
                    if (bi.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0)
 | 
			
		||||
                        throw new NumberFormatException("Value \"" + value + "\"is greater than the maximum Long value " + Long.MAX_VALUE + " !");
 | 
			
		||||
                    if (bi.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0)
 | 
			
		||||
                        throw new NumberFormatException("Value \"" + value + "\" is  less than the minimum Long value " + Long.MIN_VALUE + " !");
 | 
			
		||||
                    Double dd = parseDouble(valueP);
 | 
			
		||||
                    if (dd != null) {
 | 
			
		||||
                        return dd.longValue();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        throw new NumberFormatException(e.getMessage());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
                throw new NumberFormatException(e.getMessage());
 | 
			
		||||
            String valueP = prepareNumberString(value);
 | 
			
		||||
            int radixValue = isValidStringAndRadix(valueP, radix, value);
 | 
			
		||||
            if (radixValue  >= 25 && radixValue  <= MAX_RADIX) {
 | 
			
		||||
                return (Long) compareIntLongValueMinMax(valueP, radixValue, Long.MAX_VALUE, Long.MIN_VALUE);
 | 
			
		||||
            }
 | 
			
		||||
            return switch (radixValue) {
 | 
			
		||||
                case MIN_RADIX -> parseBinaryStringAsSignedLong(valueP);
 | 
			
		||||
                case OCTAL_RADIX, DEC_RADIX, HEX_RADIX -> Long.parseLong(valueP, radixValue);
 | 
			
		||||
                default -> throw new IllegalArgumentException("Invalid radix: [" + radix + "]");
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int getRadix(String value, int... radixS) {
 | 
			
		||||
        return radixS.length > 0 ? radixS[0] : isHexadecimal(value) ? 16 : 10;
 | 
			
		||||
    private static int parseBinaryStringAsSignedInteger(String binaryString) {
 | 
			
		||||
        if (binaryString.length() != 32) {
 | 
			
		||||
            // Pad the binary string to 64 bits if it is not already
 | 
			
		||||
            binaryString = String.format("%32s", binaryString).replace(' ', '0');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If the MSB is 1, the number is negative in two's complement
 | 
			
		||||
        if (binaryString.charAt(0) == '1') {
 | 
			
		||||
            // Calculate the two's complement
 | 
			
		||||
            String invertedBinaryString = invertBinaryString(binaryString);
 | 
			
		||||
            int positiveValue = Integer.parseInt(invertedBinaryString, MIN_RADIX) + 1;
 | 
			
		||||
            return -positiveValue;
 | 
			
		||||
        } else {
 | 
			
		||||
            return Integer.parseInt(binaryString, MIN_RADIX);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private static long parseBinaryStringAsSignedLong(String binaryString) {
 | 
			
		||||
        if (binaryString.length() != 64) {
 | 
			
		||||
            // Pad the binary string to 64 bits if it is not already
 | 
			
		||||
            binaryString = String.format("%64s", binaryString).replace(' ', '0');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If the MSB is 1, the number is negative in two's complement
 | 
			
		||||
        if (binaryString.charAt(0) == '1') {
 | 
			
		||||
            // Calculate the two's complement
 | 
			
		||||
            String invertedBinaryString = invertBinaryString(binaryString);
 | 
			
		||||
            long positiveValue = Long.parseLong(invertedBinaryString, MIN_RADIX) + 1;
 | 
			
		||||
            return -positiveValue;
 | 
			
		||||
        } else {
 | 
			
		||||
            return Long.parseLong(binaryString, MIN_RADIX);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String invertBinaryString(String binaryString) {
 | 
			
		||||
        StringBuilder invertedString = new StringBuilder();
 | 
			
		||||
        for (char bit : binaryString.toCharArray()) {
 | 
			
		||||
            invertedString.append(bit == '0' ? '1' : '0');
 | 
			
		||||
        }
 | 
			
		||||
        return invertedString.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int getRadix10_16(String value) {
 | 
			
		||||
        int radix = isDecimal(value) > 0 ? DEC_RADIX : isHexadecimal(value);
 | 
			
		||||
        if (radix > 0) {
 | 
			
		||||
            return radix;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new NumberFormatException("Value: \"" + value + "\" is not numeric or hexDecimal format!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Float parseFloat(String value) {
 | 
			
		||||
        if (value != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                return Float.parseFloat(prepareNumberString(value));
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
        return parseFloat(value, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Float parseFloat(String value, int radix) {
 | 
			
		||||
        if (StringUtils.isNotBlank(value)) {
 | 
			
		||||
            String valueP = prepareNumberString(value);
 | 
			
		||||
            int radixValue = isValidStringAndRadix(valueP, radix, value);
 | 
			
		||||
            if (radixValue == DEC_RADIX) {
 | 
			
		||||
                return Float.parseFloat(value);
 | 
			
		||||
            } else {
 | 
			
		||||
                int bits = Integer.parseUnsignedInt(valueP, HEX_RADIX);
 | 
			
		||||
                return Float.intBitsToFloat(bits);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Double parseDouble(String value) {
 | 
			
		||||
        int radix = getRadix10_16(value);
 | 
			
		||||
        return parseDouble(value, radix);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Double parseDouble(String value, int radix) {
 | 
			
		||||
        if (value != null) {
 | 
			
		||||
            try {
 | 
			
		||||
            String valueP = prepareNumberString(value);
 | 
			
		||||
            int radixValue = isValidStringAndRadix(valueP, radix, value);
 | 
			
		||||
            if (radixValue == DEC_RADIX) {
 | 
			
		||||
                return Double.parseDouble(prepareNumberString(value));
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
            } else {
 | 
			
		||||
                long bits = Long.parseUnsignedLong(valueP, HEX_RADIX);
 | 
			
		||||
                return Double.longBitsToDouble(bits);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
@ -368,9 +468,10 @@ public class TbUtils {
 | 
			
		||||
        return parseHexToInt(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int parseHexToInt(String hex, boolean bigEndian) {
 | 
			
		||||
        byte[] data = prepareHexToBytesNumber(hex, 8);
 | 
			
		||||
        return parseBytesToInt(data, 0, data.length, bigEndian);
 | 
			
		||||
    public static Integer parseHexToInt(String value, boolean bigEndian) {
 | 
			
		||||
        String hexValue = prepareNumberString(value);
 | 
			
		||||
        String hex = bigEndian ? hexValue : reverseHexStringByOrder(hexValue);
 | 
			
		||||
        return parseInt(hex, HEX_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long parseLittleEndianHexToLong(String hex) {
 | 
			
		||||
@ -385,9 +486,10 @@ public class TbUtils {
 | 
			
		||||
        return parseHexToLong(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long parseHexToLong(String hex, boolean bigEndian) {
 | 
			
		||||
        byte[] data = prepareHexToBytesNumber(hex, 16);
 | 
			
		||||
        return parseBytesToLong(data, 0, data.length, bigEndian);
 | 
			
		||||
    public static Long parseHexToLong(String value, boolean bigEndian) {
 | 
			
		||||
        String hexValue = prepareNumberString(value);
 | 
			
		||||
        String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
 | 
			
		||||
        return parseLong(hex, HEX_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static float parseLittleEndianHexToFloat(String hex) {
 | 
			
		||||
@ -402,9 +504,10 @@ public class TbUtils {
 | 
			
		||||
        return parseHexToFloat(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static float parseHexToFloat(String hex, boolean bigEndian) {
 | 
			
		||||
        byte[] data = prepareHexToBytesNumber(hex, 8);
 | 
			
		||||
        return parseBytesToFloat(data, 0, bigEndian);
 | 
			
		||||
    public static Float parseHexToFloat(String value, boolean bigEndian) {
 | 
			
		||||
        String hexValue = prepareNumberString(value);
 | 
			
		||||
        String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
 | 
			
		||||
        return parseFloat(hex, HEX_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double parseLittleEndianHexToDouble(String hex) {
 | 
			
		||||
@ -419,39 +522,171 @@ public class TbUtils {
 | 
			
		||||
        return parseHexToDouble(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double parseHexToDouble(String hex, boolean bigEndian) {
 | 
			
		||||
        byte[] data = prepareHexToBytesNumber(hex, 16);
 | 
			
		||||
        return parseBytesToDouble(data, 0, bigEndian);
 | 
			
		||||
    public static double parseHexToDouble(String value, boolean bigEndian) {
 | 
			
		||||
        String hexValue = prepareNumberString(value);
 | 
			
		||||
        String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
 | 
			
		||||
        return parseDouble(hex, HEX_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static byte[] prepareHexToBytesNumber(String hex, int len) {
 | 
			
		||||
        int length = hex.length();
 | 
			
		||||
        if (length > len) {
 | 
			
		||||
            throw new IllegalArgumentException("Hex string is too large. Maximum 8 symbols allowed.");
 | 
			
		||||
        }
 | 
			
		||||
        if (length % 2 > 0) {
 | 
			
		||||
            throw new IllegalArgumentException("Hex string must be even-length.");
 | 
			
		||||
        }
 | 
			
		||||
        byte[] data = new byte[length / 2];
 | 
			
		||||
        for (int i = 0; i < length; i += 2) {
 | 
			
		||||
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
 | 
			
		||||
        }
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ExecutionArrayList<Byte> hexToBytes(ExecutionContext ctx, String hex) {
 | 
			
		||||
    public static ExecutionArrayList<Byte> hexToBytes(ExecutionContext ctx, String value) {
 | 
			
		||||
        String hex = prepareNumberString(value);
 | 
			
		||||
        int len = hex.length();
 | 
			
		||||
        if (len % 2 > 0) {
 | 
			
		||||
            throw new IllegalArgumentException("Hex string must be even-length.");
 | 
			
		||||
        }
 | 
			
		||||
        ExecutionArrayList<Byte> data = new ExecutionArrayList<>(ctx);
 | 
			
		||||
        for (int i = 0; i < len; i += 2) {
 | 
			
		||||
            data.add((byte) ((Character.digit(hex.charAt(i), 16) << 4)
 | 
			
		||||
                    + Character.digit(hex.charAt(i + 1), 16)));
 | 
			
		||||
        for (int i = 0; i < hex.length(); i += 2) {
 | 
			
		||||
            // Extract two characters from the hex string
 | 
			
		||||
            String byteString = hex.substring(i, i + 2);
 | 
			
		||||
            // Parse the hex string to a byte
 | 
			
		||||
            byte byteValue = (byte) Integer.parseInt(byteString, HEX_RADIX);
 | 
			
		||||
            // Add the byte to the ArrayList
 | 
			
		||||
            data.add(byteValue);
 | 
			
		||||
        }
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Integer> printUnsignedBytes(ExecutionContext ctx, List<Byte> byteArray) {
 | 
			
		||||
        ExecutionArrayList<Integer> data = new ExecutionArrayList<>(ctx);
 | 
			
		||||
        for (Byte b : byteArray) {
 | 
			
		||||
            // Convert signed byte to unsigned integer
 | 
			
		||||
            int unsignedByte = Byte.toUnsignedInt(b);
 | 
			
		||||
            data.add(unsignedByte);
 | 
			
		||||
        }
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intToHex(Integer i) {
 | 
			
		||||
        return prepareNumberHexString(i.longValue(), true, false, HEX_LEN_MIN, HEX_LEN_INT_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intToHex(Integer i, boolean bigEndian) {
 | 
			
		||||
        return prepareNumberHexString(i.longValue(), bigEndian, false, HEX_LEN_MIN, HEX_LEN_INT_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intToHex(Integer i, boolean bigEndian, boolean pref) {
 | 
			
		||||
        return prepareNumberHexString(i.longValue(), bigEndian, pref, HEX_LEN_MIN, HEX_LEN_INT_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intToHex(Integer i, boolean bigEndian, boolean pref, int len) {
 | 
			
		||||
        return prepareNumberHexString(i.longValue(), bigEndian, pref, len, HEX_LEN_INT_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String longToHex(Long l) {
 | 
			
		||||
        return prepareNumberHexString(l, true, false, HEX_LEN_MIN, HEX_LEN_LONG_MAX);
 | 
			
		||||
    }
 | 
			
		||||
    public static String longToHex(Long l, boolean bigEndian) {
 | 
			
		||||
        return prepareNumberHexString(l, bigEndian, false, HEX_LEN_MIN, HEX_LEN_LONG_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String longToHex(Long l, boolean bigEndian, boolean pref) {
 | 
			
		||||
        return prepareNumberHexString(l, bigEndian, pref, HEX_LEN_MIN, HEX_LEN_LONG_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String longToHex(Long l, boolean bigEndian, boolean pref, int len) {
 | 
			
		||||
        return prepareNumberHexString(l, bigEndian, pref, len, HEX_LEN_LONG_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intLongToString(Long number) {
 | 
			
		||||
        return intLongToString(number, DEC_RADIX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intLongToString(Long number, int radix) {
 | 
			
		||||
        return intLongToString(number, radix, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intLongToString(Long number, int radix, boolean bigEndian) {
 | 
			
		||||
        return intLongToString(number, radix, bigEndian, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String intLongToString(Long number, int radix, boolean bigEndian, boolean pref) {
 | 
			
		||||
        if (radix >= 25 && radix <= MAX_RADIX) {
 | 
			
		||||
            return Long.toString(number, radix);
 | 
			
		||||
        }
 | 
			
		||||
        return switch (radix) {
 | 
			
		||||
            case MIN_RADIX ->  Long.toBinaryString(number);
 | 
			
		||||
            case OCTAL_RADIX -> Long.toOctalString(number);
 | 
			
		||||
            case DEC_RADIX -> Long.toString(number);
 | 
			
		||||
            case HEX_RADIX -> prepareNumberHexString(number, bigEndian, pref, -1, -1);
 | 
			
		||||
            default -> throw new IllegalArgumentException("Invalid radix: [" + radix + "]");
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Number compareIntLongValueMinMax(String valueP, int radix, Number maxValue, Number minValue) {
 | 
			
		||||
        boolean isInteger = maxValue.getClass().getSimpleName().equals("Integer");
 | 
			
		||||
        try {
 | 
			
		||||
            if (isInteger) {
 | 
			
		||||
                return Integer.parseInt(valueP, radix);
 | 
			
		||||
            } else {
 | 
			
		||||
                return Long.parseLong(valueP, radix);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (NumberFormatException e) {
 | 
			
		||||
            BigInteger bi = new BigInteger(valueP, radix);
 | 
			
		||||
            long maxValueL = isInteger ? maxValue.longValue() : (long) maxValue;
 | 
			
		||||
            if (bi.compareTo(BigInteger.valueOf(maxValueL)) > 0) {
 | 
			
		||||
                throw new NumberFormatException("Value \"" + valueP + "\"is greater than the maximum " + maxValue.getClass().getSimpleName() + " value " + maxValue + " !");
 | 
			
		||||
            }
 | 
			
		||||
            long minValueL = isInteger ? minValue.longValue() : (long) minValue;
 | 
			
		||||
            if (bi.compareTo(BigInteger.valueOf(minValueL)) < 0) {
 | 
			
		||||
                throw new NumberFormatException("Value \"" + valueP + "\" is  less than the minimum " + minValue.getClass().getSimpleName() + " value " + minValue + " !");
 | 
			
		||||
            }
 | 
			
		||||
            throw new NumberFormatException(e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String prepareNumberHexString(Long number, boolean bigEndian, boolean pref, int len, int hexLenMax) {
 | 
			
		||||
        String hex = Long.toHexString(number).toUpperCase();
 | 
			
		||||
        hexLenMax = hexLenMax < 0 ? hex.length() : hexLenMax;
 | 
			
		||||
        String hexWithoutZeroFF = removeLeadingZero_FF(hex, number, hexLenMax);
 | 
			
		||||
        hexWithoutZeroFF = bigEndian ? hexWithoutZeroFF : reverseHexStringByOrder(hexWithoutZeroFF);
 | 
			
		||||
        len = len == HEX_LEN_MIN ? hexWithoutZeroFF.length() : len;
 | 
			
		||||
        String result = hexWithoutZeroFF.substring(hexWithoutZeroFF.length() - len);
 | 
			
		||||
        return pref ? "0x" + result : result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String removeLeadingZero_FF(String hex, Long number, int hexLenMax) {
 | 
			
		||||
        String hexWithoutZero = hex.replaceFirst("^0+(?!$)", ""); // Remove leading zeros except for the last one
 | 
			
		||||
        hexWithoutZero = hexWithoutZero.length() % 2 > 0 ?  "0" + hexWithoutZero : hexWithoutZero;
 | 
			
		||||
        if (number >= 0) {
 | 
			
		||||
            return hexWithoutZero;
 | 
			
		||||
        } else {
 | 
			
		||||
            String hexWithoutZeroFF = hexWithoutZero.replaceFirst("^F+(?!$)", "");
 | 
			
		||||
            hexWithoutZeroFF = hexWithoutZeroFF.length() % 2 > 0 ?  "F" + hexWithoutZeroFF : hexWithoutZeroFF;
 | 
			
		||||
            if  (hexWithoutZeroFF.length() > hexLenMax) {
 | 
			
		||||
                return hexWithoutZeroFF.substring(hexWithoutZeroFF.length() - hexLenMax);
 | 
			
		||||
            } else if (hexWithoutZeroFF.length() == hexLenMax) {
 | 
			
		||||
                return hexWithoutZeroFF;
 | 
			
		||||
            } else {
 | 
			
		||||
                return "FF" + hexWithoutZeroFF;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String floatToHex(Float f) {
 | 
			
		||||
        return floatToHex(f, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String floatToHex(Float f, boolean bigEndian) {
 | 
			
		||||
        // Convert the float to its raw integer bits representation
 | 
			
		||||
        int bits = Float.floatToRawIntBits(f);
 | 
			
		||||
 | 
			
		||||
        // Format the integer bits as a hexadecimal string
 | 
			
		||||
        String result = String.format("0x%08X", bits);
 | 
			
		||||
        return bigEndian ? result : reverseHexStringByOrder(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String doubleToHex(Double d) {
 | 
			
		||||
        return doubleToHex(d, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String doubleToHex(Double d, boolean bigEndian) {
 | 
			
		||||
        long bits = Double.doubleToRawLongBits(d);
 | 
			
		||||
 | 
			
		||||
        // Format the integer bits as a hexadecimal string
 | 
			
		||||
        String result = String.format("0x%16X", bits);
 | 
			
		||||
        return bigEndian ? result : reverseHexStringByOrder(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String base64ToHex(String base64) {
 | 
			
		||||
        return bytesToHex(Base64.getDecoder().decode(base64));
 | 
			
		||||
    }
 | 
			
		||||
@ -520,8 +755,8 @@ public class TbUtils {
 | 
			
		||||
        if (offset > data.length) {
 | 
			
		||||
            throw new IllegalArgumentException("Offset: " + offset + " is out of bounds for array with length: " + data.length + "!");
 | 
			
		||||
        }
 | 
			
		||||
        if (length > 8) {
 | 
			
		||||
            throw new IllegalArgumentException("Length: " + length + " is too large. Maximum 4 bytes is allowed!");
 | 
			
		||||
        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 + "!");
 | 
			
		||||
@ -567,7 +802,7 @@ public class TbUtils {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double parseBytesToDouble(byte[] data, int offset, boolean bigEndian) {
 | 
			
		||||
        byte[] bytesToNumber = prepareBytesToNumber(data, offset, 8, bigEndian);
 | 
			
		||||
        byte[] bytesToNumber = prepareBytesToNumber(data, offset, BYTES_LEN_LONG_MAX, bigEndian);
 | 
			
		||||
        return ByteBuffer.wrap(bytesToNumber).getDouble();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -647,6 +882,15 @@ public class TbUtils {
 | 
			
		||||
        return URLDecoder.decode(uri, StandardCharsets.UTF_8);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void raiseError(String message) {
 | 
			
		||||
        raiseError(message, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void raiseError(String message, Object value) {
 | 
			
		||||
        String msg = value == null ? message : message + " for value " + value;
 | 
			
		||||
        throw new RuntimeException(msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void parseRecursive(Object json, Map<String, Object> map, List<String> excludeList, String path, boolean pathInKey) {
 | 
			
		||||
        if (json instanceof Map.Entry) {
 | 
			
		||||
            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) json;
 | 
			
		||||
@ -687,42 +931,104 @@ public class TbUtils {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static boolean isHexadecimal(String value) {
 | 
			
		||||
        return value != null && (value.contains("0x") || value.contains("0X"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String prepareNumberString(String value) {
 | 
			
		||||
        if (value != null) {
 | 
			
		||||
            value = value.trim();
 | 
			
		||||
            if (isHexadecimal(value)) {
 | 
			
		||||
                value = value.replace("0x", "");
 | 
			
		||||
                value = value.replace("0X", "");
 | 
			
		||||
            }
 | 
			
		||||
            value = value.replace("0x", "");
 | 
			
		||||
            value = value.replace("0X", "");
 | 
			
		||||
            value = value.replace(",", ".");
 | 
			
		||||
        }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static boolean isValidRadix(String value, int radix) {
 | 
			
		||||
        for (int i = 0; i < value.length(); i++) {
 | 
			
		||||
            if (i == 0 && value.charAt(i) == '-') {
 | 
			
		||||
                if (value.length() == 1)
 | 
			
		||||
                    throw new NumberFormatException("Failed radix [" + radix + "] for value: \"" + value + "\"!");
 | 
			
		||||
                else
 | 
			
		||||
                    continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (Character.digit(value.charAt(i), radix) < 0)
 | 
			
		||||
                throw new NumberFormatException("Failed radix: [" + radix + "] for value: \"" + value + "\"!");
 | 
			
		||||
    private static int isValidStringAndRadix(String valueP, int radix, String value) {
 | 
			
		||||
        int radixValue;
 | 
			
		||||
        if (radix == 0) {
 | 
			
		||||
            radixValue = getRadix10_16(valueP);
 | 
			
		||||
        } else if (radix >= 25 && radix <= MAX_RADIX) {
 | 
			
		||||
            return radix;
 | 
			
		||||
        } else {
 | 
			
		||||
            radixValue = switch (radix) {
 | 
			
		||||
                case MIN_RADIX -> isBinary(valueP);
 | 
			
		||||
                case OCTAL_RADIX -> isOctal(valueP);
 | 
			
		||||
                case DEC_RADIX -> isDecimal(valueP);
 | 
			
		||||
                case HEX_RADIX -> isHexadecimal(valueP);
 | 
			
		||||
                default -> throw new IllegalArgumentException("Invalid radix: [" + radix + "]");
 | 
			
		||||
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (radixValue > 0) {
 | 
			
		||||
            if (value.startsWith("0x")) radixValue = HEX_RADIX;
 | 
			
		||||
            if (radixValue == HEX_RADIX) {
 | 
			
		||||
                valueP = value.startsWith("-") ? value.substring(1) : value;
 | 
			
		||||
                if (valueP.length() % 2 > 0) {
 | 
			
		||||
                    throw new NumberFormatException("The hexadecimal value: \"" + value + "\" must be of even length, or if the decimal value must be a number!");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return radixValue;
 | 
			
		||||
        } else {
 | 
			
		||||
            if (radix > 0) {
 | 
			
		||||
                throw new NumberFormatException("Failed radix [" + radix + "] for value: \"" + value + "\", must be [" + radixValue + "] !");
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new NumberFormatException("Invalid \"" + value + "\". It is not numeric or hexadecimal format!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static byte isValidIntegerToByte (Integer val) {
 | 
			
		||||
        if (val > 255 || val.intValue() < -128) {
 | 
			
		||||
    public static int isBinary(String str) {
 | 
			
		||||
        if (str == null || str.isEmpty()) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        return str.matches("[01]+") ? MIN_RADIX : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int isOctal(String str) {
 | 
			
		||||
        if (str == null || str.isEmpty()) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        return str.matches("[0-7]+") ? OCTAL_RADIX : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int isDecimal(String str) {
 | 
			
		||||
        if (str == null || str.isEmpty()) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        return str.matches("-?\\d+(\\.\\d+)?") ? DEC_RADIX : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int isHexadecimal(String str) {
 | 
			
		||||
        if (str == null || str.isEmpty()) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        return str.matches("^-?(0[xX])?[0-9a-fA-F]+$") ? HEX_RADIX : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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. " +
 | 
			
		||||
                    "Integer to byte conversion requires the use of only 8 bits (with a range of min/max = -128/255)!");
 | 
			
		||||
        } else {
 | 
			
		||||
            return val.byteValue();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String reverseHexStringByOrder(String value) {
 | 
			
		||||
        if (value.startsWith("-")) {
 | 
			
		||||
            throw new IllegalArgumentException("The hexadecimal string must be without a negative sign.");
 | 
			
		||||
        }
 | 
			
		||||
        boolean isHexPref = value.startsWith("0x");
 | 
			
		||||
        String hex = isHexPref ? value.substring(2) : value;
 | 
			
		||||
        if (hex.length() % 2 > 0) {
 | 
			
		||||
            throw new IllegalArgumentException("The hexadecimal string must be even-length.");
 | 
			
		||||
        }
 | 
			
		||||
        // Split the hex string into bytes (2 characters each)
 | 
			
		||||
        StringBuilder reversedHex = new StringBuilder(BYTES_LEN_LONG_MAX);
 | 
			
		||||
        for (int i = hex.length() - 2; i >= 0; i -= 2) {
 | 
			
		||||
            reversedHex.append(hex, i, i + 2);
 | 
			
		||||
        }
 | 
			
		||||
        String result = reversedHex.toString();
 | 
			
		||||
        return isHexPref ? "0x" + result : result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,12 +15,14 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.common.primitives.Bytes;
 | 
			
		||||
import com.google.common.primitives.Ints;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.junit.jupiter.api.AfterEach;
 | 
			
		||||
import org.junit.jupiter.api.Assertions;
 | 
			
		||||
import org.junit.jupiter.api.BeforeEach;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.mvel2.ExecutionContext;
 | 
			
		||||
import org.mvel2.ParserContext;
 | 
			
		||||
import org.mvel2.SandboxedParserConfiguration;
 | 
			
		||||
@ -31,28 +33,28 @@ import java.io.IOException;
 | 
			
		||||
import java.math.BigInteger;
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Calendar;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
 | 
			
		||||
import static java.lang.Character.MAX_RADIX;
 | 
			
		||||
import static java.lang.Character.MIN_RADIX;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class TbUtilsTest {
 | 
			
		||||
 | 
			
		||||
    private ExecutionContext ctx;
 | 
			
		||||
 | 
			
		||||
    private final String intValHex = "41EA62CC";
 | 
			
		||||
    private final float floatVal = 29.29824f;
 | 
			
		||||
    private final String floatValStr = "29.29824";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private final String floatValHexRev = "CC62EA41";
 | 
			
		||||
    private final float floatValRev = -5.948442E7f;
 | 
			
		||||
 | 
			
		||||
    private final long longVal = 0x409B04B10CB295EAL;
 | 
			
		||||
    private final String longValHex = "409B04B10CB295EA";
 | 
			
		||||
    private final long longValRev = 0xEA95B20CB1049B40L;
 | 
			
		||||
    private final String longValHexRev = "EA95B20CB1049B40";
 | 
			
		||||
    private final String doubleValStr = "1729.1729";
 | 
			
		||||
 | 
			
		||||
    private final double doubleVal = 1729.1729;
 | 
			
		||||
    private final double doubleValRev = -2.7208640774822924E205;
 | 
			
		||||
 | 
			
		||||
@ -86,10 +88,9 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertEquals(0xBAAB, TbUtils.parseHexToInt("ABBA", false));
 | 
			
		||||
        Assertions.assertEquals(0xAABBCC, TbUtils.parseHexToInt("AABBCC", true));
 | 
			
		||||
        Assertions.assertEquals(0xAABBCC, TbUtils.parseHexToInt("CCBBAA", false));
 | 
			
		||||
        Assertions.assertEquals(0xAABBCCDD, TbUtils.parseHexToInt("AABBCCDD", true));
 | 
			
		||||
        Assertions.assertEquals(0xAABBCCDD, TbUtils.parseHexToInt("DDCCBBAA", false));
 | 
			
		||||
        Assertions.assertEquals(0xDDCCBBAA, TbUtils.parseHexToInt("DDCCBBAA", true));
 | 
			
		||||
        Assertions.assertEquals(0xDDCCBBAA, TbUtils.parseHexToInt("AABBCCDD", false));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseHexToInt("AABBCCDD", true));
 | 
			
		||||
        Assertions.assertEquals(0x11BBCC22, TbUtils.parseHexToInt("11BBCC22", true));
 | 
			
		||||
        Assertions.assertEquals(0x11BBCC22, TbUtils.parseHexToInt("22CCBB11", false));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -208,15 +209,28 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertNull(TbUtils.parseInt(""));
 | 
			
		||||
        Assertions.assertNull(TbUtils.parseInt(" "));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(0).get(), TbUtils.parseInt("0"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(0).get(), TbUtils.parseInt("-0"));
 | 
			
		||||
        Assertions.assertEquals((Integer) 0, TbUtils.parseInt("0"));
 | 
			
		||||
        Assertions.assertEquals((Integer) 0, TbUtils.parseInt("-0"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(473).get(), TbUtils.parseInt("473"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-255).get(), TbUtils.parseInt("-0xFF"));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("FF"));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("-0xFF123"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-255).get(), TbUtils.parseInt("-FF"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(255).get(), TbUtils.parseInt("FF"));
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseInt("FFF"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-2578).get(), TbUtils.parseInt("-0A12"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-2578).get(), TbUtils.parseHexToInt("-0A12"));
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseHexToInt("A12", false));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-14866).get(), TbUtils.parseBigEndianHexToInt("-3A12"));
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseLittleEndianHexToInt("-A12"));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("0xFG"));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(102).get(), TbUtils.parseInt("1100110", 2));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-102).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111111111110011010", 2));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("1100210", 2));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(13158).get(), TbUtils.parseInt("11001101100110", 2));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-13158).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111100110010011010", 2));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(63).get(), TbUtils.parseInt("77", 8));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("18", 8));
 | 
			
		||||
@ -224,19 +238,32 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-255).get(), TbUtils.parseInt("-FF", 16));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("FG", 16));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(Integer.MAX_VALUE).get(), TbUtils.parseInt(Integer.toString(Integer.MAX_VALUE), 10));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt(BigInteger.valueOf(Integer.MAX_VALUE).add(BigInteger.valueOf(1)).toString(10), 10));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(Integer.MIN_VALUE).get(), TbUtils.parseInt(Integer.toString(Integer.MIN_VALUE), 10));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt(BigInteger.valueOf(Integer.MIN_VALUE).subtract(BigInteger.valueOf(1)).toString(10), 10));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(506070563).get(), TbUtils.parseInt("KonaIn", 30));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("KonaIn", 10));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt(".456", 10));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("4562.", 10));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseInt("KonaIn", MAX_RADIX + 1));
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseInt("KonaIn", MIN_RADIX - 1));
 | 
			
		||||
        Assertions.assertThrows(IllegalArgumentException.class, () -> TbUtils.parseInt("KonaIn", 12));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseFloat() {
 | 
			
		||||
        String floatValStr = "29.29824";
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(floatVal).get(), TbUtils.parseFloat(floatValStr));
 | 
			
		||||
        String floatValHex = "41EA62CC";
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseHexToFloat(floatValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseHexToFloat(floatValHex, false)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBigEndianHexToFloat(floatValHex)));
 | 
			
		||||
        String floatValHexRev = "CC62EA41";
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseLittleEndianHexToFloat(floatValHexRev)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -246,21 +273,13 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(29.298f, actualF));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseHexToFloat() {
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseHexToFloat(intValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseHexToFloat(intValHex, false)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBigEndianHexToFloat(intValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseLittleEndianHexToFloat(floatValHexRev)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void arseBytesToFloat() {
 | 
			
		||||
        byte[] floatValByte = {65, -22, 98, -52};
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBytesToFloat(floatValByte, 0)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseBytesToFloat(floatValByte, 0, false)));
 | 
			
		||||
 | 
			
		||||
        List <Byte> floatVaList = Bytes.asList(floatValByte);
 | 
			
		||||
        List<Byte> floatVaList = Bytes.asList(floatValByte);
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBytesToFloat(floatVaList, 0)));
 | 
			
		||||
        Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseBytesToFloat(floatVaList, 0, false)));
 | 
			
		||||
    }
 | 
			
		||||
@ -271,14 +290,15 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertNull(TbUtils.parseLong(""));
 | 
			
		||||
        Assertions.assertNull(TbUtils.parseLong(" "));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(0L).get(), TbUtils.parseLong("0"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(0L).get(), TbUtils.parseLong("-0"));
 | 
			
		||||
        Assertions.assertEquals((Long) 0L, TbUtils.parseLong("0"));
 | 
			
		||||
        Assertions.assertEquals((Long) 0L, TbUtils.parseLong("-0"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(473L).get(), TbUtils.parseLong("473"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-65535L).get(), TbUtils.parseLong("-0xFFFF"));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("FFFFFFFF"));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(4294967295L).get(), TbUtils.parseLong("FFFFFFFF"));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("0xFGFFFFFF"));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(13158L).get(), TbUtils.parseLong("11001101100110", 2));
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(-13158L).get(), TbUtils.parseLong("1111111111111111111111111111111111111111111111111100110010011010", 2));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("11001101100210", 2));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(9223372036854775807L).get(), TbUtils.parseLong("777777777777777777777", 8));
 | 
			
		||||
@ -295,10 +315,7 @@ public class TbUtilsTest {
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(218840926543L).get(), TbUtils.parseLong("KonaLong", 27));
 | 
			
		||||
        Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("KonaLong", 10));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseHexToLong() {
 | 
			
		||||
        Assertions.assertEquals(longVal, TbUtils.parseHexToLong(longValHex));
 | 
			
		||||
        Assertions.assertEquals(longVal, TbUtils.parseHexToLong(longValHexRev, false));
 | 
			
		||||
        Assertions.assertEquals(longVal, TbUtils.parseBigEndianHexToLong(longValHex));
 | 
			
		||||
@ -312,14 +329,20 @@ public class TbUtilsTest {
 | 
			
		||||
        Bytes.reverse(longValByte);
 | 
			
		||||
        Assertions.assertEquals(longVal, TbUtils.parseBytesToLong(longValByte, 0, 8, false));
 | 
			
		||||
 | 
			
		||||
        List <Byte> longVaList = Bytes.asList(longValByte);
 | 
			
		||||
        List<Byte> longVaList = Bytes.asList(longValByte);
 | 
			
		||||
        Assertions.assertEquals(longVal, TbUtils.parseBytesToLong(longVaList, 0, 8, false));
 | 
			
		||||
        long longValRev = 0xEA95B20CB1049B40L;
 | 
			
		||||
        Assertions.assertEquals(longValRev, TbUtils.parseBytesToLong(longVaList, 0, 8));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parsDouble() {
 | 
			
		||||
        String doubleValStr = "1729.1729";
 | 
			
		||||
        Assertions.assertEquals(java.util.Optional.of(doubleVal).get(), TbUtils.parseDouble(doubleValStr));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseHexToDouble(longValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseHexToDouble(longValHex, false)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBigEndianHexToDouble(longValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseLittleEndianHexToDouble(longValHexRev)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -329,21 +352,13 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(1729.173, actualD));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseHexToDouble() {
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseHexToDouble(longValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseHexToDouble(longValHex, false)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBigEndianHexToDouble(longValHex)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseLittleEndianHexToDouble(longValHexRev)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseBytesToDouble() {
 | 
			
		||||
        byte[] doubleValByte = {64, -101, 4, -79, 12, -78, -107, -22};
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBytesToDouble(doubleValByte, 0)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseBytesToDouble(doubleValByte, 0, false)));
 | 
			
		||||
 | 
			
		||||
        List <Byte> doubleVaList = Bytes.asList(doubleValByte);
 | 
			
		||||
        List<Byte> doubleVaList = Bytes.asList(doubleValByte);
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBytesToDouble(doubleVaList, 0)));
 | 
			
		||||
        Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseBytesToDouble(doubleVaList, 0, false)));
 | 
			
		||||
    }
 | 
			
		||||
@ -354,16 +369,17 @@ public class TbUtilsTest {
 | 
			
		||||
        ExecutionHashMap<String, Object> expectedJson = new ExecutionHashMap<>(1, ctx);
 | 
			
		||||
        expectedJson.put("hello", "world");
 | 
			
		||||
        List<Byte> expectedBytes = TbUtils.stringToBytes(ctx, expectedStr);
 | 
			
		||||
        Object actualJson =  TbUtils.decodeToJson(ctx, expectedBytes);
 | 
			
		||||
        Assertions.assertEquals(expectedJson,actualJson);
 | 
			
		||||
        Object actualJson = TbUtils.decodeToJson(ctx, expectedBytes);
 | 
			
		||||
        Assertions.assertEquals(expectedJson, actualJson);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void parseStringDecodeToJson() throws IOException {
 | 
			
		||||
        String expectedStr = "{\"hello\": \"world\"}";
 | 
			
		||||
        ExecutionHashMap<String, Object> expectedJson = new ExecutionHashMap<>(1, ctx);
 | 
			
		||||
        expectedJson.put("hello", "world");
 | 
			
		||||
        Object actualJson =  TbUtils.decodeToJson(ctx, expectedStr);
 | 
			
		||||
        Assertions.assertEquals(expectedJson,actualJson);
 | 
			
		||||
        Object actualJson = TbUtils.decodeToJson(ctx, expectedStr);
 | 
			
		||||
        Assertions.assertEquals(expectedJson, actualJson);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -386,8 +402,8 @@ public class TbUtilsTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void bytesFromList() {
 | 
			
		||||
        byte[] arrayBytes =      {(byte)0x00, (byte)0x08, (byte)0x10, (byte)0x1C, (byte)0xFF, (byte)0xFC, (byte)0xAD, (byte)0x88, (byte)0x75, (byte)0x74, (byte)0x8A, (byte)0x82};
 | 
			
		||||
        Object[] arrayMix      = {    "0x00",         8,        "16",     "0x1C",        255, (byte)0xFC,        173,        136,        117,        116,       -118,     "-126"};
 | 
			
		||||
        byte[] arrayBytes = {(byte) 0x00, (byte) 0x08, (byte) 0x10, (byte) 0x1C, (byte) 0xFF, (byte) 0xFC, (byte) 0xAD, (byte) 0x88, (byte) 0x75, (byte) 0x74, (byte) 0x8A, (byte) 0x82};
 | 
			
		||||
        Object[] arrayMix = {"0x00", 8, "16", "0x1C", 255, (byte) 0xFC, 173, 136, 117, 116, -118, "-126"};
 | 
			
		||||
 | 
			
		||||
        String expected = new String(arrayBytes);
 | 
			
		||||
        ArrayList<Byte> listBytes = new ArrayList<>(arrayBytes.length);
 | 
			
		||||
@ -397,12 +413,36 @@ public class TbUtilsTest {
 | 
			
		||||
        Assertions.assertEquals(expected, TbUtils.bytesToString(listBytes));
 | 
			
		||||
 | 
			
		||||
        ArrayList<Object> listMix = new ArrayList<>(arrayMix.length);
 | 
			
		||||
        for (Object element : arrayMix) {
 | 
			
		||||
            listMix.add(element);
 | 
			
		||||
        }
 | 
			
		||||
        Collections.addAll(listMix, arrayMix);
 | 
			
		||||
        Assertions.assertEquals(expected, TbUtils.bytesToString(listMix));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void bytesFromList_SpecSymbol() {
 | 
			
		||||
        List<String> listHex = new ArrayList<>(Arrays.asList("1D", "0x1D", "1F", "0x1F", "0x20", "0x20"));
 | 
			
		||||
        byte[] expectedBytes = new byte[]{29, 29, 31, 31, 32, 32};
 | 
			
		||||
        String actualStr = TbUtils.bytesToString(listHex);
 | 
			
		||||
        byte[] actualBytes = actualStr.getBytes();
 | 
			
		||||
        Assertions.assertArrayEquals(expectedBytes, actualBytes);
 | 
			
		||||
        Assertions.assertTrue(actualStr.isBlank());
 | 
			
		||||
        listHex = new ArrayList<>(Arrays.asList("0x21", "0x21"));
 | 
			
		||||
        expectedBytes = new byte[]{33, 33};
 | 
			
		||||
        actualStr = TbUtils.bytesToString(listHex);
 | 
			
		||||
        actualBytes = actualStr.getBytes();
 | 
			
		||||
        Assertions.assertArrayEquals(expectedBytes, actualBytes);
 | 
			
		||||
        Assertions.assertFalse(actualStr.isBlank());
 | 
			
		||||
        Assertions.assertEquals("!!", actualStr);
 | 
			
		||||
        listHex = new ArrayList<>(Arrays.asList("21", "0x21"));
 | 
			
		||||
        expectedBytes = new byte[]{21, 33};
 | 
			
		||||
        actualStr = TbUtils.bytesToString(listHex);
 | 
			
		||||
        actualBytes = actualStr.getBytes();
 | 
			
		||||
        Assertions.assertArrayEquals(expectedBytes, actualBytes);
 | 
			
		||||
        Assertions.assertFalse(actualStr.isBlank());
 | 
			
		||||
        Assertions.assertEquals("!", actualStr.substring(1));
 | 
			
		||||
        Assertions.assertEquals('\u0015', actualStr.charAt(0));
 | 
			
		||||
        Assertions.assertEquals(21, actualStr.charAt(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void bytesFromList_Error() {
 | 
			
		||||
        List<String> listHex = new ArrayList<>();
 | 
			
		||||
@ -411,14 +451,7 @@ public class TbUtilsTest {
 | 
			
		||||
            TbUtils.bytesToString(listHex);
 | 
			
		||||
            Assertions.fail("Should throw NumberFormatException");
 | 
			
		||||
        } catch (NumberFormatException e) {
 | 
			
		||||
            Assertions.assertTrue(e.getMessage().contains("Failed radix: [16] for value: \"FG\"!"));
 | 
			
		||||
        }
 | 
			
		||||
        listHex.add(0, "1F");
 | 
			
		||||
        try {
 | 
			
		||||
            TbUtils.bytesToString(listHex);
 | 
			
		||||
            Assertions.fail("Should throw NumberFormatException");
 | 
			
		||||
        } catch (NumberFormatException e) {
 | 
			
		||||
            Assertions.assertTrue(e.getMessage().contains("Failed radix: [10] for value: \"1F\"!"));
 | 
			
		||||
            Assertions.assertTrue(e.getMessage().contains("Value: \"FG\" is not numeric or hexDecimal format!"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<String> listIntString = new ArrayList<>();
 | 
			
		||||
@ -482,6 +515,161 @@ public class TbUtilsTest {
 | 
			
		||||
        String uriDecodeActual = TbUtils.decodeURI(uriEncodeActual);
 | 
			
		||||
        Assertions.assertEquals(uriOriginal, uriDecodeActual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void intToHex_Test() {
 | 
			
		||||
        Assertions.assertEquals("FFF5EE", TbUtils.intToHex(-2578));
 | 
			
		||||
        Assertions.assertEquals("0xFFD8FFA6", TbUtils.intToHex(0xFFD8FFA6, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xA6FFD8FF", TbUtils.intToHex(0xFFD8FFA6, false, true));
 | 
			
		||||
        Assertions.assertEquals("0x7FFFFFFF", TbUtils.intToHex(Integer.MAX_VALUE, true, true));
 | 
			
		||||
        Assertions.assertEquals("0x80000000", TbUtils.intToHex(Integer.MIN_VALUE, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(0xAB, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xABCD", TbUtils.intToHex(0xABCD, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xABCDEF", TbUtils.intToHex(0xABCDEF, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xCDAB", TbUtils.intToHex(0xABCDEF, false, true, 4));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(171, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(0xAB, false, true));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(0xAB, true, true, 2));
 | 
			
		||||
        Assertions.assertEquals("AB", TbUtils.intToHex(0xAB, false, false, 2));
 | 
			
		||||
        Assertions.assertEquals("AB", TbUtils.intToHex(171, true, false));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(0xAB, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.intToHex(0xAB, false, true));
 | 
			
		||||
        Assertions.assertEquals("AB", TbUtils.intToHex(0xAB, false, false));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals("0xABCD", TbUtils.intToHex(0xABCD, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xCDAB", TbUtils.intToHex(0xABCD, false, true));
 | 
			
		||||
        Assertions.assertEquals("0xCD", TbUtils.intToHex(0xABCD, true, true, 2));
 | 
			
		||||
        Assertions.assertEquals("AB", TbUtils.intToHex(0xABCD, false, false, 2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void longToHex_Test() {
 | 
			
		||||
        Assertions.assertEquals("0x7FFFFFFFFFFFFFFF", TbUtils.longToHex(Long.MAX_VALUE, true, true));
 | 
			
		||||
        Assertions.assertEquals("0x8000000000000000", TbUtils.longToHex(Long.MIN_VALUE, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xFFD8FFA6FFD8FFA6", TbUtils.longToHex(0xFFD8FFA6FFD8FFA6L, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xA6FFD8FFA6FFCEFF", TbUtils.longToHex(0xFFCEFFA6FFD8FFA6L, false, true));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.longToHex(0xABL, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xABCD", TbUtils.longToHex(0xABCDL, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xABCDEF", TbUtils.longToHex(0xABCDEFL, true, true));
 | 
			
		||||
        Assertions.assertEquals("0xABEFCDAB", TbUtils.longToHex(0xABCDEFABCDEFL, false, true, 8));
 | 
			
		||||
        Assertions.assertEquals("0xAB", TbUtils.longToHex(0xABL, true, true, 2));
 | 
			
		||||
        Assertions.assertEquals("AB", TbUtils.longToHex(0xABL, false, false, 2));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals("0xFFA6", TbUtils.longToHex(0xFFD8FFA6FFD8FFA6L, true, true, 4));
 | 
			
		||||
        Assertions.assertEquals("D8FF", TbUtils.longToHex(0xFFD8FFA6FFD8FFA6L, false, false, 4));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void numberToString_Test() {
 | 
			
		||||
        Assertions.assertEquals("11001101100110", TbUtils.intLongToString(13158L, 2));
 | 
			
		||||
        Assertions.assertEquals("1111111111111111111111111111111111111111111111111111111110011010", TbUtils.intLongToString(-102L, 2));
 | 
			
		||||
        Assertions.assertEquals("1111111111111111111111111111111111111111111111111100110010011010", TbUtils.intLongToString(-13158L, 2));
 | 
			
		||||
        Assertions.assertEquals("777777777777777777777", TbUtils.intLongToString(Long.MAX_VALUE, 8));
 | 
			
		||||
        Assertions.assertEquals("1000000000000000000000", TbUtils.intLongToString(Long.MIN_VALUE, 8));
 | 
			
		||||
        Assertions.assertEquals("9223372036854775807", TbUtils.intLongToString(Long.MAX_VALUE));
 | 
			
		||||
        Assertions.assertEquals("-9223372036854775808", TbUtils.intLongToString(Long.MIN_VALUE));
 | 
			
		||||
        Assertions.assertEquals("3366", TbUtils.intLongToString(13158L, 16));
 | 
			
		||||
        Assertions.assertEquals("FFCC9A", TbUtils.intLongToString(-13158L, 16));
 | 
			
		||||
        Assertions.assertEquals("0xFFCC9A", TbUtils.intLongToString(-13158L, 16, true, true));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals("0x0400", TbUtils.intLongToString(1024L, 16, true, true));
 | 
			
		||||
        Assertions.assertNotEquals("400", TbUtils.intLongToString(1024L, 16));
 | 
			
		||||
        Assertions.assertEquals("0xFFFC00", TbUtils.intLongToString(-1024L, 16, true, true));
 | 
			
		||||
        Assertions.assertNotEquals("0xFC00", TbUtils.intLongToString(-1024L, 16, true, true));
 | 
			
		||||
 | 
			
		||||
        Assertions.assertEquals("hazelnut", TbUtils.intLongToString(1356099454469L, MAX_RADIX));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void intToHexWithPrintUnsignedBytes_Test() {
 | 
			
		||||
        Integer value = -40;
 | 
			
		||||
        String intToHexLe = TbUtils.intToHex(value, false, true);
 | 
			
		||||
        String intToHexBe = TbUtils.intToHex(value, true, true);
 | 
			
		||||
 | 
			
		||||
        List<Byte> hexTopByteLe = TbUtils.hexToBytes(ctx, intToHexLe);
 | 
			
		||||
        List<Byte> hexTopByteBe = TbUtils.hexToBytes(ctx, intToHexBe);
 | 
			
		||||
 | 
			
		||||
        byte[] arrayBytes = {-40, -1};
 | 
			
		||||
        List<Byte> expectedHexTopByteLe = Bytes.asList(arrayBytes);
 | 
			
		||||
        List<Byte> expectedHexTopByteBe = Lists.reverse(expectedHexTopByteLe);
 | 
			
		||||
        Assertions.assertEquals(expectedHexTopByteLe, hexTopByteLe);
 | 
			
		||||
        Assertions.assertEquals(expectedHexTopByteBe, hexTopByteBe);
 | 
			
		||||
 | 
			
		||||
        List<Integer> actualLe = TbUtils.printUnsignedBytes(ctx, hexTopByteLe);
 | 
			
		||||
        List<Integer> actualBe = TbUtils.printUnsignedBytes(ctx, hexTopByteBe);
 | 
			
		||||
        List<Integer> expectedLe = Ints.asList(216, 255);
 | 
			
		||||
        List<Integer> expectedBe = Lists.reverse(expectedLe);
 | 
			
		||||
        Assertions.assertEquals(expectedLe, actualLe);
 | 
			
		||||
        Assertions.assertEquals(expectedBe, actualBe);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void floatToHex_Test() {
 | 
			
		||||
        Float value = 20.89f;
 | 
			
		||||
        String expectedHex = "0x41A71EB8";
 | 
			
		||||
        String valueHexRev = "0xB81EA741";
 | 
			
		||||
        String actual = TbUtils.floatToHex(value);
 | 
			
		||||
        Assertions.assertEquals(expectedHex, actual);
 | 
			
		||||
        Float valueActual = TbUtils.parseHexToFloat(actual);
 | 
			
		||||
        Assertions.assertEquals(value, valueActual);
 | 
			
		||||
        valueActual = TbUtils.parseHexToFloat(valueHexRev, false);
 | 
			
		||||
        Assertions.assertEquals(value, valueActual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void doubleToHex_Test() {
 | 
			
		||||
        String expectedHex = "0x409B04B10CB295EA";
 | 
			
		||||
        String actual = TbUtils.doubleToHex(doubleVal);
 | 
			
		||||
        Assertions.assertEquals(expectedHex, actual);
 | 
			
		||||
        Double valueActual = TbUtils.parseHexToDouble(actual);
 | 
			
		||||
        Assertions.assertEquals(doubleVal, valueActual);
 | 
			
		||||
        actual = TbUtils.doubleToHex(doubleVal, false);
 | 
			
		||||
        String expectedHexRev = "0xEA95B20CB1049B40";
 | 
			
		||||
        Assertions.assertEquals(expectedHexRev, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void raiseError_Test() {
 | 
			
		||||
        String message = "frequency_weighting_type must be 0, 1 or 2.";
 | 
			
		||||
        Object value = 4;
 | 
			
		||||
        try {
 | 
			
		||||
            TbUtils.raiseError(message, value);
 | 
			
		||||
            Assertions.fail("Should throw NumberFormatException");
 | 
			
		||||
        } catch (RuntimeException e) {
 | 
			
		||||
            Assertions.assertTrue(e.getMessage().contains("frequency_weighting_type must be 0, 1 or 2. for value 4"));
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            TbUtils.raiseError(message);
 | 
			
		||||
            Assertions.fail("Should throw NumberFormatException");
 | 
			
		||||
        } catch (RuntimeException e) {
 | 
			
		||||
            Assertions.assertTrue(e.getMessage().contains("frequency_weighting_type must be 0, 1 or 2."));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void isBinary_Test() {
 | 
			
		||||
        Assertions.assertEquals(2, TbUtils.isBinary("1100110"));
 | 
			
		||||
        Assertions.assertEquals(-1, TbUtils.isBinary("2100110"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void isOctal_Test() {
 | 
			
		||||
        Assertions.assertEquals(8, TbUtils.isOctal("4567734"));
 | 
			
		||||
        Assertions.assertEquals(-1, TbUtils.isOctal("8100110"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void isDecimal_Test() {
 | 
			
		||||
        Assertions.assertEquals(10, TbUtils.isDecimal("4567039"));
 | 
			
		||||
        Assertions.assertEquals(-1, TbUtils.isDecimal("C100110"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void isHexadecimal_Test() {
 | 
			
		||||
        Assertions.assertEquals(16, TbUtils.isHexadecimal("F5D7039"));
 | 
			
		||||
        Assertions.assertEquals(-1, TbUtils.isHexadecimal("K100110"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static List<Byte> toList(byte[] data) {
 | 
			
		||||
        List<Byte> result = new ArrayList<>(data.length);
 | 
			
		||||
        for (Byte b : data) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user