
com.alipay.sofa.jraft.util.BytesUtil Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alipay.sofa.jraft.util;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import com.alipay.sofa.jraft.util.internal.UnsafeUtf8Util;
import com.alipay.sofa.jraft.util.internal.UnsafeUtil;
/**
* @author jiachun.fjc
*/
public final class BytesUtil {
public static final byte[] EMPTY_BYTES = new byte[0];
// A byte array comparator based on lexicograpic ordering.
private static final ByteArrayComparator BYTES_LEXICO_COMPARATOR = new LexicographicByteArrayComparator();
public static byte[] nullToEmpty(final byte[] bytes) {
return bytes == null ? EMPTY_BYTES : bytes;
}
public static boolean isEmpty(final byte[] bytes) {
return bytes == null || bytes.length == 0;
}
/**
* This method has better performance than String#getBytes(Charset),
* See the benchmark class: Utf8Benchmark for details.
*/
public static byte[] writeUtf8(final String in) {
if (in == null) {
return null;
}
if (UnsafeUtil.hasUnsafe()) {
// Calculate the encoded length.
final int len = UnsafeUtf8Util.encodedLength(in);
final byte[] outBytes = new byte[len];
UnsafeUtf8Util.encodeUtf8(in, outBytes, 0, len);
return outBytes;
} else {
return in.getBytes(StandardCharsets.UTF_8);
}
}
/**
* This method has better performance than String#String(byte[], Charset),
* See the benchmark class: Utf8Benchmark for details.
*/
public static String readUtf8(final byte[] in) {
if (in == null) {
return null;
}
if (UnsafeUtil.hasUnsafe()) {
return UnsafeUtf8Util.decodeUtf8(in, 0, in.length);
} else {
return new String(in, StandardCharsets.UTF_8);
}
}
public static byte[] nextBytes(final byte[] bytes) {
Requires.requireNonNull(bytes, "bytes");
final int len = bytes.length;
if (len == 0) { // fast path
return new byte[] { 0 };
}
final byte[] nextBytes = new byte[len + 1];
System.arraycopy(bytes, 0, nextBytes, 0, len);
nextBytes[len] = 0;
return nextBytes;
}
public static ByteArrayComparator getDefaultByteArrayComparator() {
return BYTES_LEXICO_COMPARATOR;
}
public static int compare(final byte[] a, final byte[] b) {
return getDefaultByteArrayComparator().compare(a, b);
}
public static byte[] max(final byte[] a, final byte[] b) {
return getDefaultByteArrayComparator().compare(a, b) > 0 ? a : b;
}
public static byte[] min(final byte[] a, final byte[] b) {
return getDefaultByteArrayComparator().compare(a, b) < 0 ? a : b;
}
public interface ByteArrayComparator extends Comparator, Serializable {
int compare(final byte[] buffer1, final int offset1, final int length1, final byte[] buffer2,
final int offset2, final int length2);
}
private static class LexicographicByteArrayComparator implements ByteArrayComparator {
private static final long serialVersionUID = -8623342242397267864L;
@Override
public int compare(final byte[] buffer1, final byte[] buffer2) {
return compare(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length);
}
@Override
public int compare(final byte[] buffer1, final int offset1, final int length1, final byte[] buffer2,
final int offset2, final int length2) {
// short circuit equal case
if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) {
return 0;
}
// similar to Arrays.compare() but considers offset and length
final int end1 = offset1 + length1;
final int end2 = offset2 + length2;
for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
int a = buffer1[i] & 0xff;
int b = buffer2[j] & 0xff;
if (a != b) {
return a - b;
}
}
return length1 - length2;
}
}
private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
/**
* Dump byte array into a hex string.
* See https://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java
* @param bytes bytes
* @return hex string
*/
public static String toHex(final byte[] bytes) {
if (bytes == null) {
return null;
}
final char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
/**
* Convert a string representation of a hex dump to a byte array.
* See https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
* @param s hex string
* @return bytes
*/
public static byte[] hexStringToByteArray(final String s) {
if (s == null) {
return null;
}
final int len = s.length();
final byte[] bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return bytes;
}
private BytesUtil() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy