NumberUtils 协议中对数据的处理类

178 阅读5分钟
/**
 * 数值辅助类
 */

package android.car.utils;

import android.text.TextUtils;

/**
 * NumberUtils
 */
public class NumberUtils {
    /**
     * 在byte数组的一部分中查找另一个byte数组一部分
     *
     * @param srcArr    需要进行查找的源数组
     * @param srcStart  源开始
     * @param srcEnd    源结束(不包括此)
     * @param findArr   要查找的数组
     * @param findStart 查找开始
     * @param findEnd   查找结束(不包括此)
     * @return 找到的偏移(相对于srcOffset), 未找到返回-1
     * @throws IllegalArgumentException 如果需要查找的大小为0, 则返回srcStart
     */
    public static int byteArrayFind(byte[] srcArr, int srcStart, int srcEnd, byte[] findArr, int findStart, int findEnd)
            throws IllegalArgumentException {
        int pos = -1;
        if (srcStart < 0 || findStart < 0 || srcEnd < 0 || findEnd < 0) {
            throw new IllegalArgumentException("ByteArrayFind: array size or offset < 0 !!");
        }

        if (srcArr.length < srcEnd || findArr.length < findEnd) {
            throw new IllegalArgumentException("ByteArrayFind: array size out of range!");
        }

        int findSize = findEnd - findStart;
        if (findSize == 0)
            return srcStart;

        /* 对于如果srcSize小于findSize的情况, 不会进入循环, 所以无需特别处理 */
        for (int i = srcStart; i < srcEnd - findSize + 1; ++i) {
            int cmp = byteArrayCompare(srcArr, i, findArr, findStart, findSize);
            if (cmp == 0) {
                pos = i;
                break;
            }
        }
        return pos;
    }

    /**
     * 在byte数组中找到byte
     *
     * @param srcArr   需要进行查找的源数组
     * @param srcStart 源开始
     * @param srcEnd   源结束(不包括此)
     * @param findByte 要查找的byte
     * @return 找到的偏移(相对于srcOffset), 未找到返回-1
     * @throws IllegalArgumentException 如果需要查找的大小为0, 则返回srcStart
     */
    public static int byteArrayFind(byte[] srcArr, int srcStart, int srcEnd, byte findByte)
            throws IllegalArgumentException {
        int pos = -1;
        if (srcArr == null || srcStart < 0 || srcEnd <= 0 || srcArr.length < srcEnd) {
            throw new IllegalArgumentException("ByteArrayFind: array arg error !!");
        }

        /* 对于如果srcSize小于findSize的情况, 不会进入循环, 所以无需特别处理 */
        for (int i = srcStart; i < srcEnd; ++i) {
            if (srcArr[i] == findByte) {
                pos = i;
                break;
            }
        }
        return pos;
    }

    /*
     * 比较两个byte数组的一部分
     *
     * @param srcArr 源数组
     * @param srcStart 比较偏移
     * @param dstArr 目的数组
     * @param dstStart 目的偏移
     * @param cmpSize 需要比较的大小
     * @return src == dst 返回0, src < dst 返回<0, src > dst 返回>0
     *  函数未对数组的大小进行判断, 需调用者进行判断
     */
    public static int byteArrayCompare(byte[] srcArr, int srcStart, byte[] dstArr, int dstStart, int cmpSize) {
        int cmp;
        for (int i = 0; i < cmpSize; ++i) {
            cmp = srcArr[srcStart + i] - dstArr[dstStart + i];
            if (cmp != 0) {
                return cmp;
            }
        }
        return 0;
    }

    /**
     * Byte 转为十六进制字串, 00~FF
     *
     * @param b         要转换的值
     * @param upperCase 是否转为大写
     * @return 返回转换好的字符串
     */
    public static String byteToHexString(byte b, boolean upperCase) {
        int high = (b >> 4) & 0xF;
        int low = b & 0xF;
        if (upperCase) {
            char[] str = {
                    HEX_UPPER_CHAR_TABLE[high], HEX_UPPER_CHAR_TABLE[low]
            };
            return new String(str);
        } else {
            char[] str = {
                    HEX_LOWER_CHAR_TABLE[high], HEX_LOWER_CHAR_TABLE[low]
            };
            return new String(str);
        }
    }

