content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.util.io;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.nio.ByteBuffer;
  import javax.annotation.concurrent.ThreadSafe;
  
  /**
   * A collection of utility functions to read/write primitive values from/to a byte array.
   */
  @ThreadSafe
  public final class ByteIOUtils {
  
    private ByteIOUtils() {} // prevent instantiation.
  
    /**
     * Reads a specific byte value from the input byte array at the given offset.
     *
     * @param buf input byte array
     * @param pos offset into the byte buffer to read
     * @return the byte value read
     */
    public static byte readByte(byte[] buf, int pos) {
      checkBoundary(buf, pos, 1);
      return (byte) (buf[pos] & 0xff);
    }
  
    /**
     * Reads a specific byte value from the input byte buffer at the given offset.
     *
     * @param buf input byte buffer
     * @param pos offset into the byte buffer to read
     * @return the byte value read
     */
    public static byte readByte(ByteBuffer buf, int pos) {
      return (byte) (buf.get(pos) & 0xff);
    }
  
    /**
     * Reads a specific short byte value (2 bytes) from the input byte array at the given offset.
     *
     * @param buf input byte buffer
     * @param pos offset into the byte buffer to read
     * @return the short value read
     */
    public static short readShort(byte[] buf, int pos) {
      checkBoundary(buf, pos, 2);
      return (short) (((short) (buf[pos] & 0xff) << 8) | ((short) (buf[pos + 1] & 0xff)));
    }
  
    /**
     * Reads a specific integer byte value (4 bytes) from the input byte array at the given offset.
     *
     * @param buf input byte array
     * @param pos offset into the byte buffer to read
     * @return the int value read
     */
    public static int readInt(byte[] buf, int pos) {
      checkBoundary(buf, pos, 4);
      return (((buf[pos++] & 0xff) << 24) | ((buf[pos++] & 0xff) << 16)
          | ((buf[pos++] & 0xff) << 8) | (buf[pos] & 0xff));
    }
  
    /**
     * Reads a specific integer byte value (4 bytes) from the input byte buffer at the given offset.
     *
     * @param buf input byte buffer
     * @param pos offset into the byte buffer to read
     * @return the int value read
     */
    public static int readInt(ByteBuffer buf, int pos) {
      return (((buf.get(pos) & 0xff) << 24) | ((buf.get(pos + 1) & 0xff) << 16)
          | ((buf.get(pos + 2) & 0xff) << 8) | (buf.get(pos + 3) & 0xff));
    }
  
    /**
     * Reads a specific long byte value (8 bytes) from the input byte array at the given offset.
     *
     * @param buf input byte buffer
     * @param pos offset into the byte buffer to read
     * @return the long value read
     */
    public static long readLong(byte[] buf, int pos) {
      checkBoundary(buf, pos, 8);
      return (((long) (buf[pos++] & 0xff) << 56) | ((long) (buf[pos++] & 0xff) << 48)
          | ((long) (buf[pos++] & 0xff) << 40) | ((long) (buf[pos++] & 0xff) << 32)
          | ((long) (buf[pos++] & 0xff) << 24) | ((long) (buf[pos++] & 0xff) << 16)
          | ((long) (buf[pos++] & 0xff) << 8) | ((long) (buf[pos] & 0xff)));
    }
  
    /**
     * Writes a single byte value (1 byte) to the output byte array at the given offset.
     *
     * @param buf output byte buffer
     * @param pos offset into the byte buffer to write
     * @param v byte value to write
     */
    public static void writeByte(byte[] buf, int pos, byte v) {
      checkBoundary(buf, pos, 1);
      buf[pos] = v;
    }
  
    /**
     * Writes a single byte value (1 byte) to the output byte buffer at the given offset.
     *
     * @param buf output byte buffer
     * @param pos offset into the byte buffer to write
     * @param v byte value to write
     */
    public static void writeByte(ByteBuffer buf, int pos, byte v) {
      buf.put(pos, v);
    }
  
    /**
     * Writes a single byte value (1 byte) to the output stream. This is equivalent of
     * {@link OutputStream#write(int)}.
     *
     * @param out output stream
     * @param v byte value to write
     */
    public static void writeByte(OutputStream out, byte v) throws IOException {
      out.write(v);
    }
  
    /**
     * Writes a specific short value (2 bytes) to the output byte buffer at the given offset.
     *
     * @param buf output byte buffer
     * @param pos offset into the byte buffer to write
     * @param v short value to write
     */
    public static void writeShort(byte[] buf, int pos, short v) {
      checkBoundary(buf, pos, 2);
      buf[pos++] = (byte) (0xff & (v >> 8));
      buf[pos] = (byte) (0xff & v);
    }
  
    /**
     * Writes a specific short value (2 bytes) to the output stream.
     *
     * @param out output stream
     * @param v short value to write
     */
    public static void writeShort(OutputStream out, short v) throws IOException {
      out.write((byte) (0xff & (v >> 8)));
      out.write((byte) (0xff & v));
    }
  
    /**
     * Writes a specific integer value (4 bytes) to the output byte array at the given offset.
     *
     * @param buf output byte array
     * @param pos offset into the byte buffer to write
     * @param v int value to write
     */
    public static void writeInt(byte[] buf, int pos, int v) {
      checkBoundary(buf, pos, 4);
      buf[pos++] = (byte) (0xff & (v >> 24));
      buf[pos++] = (byte) (0xff & (v >> 16));
      buf[pos++] = (byte) (0xff & (v >> 8));
      buf[pos] = (byte) (0xff & v);
    }
  
    /**
     * Writes a specific integer value (4 bytes) to the output byte buffer at the given offset.
     *
     * @param buf output byte buffer
     * @param pos offset into the byte buffer to write
     * @param v int value to write
     */
    public static void writeInt(ByteBuffer buf, int pos, int v) {
      buf.put(pos++, (byte) (0xff & (v >> 24)));
      buf.put(pos++, (byte) (0xff & (v >> 16)));
      buf.put(pos++, (byte) (0xff & (v >> 8)));
      buf.put(pos, (byte) (0xff & v));
    }
  
    /**
     * Writes a specific integer value (4 bytes) to the output stream.
     *
     * @param out output stream
     * @param v integer value to write
     */
    public static void writeInt(OutputStream out, int v) throws IOException {
      out.write((byte) (0xff & (v >> 24)));
      out.write((byte) (0xff & (v >> 16)));
      out.write((byte) (0xff & (v >> 8)));
      out.write((byte) (0xff & v));
    }
  
    /**
     * Writes a specific long value (8 bytes) to the output byte array at the given offset.
     *
     * @param buf output byte array
     * @param pos offset into the byte buffer to write
     * @param v long value to write
     */
    public static void writeLong(byte[] buf, int pos, long v) {
      checkBoundary(buf, pos, 8);
      buf[pos++] = (byte) (0xff & (v >> 56));
      buf[pos++] = (byte) (0xff & (v >> 48));
      buf[pos++] = (byte) (0xff & (v >> 40));
      buf[pos++] = (byte) (0xff & (v >> 32));
      buf[pos++] = (byte) (0xff & (v >> 24));
      buf[pos++] = (byte) (0xff & (v >> 16));
      buf[pos++] = (byte) (0xff & (v >> 8));
      buf[pos] = (byte) (0xff & v);
    }
  
    /**
     * Writes a specific long value (8 bytes) to the output stream.
     *
     * @param out output stream
     * @param v long value to write
     */
    public static void writeLong(OutputStream out, long v) throws IOException {
      out.write((byte) (0xff & (v >> 56)));
      out.write((byte) (0xff & (v >> 48)));
      out.write((byte) (0xff & (v >> 40)));
      out.write((byte) (0xff & (v >> 32)));
      out.write((byte) (0xff & (v >> 24)));
      out.write((byte) (0xff & (v >> 16)));
      out.write((byte) (0xff & (v >> 8)));
      out.write((byte) (0xff & v));
    }
  
    /**
     * Ensures that the given buffer contains at least the given number of bytes after the given
     * offset.
     *
     * @param buf input byte array
     * @param pos position in the byte array to start writing
     * @param len length of data to write from the given position
     */
    private static void checkBoundary(byte[] buf, int pos, int len) {
      if (pos + len > buf.length) {
        throw new ArrayIndexOutOfBoundsException();
      }
    }
  }
  