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