KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > util > ByteBufferOutputStream


1 // ========================================================================
2
// $Id: ByteBufferOutputStream.java,v 1.18 2006/10/08 14:13:19 gregwilkins Exp $
3
// Copyright 2001-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.util;
17 import java.io.IOException JavaDoc;
18 import java.io.OutputStream JavaDoc;
19
20 import org.apache.commons.logging.Log;
21 import org.mortbay.log.LogFactory;
22
23 /* ------------------------------------------------------------ */
24 /** ByteBuffer OutputStream.
25  * This stream is similar to the java.io.ByteArrayOutputStream,
26  * except that it maintains a reserve of bytes at the start of the
27  * buffer and allows efficient prepending of data.
28  *
29  * @version $Revision: 1.18 $
30  * @author Greg Wilkins (gregw)
31  */

32 public class ByteBufferOutputStream extends OutputStream JavaDoc
33 {
34     private static Log log = LogFactory.getLog(ByteBufferOutputStream.class);
35
36     protected byte[] _buf;
37     
38     /** The start of data capacity in the buffer
39      */

40     private int _start;
41     
42     /** The end of data capacity in the buffer
43      */

44     private int _end;
45     
46     /** The last byte of data written to the buffer
47      * _start <= _pos <= _end
48      */

49     private int _pos;
50     
51     private int _preReserve;
52     private int _postReserve;
53     private boolean _resized;
54     private boolean _fixed ;
55     
56     /* ------------------------------------------------------------ */
57     /** Constructor.
58      */

59     public ByteBufferOutputStream(){this(4096,0,0);}
60     
61     /* ------------------------------------------------------------ */
62     /** Constructor.
63      * @param capacity Buffer capacity
64      */

65     public ByteBufferOutputStream(int capacity)
66     {
67         this(capacity,0,0);
68     }
69     
70     /* ------------------------------------------------------------ */
71     /** Constructor.
72      * @param capacity Buffer capacity.
73      * @param preReserve The reserve of byte for prepending
74      */

75     public ByteBufferOutputStream(int capacity,int preReserve)
76     {
77         this(capacity,preReserve,0);
78     }
79     
80     /* ------------------------------------------------------------ */
81     /** Constructor.
82      * @param bufferSize The size of the buffer == capacity+preReserve+postReserve
83      * @param preReserve The reserve of byte for prepending
84      * @param postReserve The reserve of byte for appending
85      */

86     public ByteBufferOutputStream(int bufferSize,int preReserve,int postReserve)
87     {
88         _buf=ByteArrayPool.getByteArray(bufferSize);
89         _end=_buf.length-postReserve;
90         _preReserve=preReserve;
91         _start=preReserve;
92         _pos=preReserve;
93         _postReserve=postReserve;
94     }
95
96     /* ------------------------------------------------------------ */
97     /**
98      * @return True if the buffer cannot be expanded
99      */

100     public boolean isFixed()
101     {
102         return _fixed;
103     }
104     
105     /* ------------------------------------------------------------ */
106     /**
107      * @param fixed True if the buffer cannot be expanded
108      */

109     public void setFixed(boolean fixed)
110     {
111         _fixed = fixed;
112     }
113     
114     /* ------------------------------------------------------------ */
115     /**
116      * @return The size of valid data in the buffer.
117      */

118     public int size()
119     {
120         return _pos-_start;
121     }
122     
123     /* ------------------------------------------------------------ */
124     /**
125      * @return The size of the buffer.
126      */

127     public int bufferSize()
128     {
129         return _buf.length;
130     }
131     
132     /* ------------------------------------------------------------ */
133     /**
134      * @return The capacity of the buffer excluding pre and post reserves.
135      */

136     public int capacity()
137     {
138         return _end-_start;
139     }
140     
141     /* ------------------------------------------------------------ */
142     /**
143      * @return The available capacity of the buffer excluding pre and post
144      * reserves and data already written.
145      */

146     public int spareCapacity()
147     {
148         return _end-_pos;
149     }
150     
151     /* ------------------------------------------------------------ */
152     /**
153      * @return The current pre reserve.
154      */

155     public int preReserve()
156     {
157         return _start;
158     }
159     
160     /* ------------------------------------------------------------ */
161     /**
162      * @return The current post reserve.
163      */

164     public int postReserve()
165     {
166         return _buf.length-_end;
167     }
168     
169     /* ------------------------------------------------------------ */
170     public void writeTo(OutputStream JavaDoc out)
171         throws IOException JavaDoc
172     {
173         out.write(_buf,_start,_pos-_start);
174     }
175
176     /* ------------------------------------------------------------ */
177     public void write(int b)
178         throws IOException JavaDoc
179     {
180         ensureSpareCapacity(1);
181         _buf[_pos++]=(byte)b;
182     }
183     
184     /* ------------------------------------------------------------ */
185     public void write(byte[] b)
186         throws IOException JavaDoc
187     {
188         ensureSpareCapacity(b.length);
189         System.arraycopy(b,0,_buf,_pos,b.length);
190         _pos+=b.length;
191     }
192     
193     /* ------------------------------------------------------------ */
194     public void write(byte[] b,int offset, int length)
195         throws IOException JavaDoc
196     {
197         ensureSpareCapacity(length);
198         System.arraycopy(b,offset,_buf,_pos,length);
199         _pos+=length;
200     }
201     
202     /* ------------------------------------------------------------ */
203     /** Write byte to start of the buffer.
204      * @param b
205      */

206     public void prewrite(int b)
207     {
208         ensureReserve(1);
209         _buf[--_start]=(byte)b;
210     }
211     
212     /* ------------------------------------------------------------ */
213     /** Write byte array to start of the buffer.
214      * @param b
215      */

216     public void prewrite(byte[] b)
217     {
218         ensureReserve(b.length);
219         System.arraycopy(b,0,_buf,_start-b.length,b.length);
220         _start-=b.length;
221     }
222     
223     /* ------------------------------------------------------------ */
224     /** Write byte range to start of the buffer.
225      * @param b
226      * @param offset
227      * @param length
228      */

229     public void prewrite(byte[] b,int offset, int length)
230     {
231         ensureReserve(length);
232         System.arraycopy(b,offset,_buf,_start-length,length);
233         _start-=length;
234     }
235
236     /* ------------------------------------------------------------ */
237     /** Write bytes into the postreserve.
238      * The capacity is not checked.
239      * @param b
240      * @param offset
241      * @param length
242      * @exception IOException
243      */

244     public void postwrite(byte b)
245         throws IOException JavaDoc
246     {
247         _buf[_pos++]=b;
248     }
249
250     /* ------------------------------------------------------------ */
251     /** Write bytes into the postreserve.
252      * The capacity is not checked.
253      * @param b
254      * @param offset
255      * @param length
256      * @exception IOException
257      */

258     public void postwrite(byte[] b,int offset, int length)
259         throws IOException JavaDoc
260     {
261         System.arraycopy(b,offset,_buf,_pos,length);
262         _pos+=length;
263     }
264     
265     /* ------------------------------------------------------------ */
266     public void flush()
267         throws IOException JavaDoc
268     {
269     }
270     
271     /* ------------------------------------------------------------ */
272     public void resetStream()
273     {
274         _pos=_preReserve;
275         _start=_preReserve;
276     }
277     
278     /* ------------------------------------------------------------ */
279     public void reset(int reserve)
280     {
281         _preReserve=reserve;
282         _pos=_preReserve;
283         _start=_preReserve;
284     }
285
286     /* ------------------------------------------------------------ */
287     public void close()
288         throws IOException JavaDoc
289     {
290         flush();
291     }
292     
293     /* ------------------------------------------------------------ */
294     public void destroy()
295     {
296         if (!_resized)
297             ByteArrayPool.returnByteArray(_buf);
298         _buf=null;
299     }
300
301     /* ------------------------------------------------------------ */
302     public void ensureReserve(int n)
303     {
304         if (n>_start)
305         {
306             if (log.isDebugEnabled())log.debug("Reserve: "+n+">"+_start);
307             if ((_pos+n)<_end)
308             {
309                 if (log.isDebugEnabled())log.debug("Shift reserve: "+_pos+"+"+n+"<"+_end);
310                 System.arraycopy(_buf,_start,_buf,n,_pos-_start);
311                 _pos=_pos+n-_start;
312                 _start=n;
313             }
314             else
315             {
316                 if (log.isDebugEnabled())log.debug("New reserve: "+_pos+"+"+n+">="+_end);
317                 byte[] buf = new byte[_buf.length+n-_start];
318                 System.arraycopy(_buf,_start,buf,n,_pos-_start);
319                 _pos=n+_pos-_start;
320                 _start=n;
321                 _buf=buf;
322                 _end=_buf.length-_postReserve;
323             }
324         }
325     }
326     
327     
328     /* ------------------------------------------------------------ */
329     public void ensureSize(int bufSize)
330         throws IOException JavaDoc
331     {
332         ensureSize(bufSize,_preReserve,_postReserve);
333     }
334     
335     /* ------------------------------------------------------------ */
336     public void ensureSize(int bufSize, int pre, int post)
337         throws IOException JavaDoc
338     {
339         // Do we have space?
340
if (bufSize>_buf.length || pre>_preReserve || post>_postReserve)
341         {
342             // Make a bigger buffer if we are allowed.
343
if (_fixed)
344                 throw new IllegalStateException JavaDoc("Fixed");
345
346             byte[] old=_buf;
347             _buf=ByteArrayPool.getByteArray(bufSize);
348
349             if (_pos>_start)
350                 System.arraycopy(old,_start,_buf,pre,_pos-_start);
351             if (!_resized)
352                 ByteArrayPool.returnByteArray(old);
353             
354             _end=_buf.length-post;
355             _preReserve=pre;
356             _start=pre;
357             _pos=pre;
358             _postReserve=post;
359         }
360     }
361     
362     /* ------------------------------------------------------------ */
363     public void ensureSpareCapacity(int n)
364         throws IOException JavaDoc
365     {
366         // Do we have space?
367
if (n>spareCapacity())
368         {
369             // No, then try flushing what we do have
370
if (_pos>_start )
371                 flush();
372
373             ensureCapacity(n);
374         }
375     }
376     
377     /* ------------------------------------------------------------ */
378     public void ensureCapacity(int n)
379         throws IOException JavaDoc
380     {
381         // Do we have space?
382
if (n>capacity())
383         {
384             // Make a bigger buffer if we are allowed.
385
if (_fixed)
386                 throw new IllegalStateException JavaDoc("Fixed");
387                 
388             int new_size = ((n+_preReserve+_postReserve+4095)/4096)*4096;
389             
390             byte[] old = _buf;
391             _buf = new byte[new_size];
392             if (_pos>_start)
393                 System.arraycopy(old,_start,_buf,_start,_pos-_start);
394             if (!_resized)
395                 ByteArrayPool.returnByteArray(old);
396                 
397             _end=_buf.length-_postReserve;
398             _resized=true;
399         }
400     }
401 }
402     
403     
404
Popular Tags