• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: ByteArrayOStream.java,v 1.1.1.1 2004/05/09 16:57:52 vlad_r Exp $
8  */
9 package com.vladium.util;
10 
11 import java.io.IOException;
12 import java.io.OutputStream;
13 
14 import com.vladium.util.asserts.$assert;
15 
16 // ----------------------------------------------------------------------------
17 /**
18  * An unsynchronized version of java.io.ByteArrayOutputStream that can expose
19  * the underlying byte array without a defensive clone and can also be converted
20  * to a {@link ByteArrayIStream} without intermediate array copies.<p>
21  *
22  * All argument validation is disabled in release mode.<p>
23  *
24  * NOTE: copy-on-write not supported
25  *
26  * @author (C) 2001, Vlad Roubtsov
27  */
28 public
29 final class ByteArrayOStream extends OutputStream
30 {
31     // public: ................................................................
32 
33     /**
34      * Callee takes ownership of 'buf'.
35      */
ByteArrayOStream(final int initialCapacity)36     public ByteArrayOStream (final int initialCapacity)
37     {
38         if ($assert.ENABLED)
39             $assert.ASSERT (initialCapacity >= 0, "negative initial capacity: " + initialCapacity);
40 
41         m_buf = new byte [initialCapacity];
42     }
43 
toByteIStream()44     public final ByteArrayIStream toByteIStream ()
45     {
46         return new ByteArrayIStream (m_buf, m_pos);
47     }
48 
write2(final int b1, final int b2)49     public final void write2 (final int b1, final int b2)
50     {
51         final int pos = m_pos;
52         final int capacity = pos + 2;
53         byte [] mbuf = m_buf;
54         final int mbuflen = mbuf.length;
55 
56         if (mbuflen < capacity)
57         {
58             final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
59 
60             if (pos < NATIVE_COPY_THRESHOLD)
61                 for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
62             else
63                 System.arraycopy (mbuf, 0, newbuf, 0, pos);
64 
65             m_buf = mbuf = newbuf;
66         }
67 
68         mbuf [pos] = (byte) b1;
69         mbuf [pos + 1] = (byte) b2;
70         m_pos = capacity;
71     }
72 
write3(final int b1, final int b2, final int b3)73     public final void write3 (final int b1, final int b2, final int b3)
74     {
75         final int pos = m_pos;
76         final int capacity = pos + 3;
77         byte [] mbuf = m_buf;
78         final int mbuflen = mbuf.length;
79 
80         if (mbuflen < capacity)
81         {
82             final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
83 
84             if (pos < NATIVE_COPY_THRESHOLD)
85                 for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
86             else
87                 System.arraycopy (mbuf, 0, newbuf, 0, pos);
88 
89             m_buf = mbuf = newbuf;
90         }
91 
92         mbuf [pos] = (byte) b1;
93         mbuf [pos + 1] = (byte) b2;
94         mbuf [pos + 2] = (byte) b3;
95         m_pos = capacity;
96     }
97 
write4(final int b1, final int b2, final int b3, final int b4)98     public final void write4 (final int b1, final int b2, final int b3, final int b4)
99     {
100         final int pos = m_pos;
101         final int capacity = pos + 4;
102         byte [] mbuf = m_buf;
103         final int mbuflen = mbuf.length;
104 
105         if (mbuflen < capacity)
106         {
107             final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
108 
109             if (pos < NATIVE_COPY_THRESHOLD)
110                 for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
111             else
112                 System.arraycopy (mbuf, 0, newbuf, 0, pos);
113 
114             m_buf = mbuf = newbuf;
115         }
116 
117         mbuf [pos] = (byte) b1;
118         mbuf [pos + 1] = (byte) b2;
119         mbuf [pos + 2] = (byte) b3;
120         mbuf [pos + 3] = (byte) b4;
121         m_pos = capacity;
122     }
123 
writeTo(final OutputStream out)124     public final void writeTo (final OutputStream out)
125         throws IOException
126     {
127         out.write (m_buf, 0, m_pos);
128     }
129 
130 //    public final void readFully (final InputStream in)
131 //        throws IOException
132 //    {
133 //        while (true)
134 //        {
135 //            int chunk = in.available ();
136 //
137 //            System.out.println ("available = " + chunk);
138 //
139 //            // TODO: this case is handled poorly (on EOF)
140 //            if (chunk == 0) chunk = READ_CHUNK_SIZE;
141 //
142 //            // read at least 'available' bytes: extend the capacity as needed
143 //
144 //            int free = m_buf.length - m_pos;
145 //
146 //            final int read;
147 //            if (free > chunk)
148 //            {
149 //                // try reading more than 'chunk' anyway:
150 //                read = in.read (m_buf, m_pos, free);
151 //            }
152 //            else
153 //            {
154 //                // extend the capacity to match 'chunk':
155 //                {
156 //                    System.out.println ("reallocation");
157 //                    final byte [] newbuf = new byte [m_pos + chunk];
158 //
159 //                    if (m_pos < NATIVE_COPY_THRESHOLD)
160 //                        for (int i = 0; i < m_pos; ++ i) newbuf [i] = m_buf [i];
161 //                    else
162 //                        System.arraycopy (m_buf, 0, newbuf, 0, m_pos);
163 //
164 //                    m_buf = newbuf;
165 //                }
166 //
167 //                read = in.read (m_buf, m_pos, chunk);
168 //            }
169 //
170 //            if (read < 0)
171 //                break;
172 //            else
173 //                m_pos += read;
174 //        }
175 //    }
176 
177 //    public final void addCapacity (final int extraCapacity)
178 //    {
179 //        final int pos = m_pos;
180 //        final int capacity = pos + extraCapacity;
181 //        byte [] mbuf = m_buf;
182 //        final int mbuflen = mbuf.length;
183 //
184 //        if (mbuflen < capacity)
185 //        {
186 //            final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
187 //
188 //            if (pos < NATIVE_COPY_THRESHOLD)
189 //                for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
190 //            else
191 //                System.arraycopy (mbuf, 0, newbuf, 0, pos);
192 //
193 //            m_buf = newbuf;
194 //        }
195 //    }
196 
getByteArray()197     public final byte [] getByteArray ()
198     {
199         return m_buf;
200     }
201 
202     /**
203      *
204      * @return [result.length = size()]
205      */
copyByteArray()206     public final byte [] copyByteArray ()
207     {
208         final int pos = m_pos;
209 
210         final byte [] result = new byte [pos];
211         final byte [] mbuf = m_buf;
212 
213         if (pos < NATIVE_COPY_THRESHOLD)
214             for (int i = 0; i < pos; ++ i) result [i] = mbuf [i];
215         else
216             System.arraycopy (mbuf, 0, result, 0, pos);
217 
218         return result;
219     }
220 
size()221     public final int size ()
222     {
223         return m_pos;
224     }
225 
capacity()226     public final int capacity ()
227     {
228         return m_buf.length;
229     }
230 
231     /**
232      * Does not reduce the current capacity.
233      */
reset()234     public final void reset ()
235     {
236         m_pos = 0;
237     }
238 
239     // OutputStream:
240 
write(final int b)241     public final void write (final int b)
242     {
243         final int pos = m_pos;
244         final int capacity = pos + 1;
245         byte [] mbuf = m_buf;
246         final int mbuflen = mbuf.length;
247 
248         if (mbuflen < capacity)
249         {
250             final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
251 
252             if (pos < NATIVE_COPY_THRESHOLD)
253                 for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
254             else
255                 System.arraycopy (mbuf, 0, newbuf, 0, pos);
256 
257             m_buf = mbuf = newbuf;
258         }
259 
260         mbuf [pos] = (byte) b;
261         m_pos = capacity;
262     }
263 
264 
write(final byte [] buf, final int offset, final int length)265     public final void write (final byte [] buf, final int offset, final int length)
266     {
267         if ($assert.ENABLED)
268             $assert.ASSERT ((offset >= 0) && (offset <= buf.length) &&
269                 (length >= 0) && ((offset + length) <= buf.length),
270                 "invalid input (" + buf.length + ", " + offset + ", " + length + ")");
271 
272         final int pos = m_pos;
273         final int capacity = pos + length;
274         byte [] mbuf = m_buf;
275         final int mbuflen = mbuf.length;
276 
277         if (mbuflen < capacity)
278         {
279             final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)];
280 
281             if (pos < NATIVE_COPY_THRESHOLD)
282                 for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i];
283             else
284                 System.arraycopy (mbuf, 0, newbuf, 0, pos);
285 
286             m_buf = mbuf = newbuf;
287         }
288 
289         if (length < NATIVE_COPY_THRESHOLD)
290             for (int i = 0; i < length; ++ i) mbuf [pos + i] = buf [offset + i];
291         else
292             System.arraycopy (buf, offset, mbuf, pos, length);
293 
294         m_pos = capacity;
295     }
296 
297 
298     /**
299      * Equivalent to {@link #reset()}.
300      */
close()301     public final void close ()
302     {
303         reset ();
304     }
305 
306     // protected: .............................................................
307 
308     // package: ...............................................................
309 
310     // private: ...............................................................
311 
312 
313     private byte [] m_buf;
314     private int m_pos;
315 
316 //    private static final int READ_CHUNK_SIZE        = 16 * 1024;
317     private static final int NATIVE_COPY_THRESHOLD  = 9;
318 
319 } // end of class
320 // ----------------------------------------------------------------------------