Okio source code reading notes (3) ByteString

Actually ByteString is nothing to look at. Before I read it, I thought there was important content, but after reading it, I found out that there is no, but since I have read it, I will record it.

ByteString encapsulates the following points

1. It is to convert some input types (string/byte array/ByteBuffer/byte) into byte array, and encapsulate it into a new ByteString to return.

For example ByteString.of(...)

2. It encapsulates the comparison and encryption operations of ByteString, which is convenient to use

比如ByteString.encode(...)、base64(...)、md5(...)、sha1()、....

ByteString.startWith(...)、endWith(...)

Pretty much all that stuff.

public class ByteString implements Serializable, Comparable<ByteString> {
    static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /** A singleton empty {@code ByteString}. */
    public static final ByteString EMPTY = ByteString.of();
    final byte[] data;
    transient int hashCode; // Lazily computed; 0 if unknown.
    transient String utf8; // Lazily computed.
    ByteString(byte[] data) {
        this.data = data; // Trusted internal constructor doesn't clone data.
    }
    /**
     * Returns a new byte string containing a clone of the bytes of {@code data}.
     */
    public static ByteString of(byte... data) {
        if (data == null) {
            throw new IllegalArgumentException("data == null");
        }
        return new ByteString(data.clone());
    }
    //Copy the contents of byteCount bytes in the data cache to a new byte[] and return a new ByteString
    public static ByteString of(byte[] data, int offset, int byteCount) {
        if (data == null) {
            throw new IllegalArgumentException("data == null");
        }
        checkOffsetAndCount(data.length, offset, byteCount);//Check parameters
        byte[] copy = new byte[byteCount];
        System.arraycopy(data, offset, copy, 0, byteCount);
        return new ByteString(copy);
    }
	//Copy the contents of 0-data.remaining() in the data cache to the copy array and return a new ByteString
    public static ByteString of(ByteBuffer data) {
        if (data == null) {
            throw new IllegalArgumentException("data == null");
        }
        byte[] copy = new byte[data.remaining()];//
        data.get(copy);
        return new ByteString(copy);
    }

    // Convert string to byte[] and store it in the new ByteString for return, byteString.utf8 saves the original string of string
    public static ByteString encodeUtf8(String s) {
        if (s == null) {
            throw new IllegalArgumentException("s == null");
        }
        ByteString byteString = new ByteString(s.getBytes(Util.UTF_8));
        byteString.utf8 = s;
        return byteString;
    }

    /** Returns a new byte string containing the {@code charset}-encoded bytes of {@code s}. */
    public static ByteString encodeString(String s, Charset charset) {
        if (s == null) {
            throw new IllegalArgumentException("s == null");
        }
        if (charset == null) {
            throw new IllegalArgumentException("charset == null");
        }
        return new ByteString(s.getBytes(charset));
    }

    //Get the UTF8 string corresponding to data[]
    public String utf8() {
        String result = utf8;
        // We don't care if we double-allocate in racy code.
        return result != null ? result : (utf8 = new String(data, Util.UTF_8));
    }

    //Convert data[] to charset string
    public String string(Charset charset) {
        if (charset == null) {
            throw new IllegalArgumentException("charset == null");
        }
        return new String(data, charset);
    }

    //Encode data[] with Base64 and return
    public String base64() {
        return Base64.encode(data);
    }

    //Encrypt data[] with md5 and return
    public ByteString md5() {
        return digest("MD5");
    }

    //Encrypt data[] with sha1 and return
    public ByteString sha1() {
        return digest("SHA-1");
    }

    //Encrypt data with sha256 and return
    public ByteString sha256() {
        return digest("SHA-256");
    }

    //Encrypt data with sha512 and return
    public ByteString sha512() {
        return digest("SHA-512");
    }
	//encrypted api
    private ByteString digest(String algorithm) {
        try {
            return ByteString.of(MessageDigest.getInstance(algorithm).digest(data));
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        }
    }

    /** Returns the 160-bit SHA-1 HMAC of this byte string. */
    public ByteString hmacSha1(ByteString key) {
        return hmac("HmacSHA1", key);
    }

    /** Returns the 256-bit SHA-256 HMAC of this byte string. */
    public ByteString hmacSha256(ByteString key) {
        return hmac("HmacSHA256", key);
    }

