/* * Copyright (C) 2011 René Jeschke <rene_jeschke@yahoo.de> * * Licensed 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.github.rjeschke.weel; import java.util.Arrays; /** * A specialized ByteList for bytecode writing. * * @author René Jeschke <rene_jeschke@yahoo.de> */ final class ByteList { /** Initial size. */ private final static int INITIAL_SIZE = 128; /** Growth factor. */ private final static int GROWTH_FACTOR = 125; /** The array. */ private byte[] array; /** The size. */ private int size = 0; /** * Constructor. */ public ByteList() { this.array = new byte[INITIAL_SIZE]; } /** * Constructor. * * @param initialSize * Initial size. */ public ByteList(final int initialSize) { this.array = new byte[initialSize]; } /** * Gets the size of this ByteList. * * @return The size in bytes. */ public int size() { return this.size; } /** * Clears this ByteList by setting its size to <code>0</code>. */ public void clear() { this.size = 0; } /** * Grows this ByteList's backing array. */ private void grow() { this.array = Arrays.copyOf(this.array, (this.array.length * GROWTH_FACTOR) / 100); } /** * Adds a byte value to this ByteList. * * @param value * The byte value to add. */ public void add(final int value) { if (this.array.length == this.size) this.grow(); this.array[this.size++] = (byte) value; } /** * Adds a short (big endian) value to this ByteList. * * @param value * The short value to add. */ public void addShort(final int value) { while (this.size + 2 >= this.array.length) this.grow(); this.array[this.size + 0] = (byte) (value >> 8); this.array[this.size + 1] = (byte) value; this.size += 2; } /** * Adds an integer (big endian) value to this ByteList. * * @param value * The integer value to add. */ public void addInteger(final int value) { while (this.size + 4 >= this.array.length) this.grow(); this.array[this.size + 0] = (byte) (value >> 24); this.array[this.size + 1] = (byte) (value >> 16); this.array[this.size + 2] = (byte) (value >> 8); this.array[this.size + 3] = (byte) value; this.size += 4; } /** * Adds a long (big endian) value to this ByteList. * * @param value * The long value to add. */ public void addLong(final long value) { while (this.size + 8 >= this.array.length) this.grow(); this.array[this.size + 0] = (byte) (value >> 56L); this.array[this.size + 1] = (byte) (value >> 48L); this.array[this.size + 2] = (byte) (value >> 40L); this.array[this.size + 3] = (byte) (value >> 32L); this.array[this.size + 4] = (byte) (value >> 24L); this.array[this.size + 5] = (byte) (value >> 16L); this.array[this.size + 6] = (byte) (value >> 8L); this.array[this.size + 7] = (byte) value; this.size += 8; } /** * Sets a byte a the given index. * * @param index * The index. * @param value * The byte value. */ public void set(final int index, final int value) { this.array[index] = (byte) value; } /** * Sets a short a the given index. * * @param index * The index. * @param value * The short value. */ public void setShort(final int index, final int value) { this.array[index + 0] = (byte) (value >> 8); this.array[index + 1] = (byte) value; } /** * Sets an integer a the given index. * * @param index * The index. * @param value * The integer value. */ public void setInteger(final int index, final int value) { this.array[index + 0] = (byte) (value >> 24); this.array[index + 1] = (byte) (value >> 16); this.array[index + 2] = (byte) (value >> 8); this.array[index + 3] = (byte) value; } /** * Sets a long a the given index. * * @param index * The index. * @param value * The long value. */ public void setLong(final int index, final long value) { this.array[index + 0] = (byte) (value >> 56L); this.array[index + 1] = (byte) (value >> 48L); this.array[index + 2] = (byte) (value >> 40L); this.array[index + 3] = (byte) (value >> 32L); this.array[index + 4] = (byte) (value >> 24L); this.array[index + 5] = (byte) (value >> 16L); this.array[index + 6] = (byte) (value >> 8L); this.array[index + 7] = (byte) value; } /** * Gets the byte at the given index. * * @param index * The index. * @return The byte at the given position. */ public byte get(final int index) { return this.array[index]; } /** * Gets the (unsigned) short at the given index. * * @param index * The index. * @return The short at the given position. */ public int getShort(final int index) { return ((this.array[index] & 255) << 8) | (this.array[index + 1] & 255); } /** * Gets the byte at the given index as an unsigned value. * * @param index * The index. * @return The byte at the given position. */ public int getUnsigned(final int index) { return this.array[index] & 255; } /** * Returns a copy of this ByteLists's backing array truncated to the correct * size. * * @return The array. */ public byte[] toArray() { return Arrays.copyOf(this.array, this.size); } }