    static final char[] HEX_UPPER_CHAR_TABLE = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };
    static final char[] HEX_LOWER_CHAR_TABLE = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    /**
     * 将byte数组转为十六进制字串, 使用split分隔
     *
     * @param arr    要转换的数组
     * @param offset 偏移
     * @param size   大小
     * @param split  分隔符
     * @return 返回字符串
     */
    public static String byteArrayToHexString(byte[] arr, int offset, int size, String split) {
        if (arr == null || offset < 0 || size < 0 || offset + size > arr.length) {
            throw new IllegalArgumentException("ByteArrayToHexString arg error!");
        }

        if (size == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder(size * 4);
        sb.append(byteToHexString(arr[0], true));
        for (int i = 1; i < size; i++) {
            sb.append(split);
            sb.append(byteToHexString(arr[offset + i], true));
        }

        return sb.toString();
    }

    public static String byteArrayToHexString(byte[] arr, String split) {
        return byteArrayToHexString(arr, 0, arr.length, split);
    }

    static final String[] BINARY_STRING_TABLE = {
            "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100",
            "1101", "1110", "1111"
    };

    /**
     * Byte 转为二进制字串, 00000000~11111111
     *
     * @param b 要转换的值
     * @return 返回转换好的字符串
     */
    public static String byteToBinaryString(byte b) {
        int high = (b >> 4) & 0xF;
        int low = b & 0xF;
        return BINARY_STRING_TABLE[high] + BINARY_STRING_TABLE[low];
    }

    /**
     * 将byte数组转为十六进制字串, 使用split分隔
     *
     * @param arr    要转换的数组
     * @param offset 偏移
     * @param size   大小
     * @param split  分隔符
     * @return 返回字符串
     */
    public static String byteArrayToBinaryString(byte[] arr, int offset, int size, String split) {
        if (arr == null || offset < 0 || size < 0 || offset + size > arr.length) {
            throw new IllegalArgumentException("ByteArrayToHexString arg error!");
        }

        if (size == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder(size * 4);
        sb.append(byteToBinaryString(arr[0]));
        for (int i = 1; i < size; i++) {
            sb.append(split);
            sb.append(byteToBinaryString(arr[offset + i]));
        }

        return sb.toString();
    }

    public static String byteArrayToBinaryString(byte[] arr, String split) {
        return byteArrayToBinaryString(arr, 0, arr.length, split);
    }

    /**
     * 将int数组转为byte数据
     *
     * @param array int array
     * @return 返回byte[]
     */
    public static byte[] intArrayToByteArray(int[] array) {
        byte[] byteArr = new byte[array.length];
        for (int i = 0; i < array.length; i++) {
            byteArr[i] = (byte) (array[i] & 0xFF);
        }
        return byteArr;
    }

    /**
     * 将int写入到ByteArray
     *
     * @param value  value
     * @param arr    out arr
     * @param offset offset
     */
    public static void intWriteToByteArray(int value, byte[] arr, int offset) {
        arr[offset] = (byte) (value & 0xFF);
        arr[offset + 1] = (byte) (value >> 8 & 0xFF);
        arr[offset + 2] = (byte) (value >> 16 & 0xFF);
        arr[offset + 3] = (byte) (value >> 24 & 0xFF);
    }

    /**
     * 合成int
     *
     * @param b3 byte3
     * @param b2 byte2
     * @param b1 byte1
     * @param b0 byte0
     * @return int value
     */
    public static int makeIntByByte(int b3, int b2, int b1, int b0) {
        return (b3 & 0xFF) << 24 | (b2 & 0xFF) << 16 | (b1 & 0xFF) << 8 | (b0 & 0xFF);
    }

    public static int makeIntByByte(byte b3, byte b2, byte b1, byte b0) {
        return (b3 & 0xFF) << 24 | (b2 & 0xFF) << 16 | (b1 & 0xFF) << 8 | (b0 & 0xFF);
    }

    public static int makeIntByShort(int h, int l) {
        return (h & 0xFFFF) << 16 | (l & 0xFFFF);
    }

    public static int makeIntByShort(short h, short l) {
        return (h & 0xFFFF) << 16 | (l & 0xFFFF);
    }

    public static short makeShort(int h, int l) {
        return (short) ((h & 0xFF) << 8 | (l & 0xFF));
    }

    public static short makeShort(byte h, byte l) {
        return (short) ((h & 0xFF) << 8 | (l & 0xFF));
    }

    public static long makeLongByInt(int h, int l) {
        return (long) ((h & 0xFFFFFFFF) << 32 | (l & 0xFFFFFFFF));
    }

    public static long makeLongByShort(short s3, short s2, short s1, short s0) {
        return (s3 & 0xFFFF) << 24 | (s2 & 0xFFFF) << 16 | (s1 & 0xFFFF) << 8 | (s0 & 0xFFFF);
    }

    public static long makeLongByByte(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) {
        return ((b7 & 0xFF) << 56 | (b6 & 0xFF) << 48 | (b5 & 0xFF) << 40 | (b4 & 0xFF) << 32 | (b3 & 0xFF) << 24
                | (b2 & 0xFF) << 16 | (b1 & 0xFF) << 8 | (b0 & 0xFF));
    }

    /**
     * 测试bit
     *
     * @param val    byte val
     * @param bitPos pos for test bit
     * @return bit is 1 return true
     */
    public static boolean testBit(byte val, int bitPos) {
        return (val & (1 << bitPos)) == (1 << bitPos);
    }

    public static boolean testBit(short val, int bitPos) {
        return (val & (1 << bitPos)) == (1 << bitPos);
    }

    public static boolean testBit(int val, int bitPos) {
        return (val & (1 << bitPos)) == (1 << bitPos);
    }

    public static boolean testBit(long val, int bitPos) {
        return (val & (1 << bitPos)) == (1 << bitPos);
    }

    /**
     * 设置bit
     *
     * @param val    value
     * @param bitPos pos for set
     * @return new value
     */
    public static int setBit(int val, int bitPos) {
        return val | (1 << bitPos);
    }

    public static int clearBit(int val, int bitPos) {
        return val & ~(1 << bitPos);
    }

    /**
     * 测试数据范围
     *
     * @param val value
     * @param min min value
     * @param max max value
     * @return in range return true
     */
    public static boolean isInRange(int val, int min, int max) {
        return val >= min && val <= max;
    }

    public static boolean isInRange(float val, float min, float max) {
        return val >= min && val <= max;
    }

    public static boolean isInRange(byte val, byte min, byte max) {
        return val >= min && val <= max;
    }

    public static boolean isInRange(char val, char min, char max) {
        return val >= min && val <= max;
    }

    public static boolean isInRange(long val, long min, long max) {
        return val >= min && val <= max;
    }

    static final int[] BITS_MASK = {
            0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
            0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF,
            0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
            0xFFFFFFFF
    };

    /**
     * 按bit取值 从val中的第pos位开始取count位的数据
     * EX: val = 01100001B; pos=5; count=2; return 11B = 3
     * 函数不检测参数的范围
     *
     * @param val      value
     * @param bitPos   bit pos
     * @param bitCount bit count
     * @return value
     */
    public static int getBitsValue(int val, int bitPos, int bitCount) {
        if (bitCount >= 0 && bitCount < BITS_MASK.length) {
            return val >> bitPos & BITS_MASK[bitCount];
        }
        throw new IllegalArgumentException("count must be 0~32");
    }

    public static int getBitsValue(byte val, int bitPos, int bitCount) {
        if (bitCount >= 0 && bitCount < BITS_MASK.length) {
            return val >> bitPos & BITS_MASK[bitCount];
        }
        throw new IllegalArgumentException("count must be 0~32");
    }

    /**
     * 按bit设定值, 向srcVal的第bitPos位开始的bitCount位数据设置为setVal
     * 给指定的bit位设置值
     * @param srcVal   src   value
     * @param bitPos   bit pos
     * @param bitCount bit count
     * @param setVal   set value
     * @return value
     */
    public static int setBitsValue(int srcVal, int bitPos, int bitCount, int setVal) {
        if (bitCount >= 0 && bitCount < BITS_MASK.length) {
            return (srcVal & ~(BITS_MASK[bitCount] << bitPos)) | ((setVal & BITS_MASK[bitCount]) << bitPos);
        }
        throw new IllegalArgumentException("count must be 0~32");
    }

    /**
     * 获取int中指定byte的值
     *
     * @param val value
     * @param pos pos
     * @return new value
     */
    public static int getByteValue(int val, int pos) {
        return (val >> pos * 8) & 0xFF;
    }

    /**
     * 获取int中的低字
     *
     * @param val value
     * @return value
     */
    public static int getLowShort(int val) {
        return val & 0xFFFF;
    }

    /**
     * 获取int中的高字
     *
     * @param val value
     * @return value
     */
    public static int getHighShort(int val) {
        return (val >> 16) & 0xFFFF;
    }

    /**
     * 获取int中的低字
     *
     * @param val value
     * @return value
     */
    public static int getLowWord(int val) {
        return val & 0xFFFF;
    }

    /**
     * 获取int中的高字
     *
     * @param val value
     * @return value
     */
    public static int getHighWord(int val) {
        return (val >> 16) & 0xFFFF;
    }

    /**
     * 获取long中指定byte的值
     *
     * @param val value
     * @param pos pos
     * @return value
     */
    public static int getByteValue(long val, int pos) {
        return (int) ((val >> pos * 8) & 0xFF);
    }

    /**
     * 获取long中的低字
     *
     * @param val value
     * @return value
     */
    public static int getLowInt(long val) {
        return (int) (val & 0xFFFFFFFF);
    }

    /**
     * 获取long中的高字
     *
     * @param val value
     * @return value
     */
    public static int getHighInt(long val) {
        return (int) ((val >> 32) & 0xFFFFFFFF);
    }

    /**
     * 修正数据的范围
     *
     * @param val value
     * @param min min
     * @param max max
     * @return fix value
     */
    public static int fixRange(int val, int min, int max) {
        if (min > max) {
            int tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    public static long fixRange(long val, long min, long max) {
        if (min > max) {
            long tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    public static byte fixRange(byte val, byte min, byte max) {
        if (min > max) {
            byte tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    public static char fixRange(char val, char min, char max) {
        if (min > max) {
            char tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    public static float fixRange(float val, float min, float max) {
        if (min > max) {
            float tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    public static double fixRange(double val, double min, double max) {
        if (min > max) {
            double tmp = min;
            min = max;
            max = tmp;
        }

        if (val < min)
            return min;
        if (val > max)
            return max;
        return val;
    }

    /**
     * 解析字符串为boolean
     *
     * @param str string
     * @param def default value when fail
     * @return "0"/"n"/"N"/"no"/"false"/"off" = false
     */
    public static boolean parseBoolean(String str, boolean def) {
        boolean result = def;
        if (str != null) {
            if (str.length() == 1) {
                char ch = str.charAt(0);
                if (ch == '0' || ch == 'n' || ch == 'N')
                    result = false;
                else if (ch == '1' || ch == 'y' || ch == 'Y')
                    result = true;
            } else if (str.length() > 1) {
                if ("yes".equalsIgnoreCase(str) || "true".equalsIgnoreCase(str) || "on".equalsIgnoreCase(str)) {
                    result = true;
                } else if ("no".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str) || "off".equalsIgnoreCase(str)) {
                    result = false;
                }
            }
        }
        return result;
    }

    /**
     * 解析字符串为Int
     *
     * @param str string
     * @param def default value when fail
     * @return 字符串为空或解析异常时返回def
     */
    public static int parseInt(String str, int def) {
        int result = def;
        if (!TextUtils.isEmpty(str)) {
            try {
                return Integer.parseInt(str);
            } catch (Exception e) {
            }
        }
        return result;
    }

    /**
     * 解析字符串为Int
     *
     * @param str   string
     * @param radix radix
     * @param def   default value when fail
     * @return 字符串为空或解析异常时返回def
     */
    public static int parseInt(String str, int radix, int def) {
        int result = def;
        if (!TextUtils.isEmpty(str)) {
            try {
                return Integer.parseInt(str, radix);
            } catch (Exception e) {
            }
        }
        return result;
    }

    /**
     * 解码string为int, 会处理10,16,8进制
     *
     * @param str number str
     * @param def default value when fail
     * @return 字符串为空或解析异常时返回def
     */
    public static int integerDecode(String str, int def) {
        int result = def;
        if (!TextUtils.isEmpty(str)) {
            try {
                return Integer.decode(str);
            } catch (Exception e) {
            }
        }
        return result;
    }

    /**
     * 解析字符串为int[]
     *
     * @param str
     * @param regx 用于split的regx
     * @return 返回null代表参数错误, 其它情况返回列表, 如果列表中有不合法的数值, 则填充0
     */
    public static int[] parseIntList(String str, String regx) {
        if (TextUtils.isEmpty(regx) || TextUtils.isEmpty(str)) {
            return null;
        }

        String[] strList = str.split(regx);
        int[] intList = new int[strList.length];
        for (int i = 0; i < strList.length; ++i) {
            intList[i] = integerDecode(strList[i], 0);
        }
        return intList;
    }

    /**
     * Converts an array of C chars (mapped to Java bytes) in the representation of a C-style String
     * that ends in the char array with the '\0' character to Java String bytes.
     *
     * @param bytes  The bytes from which source to convert
     * @param offset The index of the first accessed byte
     * @param len    The length of the bytes to convert
     */
    public static byte[] cstringBytesToJstringBytes(byte[] bytes, int offset, int len) {
        if ((offset | len) < 0 || bytes.length < offset + len) {
            throw new ArrayIndexOutOfBoundsException();
        }

        int size = 0;
        for (int i = offset, last = offset + len - 1; i <= last; i++) {
            if (bytes[i] == 0 /* '\0' */) break;
            size++;
        }
        byte[] result = new byte[size];
        System.arraycopy(bytes, offset, result, 0, size);
        return result;
    }
}