2 *******************************************************************************
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.util;
10 import java.nio.ByteBuffer;
12 import com.ibm.icu.impl.Utility;
16 * A simple utility class to wrap a byte array.
19 * Generally passed as an argument object into a method. The method takes
20 * responsibility of writing into the internal byte array and increasing its
21 * size when necessary.
26 public class ByteArrayWrapper implements Comparable<ByteArrayWrapper>
28 // public data member ------------------------------------------------
31 * Internal byte array.
37 * Size of the internal byte array used.
38 * Different from bytes.length, size will be <= bytes.length.
39 * Semantics of size is similar to java.util.Vector.size().
44 // public constructor ------------------------------------------------
47 * Construct a new ByteArrayWrapper with no data.
50 public ByteArrayWrapper() {
51 // leave bytes null, don't allocate twice
55 * Construct a new ByteArrayWrapper from a byte array and size
56 * @param bytesToAdopt the byte array to adopt
57 * @param size the length of valid data in the byte array
58 * @throws IndexOutOfBoundsException if bytesToAdopt == null and size != 0, or
59 * size < 0, or size > bytesToAdopt.length.
62 public ByteArrayWrapper(byte[] bytesToAdopt, int size) {
63 if ((bytesToAdopt == null && size != 0) || size < 0 || size > bytesToAdopt.length) {
64 throw new IndexOutOfBoundsException("illegal size: " + size);
66 this.bytes = bytesToAdopt;
71 * Construct a new ByteArrayWrapper from the contents of a ByteBuffer.
72 * @param source the ByteBuffer from which to get the data.
75 public ByteArrayWrapper(ByteBuffer source) {
76 size = source.limit();
77 bytes = new byte[size];
78 source.get(bytes,0,size);
82 * Create from ByteBuffer
84 public ByteArrayWrapper(ByteArrayWrapper source) {
86 bytes = new byte[size];
87 copyBytes(source.bytes, 0, bytes, 0, size);
92 * create from byte buffer
96 public ByteArrayWrapper(byte[] src, int start, int limit) {
98 bytes = new byte[size];
99 copyBytes(src, start, bytes, 0, size);
103 // public methods ----------------------------------------------------
106 * Ensure that the internal byte array is at least of length capacity.
107 * If the byte array is null or its length is less than capacity, a new
108 * byte array of length capacity will be allocated.
109 * The contents of the array (between 0 and size) remain unchanged.
110 * @param capacity minimum length of internal byte array.
111 * @return this ByteArrayWrapper
114 public ByteArrayWrapper ensureCapacity(int capacity)
116 if (bytes == null || bytes.length < capacity) {
117 byte[] newbytes = new byte[capacity];
118 copyBytes(bytes, 0, newbytes, 0, size);
125 * Set the internal byte array from offset 0 to (limit - start) with the
126 * contents of src from offset start to limit. If the byte array is null or its length is less than capacity, a new
127 * byte array of length (limit - start) will be allocated.
128 * This resets the size of the internal byte array to (limit - start).
129 * @param src source byte array to copy from
130 * @param start start offset of src to copy from
131 * @param limit end + 1 offset of src to copy from
132 * @return this ByteArrayWrapper
135 public final ByteArrayWrapper set(byte[] src, int start, int limit)
138 append(src, start, limit);
143 public final ByteArrayWrapper get(byte[] target, int start, int limit)
145 int len = limit - start;
146 if (len > size) throw new IllegalArgumentException("limit too long");
147 copyBytes(bytes, 0, target, start, len);
153 * Appends the internal byte array from offset size with the
154 * contents of src from offset start to limit. This increases the size of
155 * the internal byte array to (size + limit - start).
156 * @param src source byte array to copy from
157 * @param start start offset of src to copy from
158 * @param limit end + 1 offset of src to copy from
159 * @return this ByteArrayWrapper
162 public final ByteArrayWrapper append(byte[] src, int start, int limit)
164 int len = limit - start;
165 ensureCapacity(size + len);
166 copyBytes(src, start, bytes, size, len);
172 public final ByteArrayWrapper append(ByteArrayWrapper other)
174 return append(other.bytes, 0, other.size);
179 * Releases the internal byte array to the caller, resets the internal
180 * byte array to null and its size to 0.
181 * @return internal byte array.
184 public final byte[] releaseBytes()
186 byte result[] = bytes;
192 // Boilerplate ----------------------------------------------------
195 * Returns string value for debugging
198 public String toString() {
199 StringBuilder result = new StringBuilder();
200 for (int i = 0; i < size; ++i) {
201 if (i != 0) result.append(" ");
202 result.append(Utility.hex(bytes[i]&0xFF,2));
204 return result.toString();
208 * Return true if the bytes in each wrapper are equal.
209 * @param other the object to compare to.
210 * @return true if the two objects are equal.
213 public boolean equals(Object other) {
214 if (this == other) return true;
215 if (other == null) return false;
217 ByteArrayWrapper that = (ByteArrayWrapper)other;
218 if (size != that.size) return false;
219 for (int i = 0; i < size; ++i) {
220 if (bytes[i] != that.bytes[i]) return false;
224 catch (ClassCastException e) {
230 * Return the hashcode.
231 * @return the hashcode.
234 public int hashCode() {
235 int result = bytes.length;
236 for (int i = 0; i < size; ++i) {
237 result = 37*result + bytes[i];
243 * Compare this object to another ByteArrayWrapper, which must not be null.
244 * @param other the object to compare to.
245 * @return a value <0, 0, or >0 as this compares less than, equal to, or
246 * greater than other.
247 * @throws ClassCastException if the other object is not a ByteArrayWrapper
250 public int compareTo(ByteArrayWrapper other) {
251 if (this == other) return 0;
252 int minSize = size < other.size ? size : other.size;
253 for (int i = 0; i < minSize; ++i) {
254 if (bytes[i] != other.bytes[i]) {
255 return (bytes[i] & 0xFF) - (other.bytes[i] & 0xFF);
258 return size - other.size;
261 // private methods -----------------------------------------------------
264 * Copies the contents of src byte array from offset srcoff to the
265 * target of tgt byte array at the offset tgtoff.
266 * @param src source byte array to copy from
267 * @param srcoff start offset of src to copy from
268 * @param tgt target byte array to copy to
269 * @param tgtoff start offset of tgt to copy to
270 * @param length size of contents to copy
272 private static final void copyBytes(byte[] src, int srcoff, byte[] tgt,
273 int tgtoff, int length) {
275 for (int i = srcoff, n = tgtoff; -- length >= 0; ++ i, ++ n) {
280 System.arraycopy(src, srcoff, tgt, tgtoff, length);