summaryrefslogtreecommitdiff
path: root/android_icu4j/src/main/java/android/icu/util/ByteArrayWrapper.java
blob: 4ddf87bf73aac83b5efbeccdf52065ff9803d669 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* GENERATED SOURCE. DO NOT MODIFY. */
/**
 *******************************************************************************
 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package android.icu.util;

import java.nio.ByteBuffer;

import android.icu.impl.Utility;

/**
 * <p>
 * A simple utility class to wrap a byte array.
 * </p>
 * <p>
 * Generally passed as an argument object into a method. The method takes
 * responsibility of writing into the internal byte array and increasing its
 * size when necessary.
 * </p> 
 * @author syn wee
 */
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper>
{
    // public data member ------------------------------------------------
    
    /**
     * Internal byte array.
     */
    public byte[] bytes;

    /**
     * Size of the internal byte array used. 
     * Different from bytes.length, size will be &lt;= bytes.length. 
     * Semantics of size is similar to java.util.Vector.size().
     */
    public int size;
    
    // public constructor ------------------------------------------------

    /** 
     * Construct a new ByteArrayWrapper with no data.
     */
    public ByteArrayWrapper() {
        // leave bytes null, don't allocate twice
    }

    /**
     * Construct a new ByteArrayWrapper from a byte array and size
     * @param bytesToAdopt the byte array to adopt
     * @param size the length of valid data in the byte array
     * @throws IndexOutOfBoundsException if bytesToAdopt == null and size != 0, or
     * size < 0, or size > bytesToAdopt.length.
     */
    public ByteArrayWrapper(byte[] bytesToAdopt, int size) {
        if ((bytesToAdopt == null && size != 0) || size < 0 || size > bytesToAdopt.length) {
            throw new IndexOutOfBoundsException("illegal size: " + size);
        }
        this.bytes = bytesToAdopt;
        this.size = size;
    }

    /**
     * Construct a new ByteArrayWrapper from the contents of a ByteBuffer.
     * @param source the ByteBuffer from which to get the data.
     */
    public ByteArrayWrapper(ByteBuffer source) {
        size = source.limit();
        bytes = new byte[size];
        source.get(bytes,0,size);
    }

    /**
     * Create from ByteBuffer
     * @param byteBuffer
    public ByteArrayWrapper(ByteArrayWrapper source) {
        size = source.size;
        bytes = new byte[size];
        copyBytes(source.bytes, 0, bytes, 0, size);
    }
     */

    /**
     * create from byte buffer
     * @param src
     * @param start
     * @param limit
    public ByteArrayWrapper(byte[] src, int start, int limit) {
        size = limit - start;
        bytes = new byte[size];
        copyBytes(src, start, bytes, 0, size);
    }
     */

    // public methods ----------------------------------------------------

    /**
     * Ensure that the internal byte array is at least of length capacity.     
     * If the byte array is null or its length is less than capacity, a new 
     * byte array of length capacity will be allocated.  
     * The contents of the array (between 0 and size) remain unchanged. 
     * @param capacity minimum length of internal byte array.
     * @return this ByteArrayWrapper
     */
    public ByteArrayWrapper ensureCapacity(int capacity) 
    {
        if (bytes == null || bytes.length < capacity) {
            byte[] newbytes = new byte[capacity];
            copyBytes(bytes, 0, newbytes, 0, size);
            bytes = newbytes;
        }
        return this;
    }
    
    /**
     * Set the internal byte array from offset 0 to (limit - start) with the 
     * contents of src from offset start to limit. If the byte array is null or its length is less than capacity, a new 
     * byte array of length (limit - start) will be allocated.  
     * This resets the size of the internal byte array to (limit - start).
     * @param src source byte array to copy from
     * @param start start offset of src to copy from
     * @param limit end + 1 offset of src to copy from
     * @return this ByteArrayWrapper
     */
    public final ByteArrayWrapper set(byte[] src, int start, int limit) 
    {
        size = 0;
        append(src, start, limit);
        return this;
    }
    
    /*
    public final ByteArrayWrapper get(byte[] target, int start, int limit) 
    {
        int len = limit - start;
        if (len > size) throw new IllegalArgumentException("limit too long");
        copyBytes(bytes, 0, target, start, len);
        return this;
    }
    */

    /**
     * Appends the internal byte array from offset size with the 
     * contents of src from offset start to limit. This increases the size of
     * the internal byte array to (size + limit - start).
     * @param src source byte array to copy from
     * @param start start offset of src to copy from
     * @param limit end + 1 offset of src to copy from
     * @return this ByteArrayWrapper
     */
    public final ByteArrayWrapper append(byte[] src, int start, int limit) 
    {
        int len = limit - start;
        ensureCapacity(size + len);
        copyBytes(src, start, bytes, size, len);
        size += len;
        return this;
    }

    /*
    public final ByteArrayWrapper append(ByteArrayWrapper other) 
    {
        return append(other.bytes, 0, other.size);
    }
    */

    /**
     * Releases the internal byte array to the caller, resets the internal
     * byte array to null and its size to 0.
     * @return internal byte array.
     */
    public final byte[] releaseBytes()
    {
        byte result[] = bytes;
        bytes = null;
        size = 0;
        return result;
    }
    
    // Boilerplate ----------------------------------------------------
    
    /**
     * Returns string value for debugging
     */
    public String toString() {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < size; ++i) {
            if (i != 0) result.append(" ");
            result.append(Utility.hex(bytes[i]&0xFF,2));
        }
        return result.toString();
    }

    /**
     * Return true if the bytes in each wrapper are equal.
     * @param other the object to compare to.
     * @return true if the two objects are equal.
     */
    public boolean equals(Object other) {
        if (this == other) return true;
        if (other == null) return false;
        try {
            ByteArrayWrapper that = (ByteArrayWrapper)other;
            if (size != that.size) return false;
            for (int i = 0; i < size; ++i) {
                if (bytes[i] != that.bytes[i]) return false;
            }
            return true;
        }
        catch (ClassCastException e) {
        }
        return false;
    }

    /**
     * Return the hashcode.
     * @return the hashcode.
     */
    public int hashCode() {
        int result = bytes.length;
        for (int i = 0; i < size; ++i) {
            result = 37*result + bytes[i];
        }
        return result;
    }

    /**
     * Compare this object to another ByteArrayWrapper, which must not be null.
     * @param other the object to compare to.
     * @return a value <0, 0, or >0 as this compares less than, equal to, or
     * greater than other.
     * @throws ClassCastException if the other object is not a ByteArrayWrapper
     */
    public int compareTo(ByteArrayWrapper other) {
        if (this == other) return 0;
        int minSize = size < other.size ? size : other.size;
        for (int i = 0; i < minSize; ++i) {
            if (bytes[i] != other.bytes[i]) {
                return (bytes[i] & 0xFF) - (other.bytes[i] & 0xFF);
            }
        }
        return size - other.size;
    }
    
    // private methods -----------------------------------------------------
    
    /**
     * Copies the contents of src byte array from offset srcoff to the 
     * target of tgt byte array at the offset tgtoff.
     * @param src source byte array to copy from
     * @param srcoff start offset of src to copy from
     * @param tgt target byte array to copy to
     * @param tgtoff start offset of tgt to copy to
     * @param length size of contents to copy
     */
    private static final void copyBytes(byte[] src, int srcoff, byte[] tgt, 
                                       int tgtoff, int length) {
        if (length < 64) {
            for (int i = srcoff, n = tgtoff; -- length >= 0; ++ i, ++ n) {
                tgt[n] = src[i];
            }
        } 
        else {
            System.arraycopy(src, srcoff, tgt, tgtoff, length);
        }
    }      
}