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