• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2010 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 
16 package javassist.bytecode;
17 
18 import java.io.OutputStream;
19 import java.io.IOException;
20 
21 final class ByteStream extends OutputStream {
22     private byte[] buf;
23     private int count;
24 
ByteStream()25     public ByteStream() { this(32); }
26 
ByteStream(int size)27     public ByteStream(int size) {
28         buf = new byte[size];
29         count = 0;
30     }
31 
getPos()32     public int getPos() { return count; }
size()33     public int size() { return count; }
34 
writeBlank(int len)35     public void writeBlank(int len) {
36         enlarge(len);
37         count += len;
38     }
39 
write(byte[] data)40     public void write(byte[] data) {
41         write(data, 0, data.length);
42     }
43 
write(byte[] data, int off, int len)44     public void write(byte[] data, int off, int len) {
45         enlarge(len);
46         System.arraycopy(data, off, buf, count, len);
47         count += len;
48     }
49 
write(int b)50     public void write(int b) {
51         enlarge(1);
52         int oldCount = count;
53         buf[oldCount] = (byte)b;
54         count = oldCount + 1;
55     }
56 
writeShort(int s)57     public void writeShort(int s) {
58         enlarge(2);
59         int oldCount = count;
60         buf[oldCount] = (byte)(s >>> 8);
61         buf[oldCount + 1] = (byte)s;
62         count = oldCount + 2;
63     }
64 
writeInt(int i)65     public void writeInt(int i) {
66         enlarge(4);
67         int oldCount = count;
68         buf[oldCount] = (byte)(i >>> 24);
69         buf[oldCount + 1] = (byte)(i >>> 16);
70         buf[oldCount + 2] = (byte)(i >>> 8);
71         buf[oldCount + 3] = (byte)i;
72         count = oldCount + 4;
73     }
74 
writeLong(long i)75     public void writeLong(long i) {
76         enlarge(8);
77         int oldCount = count;
78         buf[oldCount] = (byte)(i >>> 56);
79         buf[oldCount + 1] = (byte)(i >>> 48);
80         buf[oldCount + 2] = (byte)(i >>> 40);
81         buf[oldCount + 3] = (byte)(i >>> 32);
82         buf[oldCount + 4] = (byte)(i >>> 24);
83         buf[oldCount + 5] = (byte)(i >>> 16);
84         buf[oldCount + 6] = (byte)(i >>> 8);
85         buf[oldCount + 7] = (byte)i;
86         count = oldCount + 8;
87     }
88 
writeFloat(float v)89     public void writeFloat(float v) {
90         writeInt(Float.floatToIntBits(v));
91     }
92 
writeDouble(double v)93     public void writeDouble(double v) {
94         writeLong(Double.doubleToLongBits(v));
95     }
96 
writeUTF(String s)97     public void writeUTF(String s) {
98         int sLen = s.length();
99         int pos = count;
100         enlarge(sLen + 2);
101 
102         byte[] buffer = buf;
103         buffer[pos++] = (byte)(sLen >>> 8);
104         buffer[pos++] = (byte)sLen;
105         for (int i = 0; i < sLen; ++i) {
106             char c = s.charAt(i);
107             if (0x01 <= c && c <= 0x7f)
108                 buffer[pos++] = (byte)c;
109             else {
110                 writeUTF2(s, sLen, i);
111                 return;
112             }
113         }
114 
115         count = pos;
116     }
117 
writeUTF2(String s, int sLen, int offset)118     private void writeUTF2(String s, int sLen, int offset) {
119         int size = sLen;
120         for (int i = offset; i < sLen; i++) {
121             int c = s.charAt(i);
122             if (c > 0x7ff)
123                 size += 2;  // 3 bytes code
124             else if (c == 0 || c > 0x7f)
125                 ++size;     // 2 bytes code
126         }
127 
128         if (size > 65535)
129             throw new RuntimeException(
130                     "encoded string too long: " + sLen + size + " bytes");
131 
132         enlarge(size + 2);
133         int pos = count;
134         byte[] buffer = buf;
135         buffer[pos] = (byte)(size >>> 8);
136         buffer[pos + 1] = (byte)size;
137         pos += 2 + offset;
138         for (int j = offset; j < sLen; ++j) {
139             int c = s.charAt(j);
140             if (0x01 <= c && c <= 0x7f)
141                 buffer[pos++] = (byte) c;
142             else if (c > 0x07ff) {
143                 buffer[pos] = (byte)(0xe0 | ((c >> 12) & 0x0f));
144                 buffer[pos + 1] = (byte)(0x80 | ((c >> 6) & 0x3f));
145                 buffer[pos + 2] = (byte)(0x80 | (c & 0x3f));
146                 pos += 3;
147             }
148             else {
149                 buffer[pos] = (byte)(0xc0 | ((c >> 6) & 0x1f));
150                 buffer[pos + 1] = (byte)(0x80 | (c & 0x3f));
151                 pos += 2;
152             }
153         }
154 
155         count = pos;
156     }
157 
write(int pos, int value)158     public void write(int pos, int value) {
159         buf[pos] = (byte)value;
160     }
161 
writeShort(int pos, int value)162     public void writeShort(int pos, int value) {
163         buf[pos] = (byte)(value >>> 8);
164         buf[pos + 1] = (byte)value;
165     }
166 
writeInt(int pos, int value)167     public void writeInt(int pos, int value) {
168         buf[pos] = (byte)(value >>> 24);
169         buf[pos + 1] = (byte)(value >>> 16);
170         buf[pos + 2] = (byte)(value >>> 8);
171         buf[pos + 3] = (byte)value;
172     }
173 
toByteArray()174     public byte[] toByteArray() {
175         byte[] buf2 = new byte[count];
176         System.arraycopy(buf, 0, buf2, 0, count);
177         return buf2;
178     }
179 
writeTo(OutputStream out)180     public void writeTo(OutputStream out) throws IOException {
181         out.write(buf, 0, count);
182     }
183 
enlarge(int delta)184     public void enlarge(int delta) {
185         int newCount = count + delta;
186         if (newCount > buf.length) {
187             int newLen = buf.length << 1;
188             byte[] newBuf = new byte[newLen > newCount ? newLen : newCount];
189             System.arraycopy(buf, 0, newBuf, 0, count);
190             buf = newBuf;
191         }
192     }
193 }
194