content: package com.espressif.iot.esptouch.util;
  
  import java.io.UnsupportedEncodingException;
  import java.util.Random;
  
  /**
   * In Java, it don't support unsigned int, so we use char to replace uint8.
   * The range of byte is [-128,127], and the range of char is [0,65535].
   * So the byte could used to store the uint8.
   * (We assume that the String could be mapped to assic)
   *
   * @author afunx
   */
  public class ByteUtil {
  
      public static final String ESPTOUCH_ENCODING_CHARSET = "UTF-8";
  
      /**
       * Put String to byte[]
       *
       * @param destbytes  the byte[] of dest
       * @param srcString  the String of src
       * @param destOffset the offset of byte[]
       * @param srcOffset  the offset of String
       * @param count      the count of dest, and the count of src as well
       */
      public static void putString2bytes(byte[] destbytes, String srcString,
                                         int destOffset, int srcOffset, int count) {
          for (int i = 0; i < count; i++) {
              destbytes[count + i] = srcString.getBytes()[i];
          }
      }
  
      /**
       * Convert uint8 into char( we treat char as uint8)
       *
       * @param uint8 the unit8 to be converted
       * @return the byte of the unint8
       */
      public static byte convertUint8toByte(char uint8) {
          if (uint8 > Byte.MAX_VALUE - Byte.MIN_VALUE) {
              throw new RuntimeException("Out of Boundary");
          }
          return (byte) uint8;
      }
  
      /**
       * Convert char into uint8( we treat char as uint8 )
       *
       * @param b the byte to be converted
       * @return the char(uint8)
       */
      public static char convertByte2Uint8(byte b) {
          // char will be promoted to int for char don't support & operator
          // & 0xff could make negatvie value to positive
          return (char) (b & 0xff);
      }
  
      /**
       * Convert byte[] into char[]( we treat char[] as uint8[])
       *
       * @param bytes the byte[] to be converted
       * @return the char[](uint8[])
       */
      public static char[] convertBytes2Uint8s(byte[] bytes) {
          int len = bytes.length;
          char[] uint8s = new char[len];
          for (int i = 0; i < len; i++) {
              uint8s[i] = convertByte2Uint8(bytes[i]);
          }
          return uint8s;
      }
  
      /**
       * Put byte[] into char[]( we treat char[] as uint8[])
       *
       * @param destUint8s the char[](uint8[]) array
       * @param srcBytes   the byte[]
       * @param destOffset the offset of char[](uint8[])
       * @param srcOffset  the offset of byte[]
       * @param count      the count of dest, and the count of src as well
       */
      public static void putbytes2Uint8s(char[] destUint8s, byte[] srcBytes,
                                         int destOffset, int srcOffset, int count) {
          for (int i = 0; i < count; i++) {
              destUint8s[destOffset + i] = convertByte2Uint8(srcBytes[srcOffset
                      + i]);
          }
      }
  
      /**
       * Convert byte to Hex String
       *
       * @param b the byte to be converted
       * @return the Hex String
       */
      public static String convertByte2HexString(byte b) {
          char u8 = convertByte2Uint8(b);
          return Integer.toHexString(u8);
      }
  
      /**
       * Convert char(uint8) to Hex String
       *
       * @param u8 the char(uint8) to be converted
       * @return the Hex String
       */
      public static String convertU8ToHexString(char u8) {
          return Integer.toHexString(u8);
      }
  
      /**
       * Split uint8 to 2 bytes of high byte and low byte. e.g. 20 = 0x14 should
       * be split to [0x01,0x04] 0x01 is high byte and 0x04 is low byte
       *
       * @param uint8 the char(uint8)
       * @return the high and low bytes be split, byte[0] is high and byte[1] is
       * low
       */
      public static byte[] splitUint8To2bytes(char uint8) {
          if (uint8 < 0 || uint8 > 0xff) {
              throw new RuntimeException("Out of Boundary");
          }
          String hexString = Integer.toHexString(uint8);
          byte low;
          byte high;
          if (hexString.length() > 1) {
              high = (byte) Integer.parseInt(hexString.substring(0, 1), 16);
              low = (byte) Integer.parseInt(hexString.substring(1, 2), 16);
          } else {
              high = 0;
              low = (byte) Integer.parseInt(hexString.substring(0, 1), 16);
          }
          byte[] result = new byte[]{high, low};
          return result;
      }
  
      /**
       * Combine 2 bytes (high byte and low byte) to one whole byte
       *
       * @param high the high byte
       * @param low  the low byte
       * @return the whole byte
       */
      public static byte combine2bytesToOne(byte high, byte low) {
          if (high < 0 || high > 0xf || low < 0 || low > 0xf) {
              throw new RuntimeException("Out of Boundary");
          }
          return (byte) (high << 4 | low);
      }
  
      /**
       * Combine 2 bytes (high byte and low byte) to
       *
       * @param high the high byte
       * @param low  the low byte
       * @return the char(u8)
       */
      public static char combine2bytesToU16(byte high, byte low) {
          char highU8 = convertByte2Uint8(high);
          char lowU8 = convertByte2Uint8(low);
          return (char) (highU8 << 8 | lowU8);
      }
  
      /**
       * Generate the random byte to be sent
       *
       * @return the random byte
       */
      private static byte randomByte() {
          return (byte) (127 - new Random().nextInt(256));
      }
  
      /**
       * Generate the random byte to be sent
       *
       * @param len the len presented by u8
       * @return the byte[] to be sent
       */
      public static byte[] randomBytes(char len) {
          byte[] data = new byte[len];
          for (int i = 0; i < len; i++) {
              data[i] = randomByte();
          }
          return data;
      }
  
      public static byte[] genSpecBytes(char len) {
          byte[] data = new byte[len];
          for (int i = 0; i < len; i++) {
              data[i] = '1';
          }
          return data;
      }
  
      /**
       * Generate the random byte to be sent
       *
       * @param len the len presented by byte
       * @return the byte[] to be sent
       */
      public static byte[] randomBytes(byte len) {
          char u8 = convertByte2Uint8(len);
          return randomBytes(u8);
      }
  
      /**
       * Generate the specific byte to be sent
       *
       * @param len the len presented by byte
       * @return the byte[]
       */
      public static byte[] genSpecBytes(byte len) {
          char u8 = convertByte2Uint8(len);
          return genSpecBytes(u8);
      }
  
      public static String parseBssid(byte[] bssidBytes, int offset, int count) {
          byte[] bytes = new byte[count];
          System.arraycopy(bssidBytes, offset, bytes, 0, count);
          return parseBssid(bytes);
      }
  
      /**
       * parse "24,-2,52,-102,-93,-60" to "18,fe,34,9a,a3,c4"
       * parse the bssid from hex to String
       *
       * @param bssidBytes the hex bytes bssid, e.g. {24,-2,52,-102,-93,-60}
       * @return the String of bssid, e.g. 18fe349aa3c4
       */
      public static String parseBssid(byte[] bssidBytes) {
          StringBuilder sb = new StringBuilder();
          int k;
          String hexK;
          String str;
          for (byte bssidByte : bssidBytes) {
              k = 0xff & bssidByte;
              hexK = Integer.toHexString(k);
              str = ((k < 16) ? ("0" + hexK) : (hexK));
              System.out.println(str);
              sb.append(str);
          }
          return sb.toString();
      }
  
      /**
       * @param string the string to be used
       * @return the byte[] of String according to {@link #ESPTOUCH_ENCODING_CHARSET}
       */
      public static byte[] getBytesByString(String string) {
          try {
              return string.getBytes(ESPTOUCH_ENCODING_CHARSET);
          } catch (UnsupportedEncodingException e) {
              throw new IllegalArgumentException("the charset is invalid");
          }
      }
  
      private static void test_splitUint8To2bytes() {
          // 20 = 0x14
          byte[] result = splitUint8To2bytes((char) 20);
          if (result[0] == 1 && result[1] == 4) {
              System.out.println("test_splitUint8To2bytes(): pass");
          } else {
              System.out.println("test_splitUint8To2bytes(): fail");
          }
      }
  
      private static void test_combine2bytesToOne() {
          byte high = 0x01;
          byte low = 0x04;
          if (combine2bytesToOne(high, low) == 20) {
              System.out.println("test_combine2bytesToOne(): pass");
          } else {
              System.out.println("test_combine2bytesToOne(): fail");
          }
      }
  
      private static void test_convertChar2Uint8() {
          byte b1 = 'a';
          // -128: 1000 0000 should be 128 in unsigned char
          // -1: 1111 1111 should be 255 in unsigned char
          byte b2 = (byte) -128;
          byte b3 = (byte) -1;
          if (convertByte2Uint8(b1) == 97 && convertByte2Uint8(b2) == 128
                  && convertByte2Uint8(b3) == 255) {
              System.out.println("test_convertChar2Uint8(): pass");
          } else {
              System.out.println("test_convertChar2Uint8(): fail");
          }
      }
  
      private static void test_convertUint8toByte() {
          char c1 = 'a';
          // 128: 1000 0000 should be -128 in byte
          // 255: 1111 1111 should be -1 in byte
          char c2 = 128;
          char c3 = 255;
          if (convertUint8toByte(c1) == 97 && convertUint8toByte(c2) == -128
                  && convertUint8toByte(c3) == -1) {
              System.out.println("test_convertUint8toByte(): pass");
          } else {
              System.out.println("test_convertUint8toByte(): fail");
          }
      }
  
      private static void test_parseBssid() {
          byte b[] = {15, -2, 52, -102, -93, -60};
          if (parseBssid(b).equals("0ffe349aa3c4")) {
              System.out.println("test_parseBssid(): pass");
          } else {
              System.out.println("test_parseBssid(): fail");
          }
      }
  
      public static void main(String args[]) {
          test_convertUint8toByte();
          test_convertChar2Uint8();
          test_splitUint8To2bytes();
          test_combine2bytesToOne();
          test_parseBssid();
      }
  
  }
  