001    /*
002     * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.util;
027    
028    import java.io.*;
029    
030    /** A byte buffer is a flexible array which grows when elements are
031     *  appended. There are also methods to append names to byte buffers
032     *  and to convert byte buffers to names.
033     *
034     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
035     *  you write code that depends on this, you do so at your own risk.
036     *  This code and its internal interfaces are subject to change or
037     *  deletion without notice.</b>
038     */
039    public class ByteBuffer {
040    
041        /** An array holding the bytes in this buffer; can be grown.
042         */
043        public byte[] elems;
044    
045        /** The current number of defined bytes in this buffer.
046         */
047        public int length;
048    
049        /** Create a new byte buffer.
050         */
051        public ByteBuffer() {
052            this(64);
053        }
054    
055        /** Create a new byte buffer with an initial elements array
056         *  of given size.
057         */
058        public ByteBuffer(int initialSize) {
059            elems = new byte[initialSize];
060            length = 0;
061        }
062    
063        private void copy(int size) {
064            byte[] newelems = new byte[size];
065            System.arraycopy(elems, 0, newelems, 0, elems.length);
066            elems = newelems;
067        }
068    
069        /** Append byte to this buffer.
070         */
071        public void appendByte(int b) {
072            if (length >= elems.length) copy(elems.length * 2);
073            elems[length++] = (byte)b;
074        }
075    
076        /** Append `len' bytes from byte array,
077         *  starting at given `start' offset.
078         */
079        public void appendBytes(byte[] bs, int start, int len) {
080            while (length + len > elems.length) copy(elems.length * 2);
081            System.arraycopy(bs, start, elems, length, len);
082            length += len;
083        }
084    
085        /** Append all bytes from given byte array.
086         */
087        public void appendBytes(byte[] bs) {
088            appendBytes(bs, 0, bs.length);
089        }
090    
091        /** Append a character as a two byte number.
092         */
093        public void appendChar(int x) {
094            while (length + 1 >= elems.length) copy(elems.length * 2);
095            elems[length  ] = (byte)((x >>  8) & 0xFF);
096            elems[length+1] = (byte)((x      ) & 0xFF);
097            length = length + 2;
098        }
099    
100        /** Append an integer as a four byte number.
101         */
102        public void appendInt(int x) {
103            while (length + 3 >= elems.length) copy(elems.length * 2);
104            elems[length  ] = (byte)((x >> 24) & 0xFF);
105            elems[length+1] = (byte)((x >> 16) & 0xFF);
106            elems[length+2] = (byte)((x >>  8) & 0xFF);
107            elems[length+3] = (byte)((x      ) & 0xFF);
108            length = length + 4;
109        }
110    
111        /** Append a long as an eight byte number.
112         */
113        public void appendLong(long x) {
114            ByteArrayOutputStream buffer = new ByteArrayOutputStream(8);
115            DataOutputStream bufout = new DataOutputStream(buffer);
116            try {
117                bufout.writeLong(x);
118                appendBytes(buffer.toByteArray(), 0, 8);
119            } catch (IOException e) {
120                throw new AssertionError("write");
121            }
122        }
123    
124        /** Append a float as a four byte number.
125         */
126        public void appendFloat(float x) {
127            ByteArrayOutputStream buffer = new ByteArrayOutputStream(4);
128            DataOutputStream bufout = new DataOutputStream(buffer);
129            try {
130                bufout.writeFloat(x);
131                appendBytes(buffer.toByteArray(), 0, 4);
132            } catch (IOException e) {
133                throw new AssertionError("write");
134            }
135        }
136    
137        /** Append a double as a eight byte number.
138         */
139        public void appendDouble(double x) {
140            ByteArrayOutputStream buffer = new ByteArrayOutputStream(8);
141            DataOutputStream bufout = new DataOutputStream(buffer);
142            try {
143                bufout.writeDouble(x);
144                appendBytes(buffer.toByteArray(), 0, 8);
145            } catch (IOException e) {
146                throw new AssertionError("write");
147            }
148        }
149    
150        /** Append a name.
151         */
152        public void appendName(Name name) {
153            appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
154        }
155    
156        /** Reset to zero length.
157         */
158        public void reset() {
159            length = 0;
160        }
161    
162        /** Convert contents to name.
163         */
164        public Name toName(Names names) {
165            return names.fromUtf(elems, 0, length);
166        }
167    }