1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.asn1.ber.digester.rules ;
18
19
20 import java.nio.ByteBuffer;
21
22 import org.apache.commons.lang.ArrayUtils;
23
24
25 /***
26 * Gathers bytes from buffers while dynamically growing to accomodate a new size.
27 *
28 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
29 * @version $Rev: 157644 $
30 */
31 public class ByteAccumulator
32 {
33 /*** the default initial size */
34 private static final int DEFAULT_INIT_SIZE = 0 ;
35 /*** the default initial size */
36 private static final int DEFAULT_INCREMENT = 100 ;
37
38 /*** the accumulator's backing store */
39 private byte[] bs ;
40 /*** the current position of the accumulator */
41 private int pos ;
42 /*** the growth increment used to augment the backing store */
43 private int increment ;
44 /*** the initial size of the backing store */
45 private int initial = DEFAULT_INIT_SIZE ;
46
47
48
49
50
51
52 /***
53 * Creates a ByteAccumulator used to gather bytes from various sources
54 * with a default initial size and a default growth increment.
55 */
56 public ByteAccumulator()
57 {
58 bs = ArrayUtils.EMPTY_BYTE_ARRAY ;
59 pos = 0 ;
60 initial = DEFAULT_INIT_SIZE ;
61 increment = DEFAULT_INCREMENT ;
62 }
63
64
65 /***
66 * Creates a ByteAccumulator used to gather bytes from various sources
67 * with a default initial size and a default growth increment.
68 *
69 * @param initial the initial size for the backing store
70 */
71 ByteAccumulator( int initial )
72 {
73 if ( initial <= 0 )
74 {
75 bs = ArrayUtils.EMPTY_BYTE_ARRAY ;
76 this.initial = 0 ;
77 }
78 else
79 {
80 bs = new byte[initial] ;
81 this.initial = initial ;
82 }
83
84 pos = 0 ;
85 increment = DEFAULT_INCREMENT ;
86 }
87
88
89 /***
90 * Fills this accumulator with the content of the argument buffer into
91 * this accumulator. The buffer argument is fully drained when this
92 * operation completes.
93 *
94 * @param buf the buffer to fill into this accumulator
95 */
96 public void fill( ByteBuffer buf )
97 {
98 while ( buf.hasRemaining() )
99 {
100 if ( pos >= bs.length )
101 {
102 int size = 0 ;
103
104 if ( buf.remaining() > increment )
105 {
106 size = bs.length + buf.remaining() ;
107 }
108 else
109 {
110 size = bs.length + increment ;
111 }
112
113 byte[] dest = new byte[ size ] ;
114 System.arraycopy( bs, 0, dest, 0, bs.length ) ;
115 bs = dest ;
116 }
117
118
119
120
121
122 int spaceLeft = bs.length - pos ;
123 if ( buf.remaining() <= spaceLeft )
124 {
125 int remaining = buf.remaining() ;
126 buf.get( bs, pos, remaining ) ;
127 pos += remaining ;
128 return ;
129 }
130
131
132
133
134
135
136 buf.get( bs, pos, spaceLeft ) ;
137 pos += spaceLeft ;
138 }
139 }
140
141
142 /***
143 * Wraps a ByteBuffer around the populated bytes of this ByteAccumulator
144 * and resets the backing store to a newly allocated byte array of initial
145 * size.
146 *
147 * @return the compacted byte[] wrapped as a ByteBuffer
148 */
149 public ByteBuffer drain()
150 {
151 ByteBuffer compacted ;
152
153 if ( pos == bs.length )
154 {
155 compacted = ByteBuffer.wrap( bs ) ;
156 }
157 else
158 {
159 compacted = ByteBuffer.wrap( bs, 0, pos ) ;
160 }
161
162 if ( initial <= 0 )
163 {
164 bs = ArrayUtils.EMPTY_BYTE_ARRAY ;
165 }
166 else
167 {
168 bs = new byte[initial] ;
169 }
170
171 pos = 0 ;
172 return compacted ;
173 }
174
175
176 /***
177 * Wraps a ByteBuffer around the populated bytes of this ByteAccumulator
178 * and resets the backing store to a newly allocated byte array of initial
179 * size.
180 *
181 * @return the compacted byte[] wrapped as a ByteBuffer
182 */
183 public ByteBuffer drain( int initial )
184 {
185 ByteBuffer compacted ;
186
187 if ( pos == bs.length )
188 {
189 compacted = ByteBuffer.wrap( bs ) ;
190 }
191 else
192 {
193 compacted = ByteBuffer.wrap( bs, 0, pos ) ;
194 }
195
196 if ( initial <= 0 )
197 {
198 bs = ArrayUtils.EMPTY_BYTE_ARRAY ;
199 }
200 else
201 {
202 bs = new byte[initial] ;
203 }
204
205 pos = 0 ;
206 return compacted ;
207 }
208
209
210 /***
211 * Allocates memory to handle a capacity without the need to grow.
212 * This serves to control growth for more efficient use.
213 *
214 * @param capacity the capacity to hold without the need to grow
215 */
216 public void ensureCapacity( int capacity )
217 {
218 if ( bs.length < capacity )
219 {
220 byte[] newArray = new byte[capacity] ;
221
222 if ( bs != ArrayUtils.EMPTY_BYTE_ARRAY )
223 {
224 System.arraycopy( bs, 0, newArray, 0, pos + 1 ) ;
225 }
226
227 bs = newArray ;
228 }
229 }
230
231
232 /***
233 * The growth increment by which the backing store is augmented.
234 *
235 * @return the number of bytes to grow the backing store by
236 */
237 public int getGrowthIncrement()
238 {
239 return increment ;
240 }
241
242
243 /***
244 * The initial size of the backing store.
245 *
246 * @return the initial size in bytes of the backing store
247 */
248 public int getInitialSize()
249 {
250 return initial ;
251 }
252
253
254 /***
255 * The current capacity of the backing store which may change as this
256 * accumulator is filled with bytes.
257 *
258 * @return the current capacity in bytes
259 */
260 public int getCapacity()
261 {
262 return bs.length ;
263 }
264
265
266 /***
267 * The remaining free space that can be filled before having to grow the
268 * backing store of the accumulator.
269 *
270 * @return the remaining free space until the next growth spurt
271 */
272 public int getRemainingSpace()
273 {
274 return bs.length - pos ;
275 }
276
277
278 /***
279 * The current position within the backing store marking the point to
280 * which this accumulator is filled.
281 *
282 * @return the current fill position
283 */
284 public int getPosition()
285 {
286 return pos ;
287 }
288
289
290 /***
291 * Gets a compacted copy of this ByteAccumulator's backing store. The
292 * compacted byte array is equal to the amount of bytes put into this
293 * ByteAccumulator which may still have free space to populate since the
294 * last growth took place.
295 *
296 * @return the compacted copy of this ByteAccumulator
297 */
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316 }