1 /*
2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.javac.util;
27 
28 import java.io.*;
29 
30 /** A byte buffer is a flexible array which grows when elements are
31  *  appended. There are also methods to append names to byte buffers
32  *  and to convert byte buffers to names.
33  *
34  *  <p><b>This is NOT part of any supported API.
35  *  If you write code that depends on this, you do so at your own risk.
36  *  This code and its internal interfaces are subject to change or
37  *  deletion without notice.</b>
38  */
39 public class ByteBuffer {
40 
41     /** An array holding the bytes in this buffer; can be grown.
42      */
43     public byte[] elems;
44 
45     /** The current number of defined bytes in this buffer.
46      */
47     public int length;
48 
49     /** Create a new byte buffer.
50      */
ByteBuffer()51     public ByteBuffer() {
52         this(64);
53     }
54 
55     /** Create a new byte buffer with an initial elements array
56      *  of given size.
57      */
ByteBuffer(int initialSize)58     public ByteBuffer(int initialSize) {
59         elems = new byte[initialSize];
60         length = 0;
61     }
62 
63     /** Append byte to this buffer.
64      */
appendByte(int b)65     public void appendByte(int b) {
66         elems = ArrayUtils.ensureCapacity(elems, length);
67         elems[length++] = (byte)b;
68     }
69 
70     /** Append `len' bytes from byte array,
71      *  starting at given `start' offset.
72      */
appendBytes(byte[] bs, int start, int len)73     public void appendBytes(byte[] bs, int start, int len) {
74         elems = ArrayUtils.ensureCapacity(elems, length + len);
75         System.arraycopy(bs, start, elems, length, len);
76         length += len;
77     }
78 
79     /** Append all bytes from given byte array.
80      */
appendBytes(byte[] bs)81     public void appendBytes(byte[] bs) {
82         appendBytes(bs, 0, bs.length);
83     }
84 
85     /** Append a character as a two byte number.
86      */
appendChar(int x)87     public void appendChar(int x) {
88         elems = ArrayUtils.ensureCapacity(elems, length + 1);
89         elems[length  ] = (byte)((x >>  8) & 0xFF);
90         elems[length+1] = (byte)((x      ) & 0xFF);
91         length = length + 2;
92     }
93 
94     /** Append an integer as a four byte number.
95      */
appendInt(int x)96     public void appendInt(int x) {
97         elems = ArrayUtils.ensureCapacity(elems, length + 3);
98         elems[length  ] = (byte)((x >> 24) & 0xFF);
99         elems[length+1] = (byte)((x >> 16) & 0xFF);
100         elems[length+2] = (byte)((x >>  8) & 0xFF);
101         elems[length+3] = (byte)((x      ) & 0xFF);
102         length = length + 4;
103     }
104 
105     /** Append a long as an eight byte number.
106      */
appendLong(long x)107     public void appendLong(long x) {
108         ByteArrayOutputStream buffer = new ByteArrayOutputStream(8);
109         DataOutputStream bufout = new DataOutputStream(buffer);
110         try {
111             bufout.writeLong(x);
112             appendBytes(buffer.toByteArray(), 0, 8);
113         } catch (IOException e) {
114             throw new AssertionError("write");
115         }
116     }
117 
118     /** Append a float as a four byte number.
119      */
appendFloat(float x)120     public void appendFloat(float x) {
121         ByteArrayOutputStream buffer = new ByteArrayOutputStream(4);
122         DataOutputStream bufout = new DataOutputStream(buffer);
123         try {
124             bufout.writeFloat(x);
125             appendBytes(buffer.toByteArray(), 0, 4);
126         } catch (IOException e) {
127             throw new AssertionError("write");
128         }
129     }
130 
131     /** Append a double as a eight byte number.
132      */
appendDouble(double x)133     public void appendDouble(double x) {
134         ByteArrayOutputStream buffer = new ByteArrayOutputStream(8);
135         DataOutputStream bufout = new DataOutputStream(buffer);
136         try {
137             bufout.writeDouble(x);
138             appendBytes(buffer.toByteArray(), 0, 8);
139         } catch (IOException e) {
140             throw new AssertionError("write");
141         }
142     }
143 
144     /** Append a name.
145      */
appendName(Name name)146     public void appendName(Name name) {
147         appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
148     }
149 
150      /** Append the content of a given input stream.
151      */
appendStream(InputStream is)152     public void appendStream(InputStream is) throws IOException {
153         try {
154             int start = length;
155             int initialSize = is.available();
156             elems = ArrayUtils.ensureCapacity(elems, length + initialSize);
157             int r = is.read(elems, start, initialSize);
158             int bp = start;
159             while (r != -1) {
160                 bp += r;
161                 elems = ArrayUtils.ensureCapacity(elems, bp);
162                 r = is.read(elems, bp, elems.length - bp);
163             }
164         } finally {
165             try {
166                 is.close();
167             } catch (IOException e) {
168                 /* Ignore any errors, as this stream may have already
169                  * thrown a related exception which is the one that
170                  * should be reported.
171                  */
172             }
173         }
174     }
175 
176     /** Extract an integer at position bp from elems.
177      */
getInt(int bp)178     public int getInt(int bp) {
179         return
180             ((elems[bp] & 0xFF) << 24) +
181             ((elems[bp+1] & 0xFF) << 16) +
182             ((elems[bp+2] & 0xFF) << 8) +
183             (elems[bp+3] & 0xFF);
184     }
185 
186 
187     /** Extract a long integer at position bp from elems.
188      */
getLong(int bp)189     public long getLong(int bp) {
190         DataInputStream elemsin =
191             new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
192         try {
193             return elemsin.readLong();
194         } catch (IOException e) {
195             throw new AssertionError(e);
196         }
197     }
198 
199     /** Extract a float at position bp from elems.
200      */
getFloat(int bp)201     public float getFloat(int bp) {
202         DataInputStream elemsin =
203             new DataInputStream(new ByteArrayInputStream(elems, bp, 4));
204         try {
205             return elemsin.readFloat();
206         } catch (IOException e) {
207             throw new AssertionError(e);
208         }
209     }
210 
211     /** Extract a double at position bp from elems.
212      */
getDouble(int bp)213     public double getDouble(int bp) {
214         DataInputStream elemsin =
215             new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
216         try {
217             return elemsin.readDouble();
218         } catch (IOException e) {
219             throw new AssertionError(e);
220         }
221     }
222 
223     /** Extract a character at position bp from elems.
224      */
getChar(int bp)225     public char getChar(int bp) {
226         return
227             (char)(((elems[bp] & 0xFF) << 8) + (elems[bp+1] & 0xFF));
228     }
229 
getByte(int bp)230     public byte getByte(int bp) {
231         return elems[bp];
232     }
233 
234     /** Reset to zero length.
235      */
reset()236     public void reset() {
237         length = 0;
238     }
239 
240     /** Convert contents to name.
241      */
toName(Names names)242     public Name toName(Names names) {
243         return names.fromUtf(elems, 0, length);
244     }
245 }
246