    /** Returns the 512-bit SHA-512 HMAC of this byte string. */
    public ByteString hmacSha512(ByteString key) {
        return hmac("HmacSHA512", key);
    }

    private ByteString hmac(String algorithm, ByteString key) {
        try {
            Mac mac = Mac.getInstance(algorithm);
            mac.init(new SecretKeySpec(key.toByteArray(), algorithm));
            return ByteString.of(mac.doFinal(data));
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException(e);
        }
    }

    //If data is the byte array of the url, encode the byte array of the url with Base64, and return the encoded string
    public String base64Url() {
        return Base64.encodeUrl(data);
    }

    /**
     * Decodes the Base64-encoded bytes and returns their value as a byte string.
     * Returns null if {@code base64} is not a Base64-encoded sequence of bytes.
     */
    public static @Nullable
    ByteString decodeBase64(String base64) {
        if (base64 == null) {
            throw new IllegalArgumentException("base64 == null");
        }
        byte[] decoded = Base64.decode(base64);
        return decoded != null ? new ByteString(decoded) : null;
    }

    /** Returns this byte string encoded in hexadecimal. */
    public String hex() {
        char[] result = new char[data.length * 2];
        int c = 0;
        for (byte b : data) {
            result[c++] = HEX_DIGITS[(b >> 4) & 0xf];
            result[c++] = HEX_DIGITS[b & 0xf];
        }
        return new String(result);
    }

    /** Decodes the hex-encoded bytes and returns their value a byte string. */
    public static ByteString decodeHex(String hex) {
        if (hex == null) {
            throw new IllegalArgumentException("hex == null");
        }
        if (hex.length() % 2 != 0) {
            throw new IllegalArgumentException("Unexpected hex string: " + hex);
        }

        byte[] result = new byte[hex.length() / 2];
        for (int i = 0; i < result.length; i++) {
            int d1 = decodeHexDigit(hex.charAt(i * 2)) << 4;
            int d2 = decodeHexDigit(hex.charAt(i * 2 + 1));
            result[i] = (byte) (d1 + d2);
        }
        return of(result);
    }

    private static int decodeHexDigit(char c) {
        if (c >= '0' && c <= '9') {
            return c - '0';
        }
        if (c >= 'a' && c <= 'f') {
            return c - 'a' + 10;
        }
        if (c >= 'A' && c <= 'F') {
            return c - 'A' + 10;
        }
        throw new IllegalArgumentException("Unexpected hex digit: " + c);
    }

    //Write the content of the input stream in to a byte array, encapsulate it into a ByteString and return it
    public static ByteString read(InputStream in, int byteCount) throws IOException {
        if (in == null) {
            throw new IllegalArgumentException("in == null");
        }
        if (byteCount < 0) {
            throw new IllegalArgumentException("byteCount < 0: " + byteCount);
        }

        byte[] result = new byte[byteCount];
        for (int offset = 0, read; offset < byteCount; offset += read) {
            read = in.read(result, offset, byteCount - offset);
            if (read == -1) {
                throw new EOFException();
            }
        }
        return new ByteString(result);
    }

    // Convert the characters between AZ in data[] to lowercase, generate a new byte array, encapsulate it into a new ByteString and return it
    public ByteString toAsciiLowercase() {
        for (int i = 0; i < data.length; i++) {
            byte c = data[i];
            if (c < 'A' || c > 'Z') {
                continue;
            }
            byte[] lowercase = data.clone();
            lowercase[i++] = (byte) (c - ('A' - 'a'));
            for (; i < lowercase.length; i++) {
                c = lowercase[i];
                if (c < 'A' || c > 'Z') {
                    continue;
                }
                lowercase[i] = (byte) (c - ('A' - 'a'));
            }
            return new ByteString(lowercase);
        }
        return this;
    }

    // Convert the characters between az in data[], lowercase to uppercase, generate a new byte array, encapsulate it into a new ByteString and return it
    public ByteString toAsciiUppercase() {
        for (int i = 0; i < data.length; i++) {
            byte c = data[i];
            if (c < 'a' || c > 'z') {
                continue;
            }
            byte[] lowercase = data.clone();
            lowercase[i++] = (byte) (c - ('a' - 'A'));
            for (; i < lowercase.length; i++) {
                c = lowercase[i];
                if (c < 'a' || c > 'z') {
                    continue;
                }
                lowercase[i] = (byte) (c - ('a' - 'A'));
            }
            return new ByteString(lowercase);
        }
        return this;
    }

