/* * 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 org.apache.geode.internal.util; import java.nio.ByteBuffer; /** * Provides utilities for converting from byte[] to primitive values. * */ public class Bytes { /** * Inserts the integer value into the array at the requested offset. * * @param val the value * @param buf the array * @param off the offset */ public static void putInt(int val, byte[] buf, int off) { assert off + 4 <= buf.length; buf[off] = int0(val); buf[off + 1] = int1(val); buf[off + 2] = int2(val); buf[off + 3] = int3(val); } /** * Inserts the long value into the array at the requested offset. * * @param val the value * @param buf the array * @param off the offset */ public static void putLong(long val, byte[] buf, int off) { assert off + 4 <= buf.length; buf[off] = long0(val); buf[off + 1] = long1(val); buf[off + 2] = long2(val); buf[off + 3] = long3(val); buf[off + 4] = long4(val); buf[off + 5] = long5(val); buf[off + 6] = long6(val); buf[off + 7] = long7(val); } /** * Extracts the protobuf varint from the buffer. * * @param buf the buffer * @return the varint */ public static int getVarInt(ByteBuffer buf) { byte b; int val; // unrolled! :-) b = buf.get(); val = (b & 0x7f); if ((b & 0x80) == 0) return val; b = buf.get(); val |= (b & 0x7f) << 7; if ((b & 0x80) == 0) return val; b = buf.get(); val |= (b & 0x7f) << 14; if ((b & 0x80) == 0) return val; b = buf.get(); val |= (b & 0x7f) << 21; if ((b & 0x80) == 0) return val; b = buf.get(); val |= (b & 0x7f) << 28; return val; } /** * Extracts the protbuf varint from the array. * * @param buf the array * @param off the offset * @return the varint */ public static int getVarInt(byte[] buf, int off) { byte b; int val; // unrolled! :-) b = buf[off++]; val = (b & 0x7f); if ((b & 0x80) == 0) return val; b = buf[off++]; val |= (b & 0x7f) << 7; if ((b & 0x80) == 0) return val; b = buf[off++]; val |= (b & 0x7f) << 14; if ((b & 0x80) == 0) return val; b = buf[off++]; val |= (b & 0x7f) << 21; if ((b & 0x80) == 0) return val; b = buf[off++]; val |= (b & 0x7f) << 28; return val; } /** * Inserts the protobuf varint into the buffer at the current position. * * @param val the value * @param buf the buffer * @return the buffer */ public static ByteBuffer putVarInt(int val, ByteBuffer buf) { assert val >= 0; // protobuf-style varint encoding // set the MSB as continuation bit for each byte except the last byte // pack the bytes in reverse order // packed size is (bits / 7) + 1 while ((val & ~0x7f) != 0) { buf.put((byte) ((val & 0x7f) | 0x80)); val >>= 7; } return buf.put((byte) val); } /** * Inserts the protobuf varint into the array at the requested offset. * * @param val the value * @param buf the array * @param off the offset * @return the updated offset */ public static int putVarInt(int val, byte[] buf, int off) { assert val >= 0; // protobuf-style varint encoding // set the MSB as continuation bit for each byte except the last byte // TODO see if unrolling is faster while (val > 0x7f) { buf[off++] = (byte) ((val & 0x7f) | 0x80); val >>= 7; } buf[off++] = (byte) val; return off; } /** * Returns the bytes required to store a protobuf varint. * * @param val the value * @return the varint size */ public static int sizeofVarInt(int val) { assert val >= 0; if (val < (1 << 7)) { return 1; } else if (val < (1 << 14)) { return 2; } else if (val < (1 << 21)) { return 3; } else if (val < (1 << 28)) { return 4; } return 5; } /** * Creates a short value from two bytes. * * @param b0 the first byte * @param b1 the second byte * @return the value */ public static short toShort(byte b0, byte b1) { return (short) ((b0 << 8) | (b1 & 0xff)); } /** * Creates a char value from two bytes. * * @param b0 the first byte * @param b1 the second byte * @return the value */ public static char toChar(byte b0, byte b1) { return (char) ((b0 << 8) | (b1 & 0xff)); } /** * Creates an unsigned short from two bytes. * * @param b0 the first byte * @param b1 the second byte * @return the value */ public static int toUnsignedShort(byte b0, byte b1) { return ((b0 & 0xff) << 8) | (b1 & 0xff); } /** * Creates an integer from four bytes. * * @param b0 the first byte * @param b1 the second byte * @param b2 the third byte * @param b3 the fourth byte * @return the value */ public static int toInt(byte b0, byte b1, byte b2, byte b3) { return (b0 << 24) | ((b1 & 0xff) << 16) | ((b2 & 0xff) << 8) | (b3 & 0xff); } /** * Creates a long from eight bytes. * * @param b0 the first byte * @param b1 the second byte * @param b2 the third byte * @param b3 the fourth byte * @param b4 the fifth byte * @param b5 the sixth byte * @param b6 the seventh byte * @param b7 the eighth byte * @return the value */ public static long toLong(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) { return ((long) b0 << 56) | (((long) b1 & 0xff) << 48) | (((long) b2 & 0xff) << 40) | (((long) b3 & 0xff) << 32) | (((long) b4 & 0xff) << 24) | (((long) b5 & 0xff) << 16) | (((long) b6 & 0xff) << 8) | ((long) b7 & 0xff); } public static byte char0(char value) { return (byte) (value >> 8); } public static byte char1(char value) { return (byte) value; } public static byte short0(short value) { return (byte) (value >> 8); } public static byte short1(short value) { return (byte) value; } public static byte int0(int value) { return (byte) (value >> 24); } public static byte int1(int value) { return (byte) (value >> 16); } public static byte int2(int value) { return (byte) (value >> 8); } public static byte int3(int value) { return (byte) value; } public static byte long0(long value) { return (byte) (value >> 56); } public static byte long1(long value) { return (byte) (value >> 48); } public static byte long2(long value) { return (byte) (value >> 40); } public static byte long3(long value) { return (byte) (value >> 32); } public static byte long4(long value) { return (byte) (value >> 24); } public static byte long5(long value) { return (byte) (value >> 16); } public static byte long6(long value) { return (byte) (value >> 8); } public static byte long7(long value) { return (byte) value; } }