blob: 145411cf7a6a65a9d2d583aeebe953af254e11f4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
19import java.util.LinkedList;
Grace Kloba3af8e932009-06-19 15:03:46 -070020import java.util.ListIterator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021
22/** Utility class optimized for accumulating bytes, and then spitting
23 them back out. It does not optimize for returning the result in a
24 single array, though this is supported in the API. It is fastest
25 if the retrieval can be done via iterating through chunks.
26
27 Things to add:
28 - consider dynamically increasing our min_capacity,
29 as we see mTotalSize increase
30*/
31class ByteArrayBuilder {
32
33 private static final int DEFAULT_CAPACITY = 8192;
34
35 private LinkedList<Chunk> mChunks;
36
37 /** free pool */
38 private LinkedList<Chunk> mPool;
39
40 private int mMinCapacity;
41
42 public ByteArrayBuilder() {
43 init(0);
44 }
45
46 public ByteArrayBuilder(int minCapacity) {
47 init(minCapacity);
48 }
49
50 private void init(int minCapacity) {
51 mChunks = new LinkedList<Chunk>();
52 mPool = new LinkedList<Chunk>();
53
54 if (minCapacity <= 0) {
55 minCapacity = DEFAULT_CAPACITY;
56 }
57 mMinCapacity = minCapacity;
58 }
59
60 public void append(byte[] array) {
61 append(array, 0, array.length);
62 }
63
64 public synchronized void append(byte[] array, int offset, int length) {
65 while (length > 0) {
66 Chunk c = appendChunk(length);
67 int amount = Math.min(length, c.mArray.length - c.mLength);
68 System.arraycopy(array, offset, c.mArray, c.mLength, amount);
69 c.mLength += amount;
70 length -= amount;
71 offset += amount;
72 }
73 }
74
75 /**
76 * The fastest way to retrieve the data is to iterate through the
77 * chunks. This returns the first chunk. Note: this pulls the
78 * chunk out of the queue. The caller must call releaseChunk() to
79 * dispose of it.
80 */
81 public synchronized Chunk getFirstChunk() {
82 if (mChunks.isEmpty()) return null;
83 return mChunks.removeFirst();
84 }
85
86 /**
87 * recycles chunk
88 */
89 public synchronized void releaseChunk(Chunk c) {
90 c.mLength = 0;
91 mPool.addLast(c);
92 }
93
94 public boolean isEmpty() {
95 return mChunks.isEmpty();
96 }
97
Grace Kloba3af8e932009-06-19 15:03:46 -070098 public int size() {
99 return mChunks.size();
100 }
101
102 public int getByteSize() {
103 int total = 0;
104 ListIterator<Chunk> it = mChunks.listIterator(0);
105 while (it.hasNext()) {
106 Chunk c = it.next();
107 total += c.mLength;
108 }
109 return total;
110 }
111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 public synchronized void clear() {
113 Chunk c = getFirstChunk();
114 while (c != null) {
115 releaseChunk(c);
116 c = getFirstChunk();
117 }
118 }
119
120 private Chunk appendChunk(int length) {
121 if (length < mMinCapacity) {
122 length = mMinCapacity;
123 }
124
125 Chunk c;
126 if (mChunks.isEmpty()) {
127 c = obtainChunk(length);
128 } else {
129 c = mChunks.getLast();
130 if (c.mLength == c.mArray.length) {
131 c = obtainChunk(length);
132 }
133 }
134 return c;
135 }
136
137 private Chunk obtainChunk(int length) {
138 Chunk c;
139 if (mPool.isEmpty()) {
140 c = new Chunk(length);
141 } else {
142 c = mPool.removeFirst();
143 }
144 mChunks.addLast(c);
145 return c;
146 }
147
148 public static class Chunk {
149 public byte[] mArray;
150 public int mLength;
151
152 public Chunk(int length) {
153 mArray = new byte[length];
154 mLength = 0;
155 }
156 }
157}