169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2010 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.OutputStream;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalfinal class ByteStream extends OutputStream {
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private byte[] buf;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int count;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ByteStream() { this(32); }
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ByteStream(int size) {
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf = new byte[size];
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = 0;
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getPos() { return count; }
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int size() { return count; }
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeBlank(int len) {
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(len);
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count += len;
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(byte[] data) {
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        write(data, 0, data.length);
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(byte[] data, int off, int len) {
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(len);
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        System.arraycopy(data, off, buf, count, len);
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count += len;
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(int b) {
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(1);
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int oldCount = count;
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount] = (byte)b;
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = oldCount + 1;
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeShort(int s) {
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(2);
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int oldCount = count;
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount] = (byte)(s >>> 8);
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 1] = (byte)s;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = oldCount + 2;
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeInt(int i) {
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(4);
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int oldCount = count;
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount] = (byte)(i >>> 24);
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 1] = (byte)(i >>> 16);
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 2] = (byte)(i >>> 8);
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 3] = (byte)i;
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = oldCount + 4;
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeLong(long i) {
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(8);
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int oldCount = count;
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount] = (byte)(i >>> 56);
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 1] = (byte)(i >>> 48);
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 2] = (byte)(i >>> 40);
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 3] = (byte)(i >>> 32);
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 4] = (byte)(i >>> 24);
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 5] = (byte)(i >>> 16);
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 6] = (byte)(i >>> 8);
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[oldCount + 7] = (byte)i;
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = oldCount + 8;
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeFloat(float v) {
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        writeInt(Float.floatToIntBits(v));
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeDouble(double v) {
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        writeLong(Double.doubleToLongBits(v));
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeUTF(String s) {
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int sLen = s.length();
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int pos = count;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(sLen + 2);
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] buffer = buf;
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer[pos++] = (byte)(sLen >>> 8);
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer[pos++] = (byte)sLen;
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < sLen; ++i) {
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            char c = s.charAt(i);
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (0x01 <= c && c <= 0x7f)
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos++] = (byte)c;
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                writeUTF2(s, sLen, i);
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = pos;
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void writeUTF2(String s, int sLen, int offset) {
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int size = sLen;
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = offset; i < sLen; i++) {
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int c = s.charAt(i);
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c > 0x7ff)
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                size += 2;  // 3 bytes code
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (c == 0 || c > 0x7f)
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ++size;     // 2 bytes code
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (size > 65535)
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new RuntimeException(
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    "encoded string too long: " + sLen + size + " bytes");
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        enlarge(size + 2);
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int pos = count;
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] buffer = buf;
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer[pos] = (byte)(size >>> 8);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer[pos + 1] = (byte)size;
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        pos += 2 + offset;
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int j = offset; j < sLen; ++j) {
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int c = s.charAt(j);
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (0x01 <= c && c <= 0x7f)
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos++] = (byte) c;
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (c > 0x07ff) {
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos] = (byte)(0xe0 | ((c >> 12) & 0x0f));
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos + 1] = (byte)(0x80 | ((c >> 6) & 0x3f));
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos + 2] = (byte)(0x80 | (c & 0x3f));
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 3;
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos] = (byte)(0xc0 | ((c >> 6) & 0x1f));
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buffer[pos + 1] = (byte)(0x80 | (c & 0x3f));
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 2;
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        count = pos;
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(int pos, int value) {
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos] = (byte)value;
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeShort(int pos, int value) {
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos] = (byte)(value >>> 8);
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos + 1] = (byte)value;
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeInt(int pos, int value) {
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos] = (byte)(value >>> 24);
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos + 1] = (byte)(value >>> 16);
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos + 2] = (byte)(value >>> 8);
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf[pos + 3] = (byte)value;
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public byte[] toByteArray() {
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] buf2 = new byte[count];
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        System.arraycopy(buf, 0, buf2, 0, count);
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return buf2;
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void writeTo(OutputStream out) throws IOException {
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.write(buf, 0, count);
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void enlarge(int delta) {
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int newCount = count + delta;
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (newCount > buf.length) {
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int newLen = buf.length << 1;
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] newBuf = new byte[newLen > newCount ? newLen : newCount];
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            System.arraycopy(buf, 0, newBuf, 0, count);
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            buf = newBuf;
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
194