    /**
     * Returns a byte string that is a substring of this byte string, beginning at the specified
     * index until the end of this string. Returns this byte string if {@code beginIndex} is 0.
     */
    public ByteString substring(int beginIndex) {
        return substring(beginIndex, data.length);
    }

    //Encapsulate the content between beginIndex and endIndex in data[] into a new byte array, encapsulate it as ByteStirng and return it
    public ByteString substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new IllegalArgumentException("beginIndex < 0");
        }
        if (endIndex > data.length) {
            throw new IllegalArgumentException("endIndex > length(" + data.length + ")");
        }

        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new IllegalArgumentException("endIndex < beginIndex");
        }

        if ((beginIndex == 0) && (endIndex == data.length)) {
            return this;
        }

        byte[] copy = new byte[subLen];
        System.arraycopy(data, beginIndex, copy, 0, subLen);
        return new ByteString(copy);
    }

    //Return the posth byte of data[]
    public byte getByte(int pos) {
        return data[pos];
    }

    //Return the length of data[] in ByteString
    public int size() {
        return data.length;
    }

    //return a copy of data[]
    public byte[] toByteArray() {
        return data.clone();
    }

    //return data[] itself
    byte[] internalArray() {
        return data;
    }

    //Encapsulate a read-only ByteBuffer view with data[] to return
    public ByteBuffer asByteBuffer() {
        return ByteBuffer.wrap(data).asReadOnlyBuffer();
    }

    //Write the contents of the current data[] to the out output stream
    public void write(OutputStream out) throws IOException {
        if (out == null) {
            throw new IllegalArgumentException("out == null");
        }
        out.write(data);
    }

    //Write the contents of data[] into the buffer
    void write(Buffer buffer) {
        buffer.write(data, 0, data.length);
    }

    //Compare the content of offset~offset+byteCount of current ByteString.data[] with the content of otherOffset~otherOffset+byteCount of otherOffset.data[]
    public boolean rangeEquals(int offset, ByteString other, int otherOffset, int byteCount) {
        return other.rangeEquals(otherOffset, this.data, offset, byteCount);
    }

    /**
     * Returns true if the bytes of this in {@code [offset..offset+byteCount)} equal the bytes of
     * {@code other} in {@code [otherOffset..otherOffset+byteCount)}. Returns false if either range is
     * out of bounds.
     */
    public boolean rangeEquals(int offset, byte[] other, int otherOffset, int byteCount) {
        return offset >= 0 && offset <= data.length - byteCount
                && otherOffset >= 0 && otherOffset <= other.length - byteCount
                && arrayRangeEquals(data, offset, other, otherOffset, byteCount);
    }
	/ / Determine the current bytestring.data[] prefix
    public final boolean startsWith(ByteString prefix) {
        return rangeEquals(0, prefix, 0, prefix.size());
    }

    public final boolean startsWith(byte[] prefix) {
        return rangeEquals(0, prefix, 0, prefix.length);
    }
	/ / Determine the current bytestring.data[] suffix
    public final boolean endsWith(ByteString suffix) {
        return rangeEquals(size() - suffix.size(), suffix, 0, suffix.size());
    }

    public final boolean endsWith(byte[] suffix) {
        return rangeEquals(size() - suffix.length, suffix, 0, suffix.length);
    }
	/ / Determine the position index of other in the current ByteString
    public final int indexOf(ByteString other) {
        return indexOf(other.internalArray(), 0);
    }
	...
    @Override
    public int compareTo(ByteString byteString) {
        int sizeA = size();
        int sizeB = byteString.size();
        for (int i = 0, size = Math.min(sizeA, sizeB); i < size; i++) {
            int byteA = getByte(i) & 0xff;//&0xff, to prevent data from changing due to java type conversion complement
            int byteB = byteString.getByte(i) & 0xff;
            if (byteA == byteB) {
                continue;
            }
            return byteA < byteB ? -1 : 1;
        }
        if (sizeA == sizeB) {
            return 0;
        }
        return sizeA < sizeB ? -1 : 1;
    }
    ...
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324698997&siteId=291194637