001: //##header
002: /**
003: *******************************************************************************
004: * Copyright (C) 1996-2006, International Business Machines Corporation and *
005: * others. All Rights Reserved. *
006: *******************************************************************************
007: */package com.ibm.icu.util;
008:
009: //#ifndef FOUNDATION
010: import java.nio.ByteBuffer; //#else
011: //##import com.ibm.icu.impl.ByteBuffer;
012: //#endif
013: import com.ibm.icu.impl.Utility;
014:
015: /**
016: * <p>
017: * A simple utility class to wrap a byte array.
018: * </p>
019: * <p>
020: * Generally passed as an argument object into a method. The method takes
021: * responsibility of writing into the internal byte array and increasing its
022: * size when necessary.
023: * </p>
024: * @author syn wee
025: * @stable ICU 2.8
026: */
027: public class ByteArrayWrapper implements Comparable {
028: // public data member ------------------------------------------------
029:
030: /**
031: * Internal byte array.
032: * @stable ICU 2.8
033: */
034: public byte[] bytes;
035:
036: /**
037: * Size of the internal byte array used.
038: * Different from bytes.length, size will be <= bytes.length.
039: * Semantics of size is similar to java.util.Vector.size().
040: * @stable ICU 2.8
041: */
042: public int size;
043:
044: // public constructor ------------------------------------------------
045:
046: /**
047: * Construct a new ByteArrayWrapper with no data.
048: * @stable ICU 2.8
049: */
050: public ByteArrayWrapper() {
051: // leave bytes null, don't allocate twice
052: }
053:
054: /**
055: * Construct a new ByteArrayWrapper from a byte array and size
056: * @param bytesToAdopt the byte array to adopt
057: * @param size the length of valid data in the byte array
058: * @throws IndexOutOfBoundsException if bytesToAdopt == null and size != 0, or
059: * size < 0, or size > bytesToAdopt.length.
060: * @draft ICU 3.2
061: * @provisional This API might change or be removed in a future release.
062: */
063: public ByteArrayWrapper(byte[] bytesToAdopt, int size) {
064: if ((bytesToAdopt == null && size != 0) || size < 0
065: || size > bytesToAdopt.length) {
066: throw new IndexOutOfBoundsException("illegal size: " + size);
067: }
068: this .bytes = bytesToAdopt;
069: this .size = size;
070: }
071:
072: /**
073: * Construct a new ByteArrayWrapper from the contents of a ByteBuffer.
074: * @param source the ByteBuffer from which to get the data.
075: * @draft ICU 3.2
076: * @provisional This API might change or be removed in a future release.
077: */
078: public ByteArrayWrapper(ByteBuffer source) {
079: size = source.limit();
080: bytes = new byte[size];
081: source.get(bytes, 0, size);
082: }
083:
084: /**
085: * Create from ByteBuffer
086: * @param byteBuffer
087: public ByteArrayWrapper(ByteArrayWrapper source) {
088: size = source.size;
089: bytes = new byte[size];
090: copyBytes(source.bytes, 0, bytes, 0, size);
091: }
092: */
093:
094: /**
095: * create from byte buffer
096: * @param src
097: * @param start
098: * @param limit
099: public ByteArrayWrapper(byte[] src, int start, int limit) {
100: size = limit - start;
101: bytes = new byte[size];
102: copyBytes(src, start, bytes, 0, size);
103: }
104: */
105:
106: // public methods ----------------------------------------------------
107: /**
108: * Ensure that the internal byte array is at least of length capacity.
109: * If the byte array is null or its length is less than capacity, a new
110: * byte array of length capacity will be allocated.
111: * The contents of the array (between 0 and size) remain unchanged.
112: * @param capacity minimum length of internal byte array.
113: * @return this ByteArrayWrapper
114: * @draft ICU 3.2
115: * @provisional This API might change or be removed in a future release.
116: */
117: public ByteArrayWrapper ensureCapacity(int capacity) {
118: if (bytes == null || bytes.length < capacity) {
119: byte[] newbytes = new byte[capacity];
120: copyBytes(bytes, 0, newbytes, 0, size);
121: bytes = newbytes;
122: }
123: return this ;
124: }
125:
126: /**
127: * Set the internal byte array from offset 0 to (limit - start) with the
128: * contents of src from offset start to limit. If the byte array is null or its length is less than capacity, a new
129: * byte array of length (limit - start) will be allocated.
130: * This resets the size of the internal byte array to (limit - start).
131: * @param src source byte array to copy from
132: * @param start start offset of src to copy from
133: * @param limit end + 1 offset of src to copy from
134: * @return this ByteArrayWrapper
135: * @draft ICU 3.2
136: * @provisional This API might change or be removed in a future release.
137: */
138: public final ByteArrayWrapper set(byte[] src, int start, int limit) {
139: size = 0;
140: append(src, start, limit);
141: return this ;
142: }
143:
144: /*
145: public final ByteArrayWrapper get(byte[] target, int start, int limit)
146: {
147: int len = limit - start;
148: if (len > size) throw new IllegalArgumentException("limit too long");
149: copyBytes(bytes, 0, target, start, len);
150: return this;
151: }
152: */
153:
154: /**
155: * Appends the internal byte array from offset size with the
156: * contents of src from offset start to limit. This increases the size of
157: * the internal byte array to (size + limit - start).
158: * @param src source byte array to copy from
159: * @param start start offset of src to copy from
160: * @param limit end + 1 offset of src to copy from
161: * @return this ByteArrayWrapper
162: * @draft ICU 3.2
163: * @provisional This API might change or be removed in a future release.
164: */
165: public final ByteArrayWrapper append(byte[] src, int start,
166: int limit) {
167: int len = limit - start;
168: ensureCapacity(size + len);
169: copyBytes(src, start, bytes, size, len);
170: size += len;
171: return this ;
172: }
173:
174: /*
175: public final ByteArrayWrapper append(ByteArrayWrapper other)
176: {
177: return append(other.bytes, 0, other.size);
178: }
179: */
180:
181: /**
182: * Releases the internal byte array to the caller, resets the internal
183: * byte array to null and its size to 0.
184: * @return internal byte array.
185: * @stable ICU 2.8
186: */
187: public final byte[] releaseBytes() {
188: byte result[] = bytes;
189: bytes = null;
190: size = 0;
191: return result;
192: }
193:
194: // Boilerplate ----------------------------------------------------
195:
196: /**
197: * Returns string value for debugging
198: * @draft ICU 3.2
199: * @provisional This API might change or be removed in a future release.
200: */
201: public String toString() {
202: StringBuffer result = new StringBuffer();
203: for (int i = 0; i < size; ++i) {
204: if (i != 0)
205: result.append(" ");
206: result.append(Utility.hex(bytes[i] & 0xFF, 2));
207: }
208: return result.toString();
209: }
210:
211: /**
212: * Return true if the bytes in each wrapper are equal.
213: * @param other the object to compare to.
214: * @return true if the two objects are equal.
215: * @draft ICU 3.2
216: * @provisional This API might change or be removed in a future release.
217: */
218: public boolean equals(Object other) {
219: if (this == other)
220: return true;
221: if (other == null)
222: return false;
223: try {
224: ByteArrayWrapper that = (ByteArrayWrapper) other;
225: if (size != that.size)
226: return false;
227: for (int i = 0; i < size; ++i) {
228: if (bytes[i] != that.bytes[i])
229: return false;
230: }
231: return true;
232: } catch (ClassCastException e) {
233: }
234: return false;
235: }
236:
237: /**
238: * Return the hashcode.
239: * @return the hashcode.
240: * @draft ICU 3.2
241: * @provisional This API might change or be removed in a future release.
242: */
243: public int hashCode() {
244: int result = bytes.length;
245: for (int i = 0; i < size; ++i) {
246: result = 37 * result + bytes[i];
247: }
248: return result;
249: }
250:
251: /**
252: * Compare this object to another ByteArrayWrapper, which must not be null.
253: * @param other the object to compare to.
254: * @return a value <0, 0, or >0 as this compares less than, equal to, or
255: * greater than other.
256: * @throws ClassCastException if the other object is not a ByteArrayWrapper
257: * @draft ICU 3.2
258: * @provisional This API might change or be removed in a future release.
259: */
260: public int compareTo(Object other) {
261: if (this == other)
262: return 0;
263: ByteArrayWrapper that = (ByteArrayWrapper) other;
264: int minSize = size < that.size ? size : that.size;
265: for (int i = 0; i < minSize; ++i) {
266: if (bytes[i] != that.bytes[i]) {
267: return (bytes[i] & 0xFF) - (that.bytes[i] & 0xFF);
268: }
269: }
270: return size - that.size;
271: }
272:
273: // private methods -----------------------------------------------------
274:
275: /**
276: * Copies the contents of src byte array from offset srcoff to the
277: * target of tgt byte array at the offset tgtoff.
278: * @param src source byte array to copy from
279: * @param srcoff start offset of src to copy from
280: * @param tgt target byte array to copy to
281: * @param tgtoff start offset of tgt to copy to
282: * @param length size of contents to copy
283: */
284: private static final void copyBytes(byte[] src, int srcoff,
285: byte[] tgt, int tgtoff, int length) {
286: if (length < 64) {
287: for (int i = srcoff, n = tgtoff; --length >= 0; ++i, ++n) {
288: tgt[n] = src[i];
289: }
290: } else {
291: System.arraycopy(src, srcoff, tgt, tgtoff, length);
292: }
293: }
294: }
|