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 16package javassist.bytecode; 17 18import java.io.OutputStream; 19import java.io.IOException; 20 21final class ByteStream extends OutputStream { 22 private byte[] buf; 23 private int count; 24 25 public ByteStream() { this(32); } 26 27 public ByteStream(int size) { 28 buf = new byte[size]; 29 count = 0; 30 } 31 32 public int getPos() { return count; } 33 public int size() { return count; } 34 35 public void writeBlank(int len) { 36 enlarge(len); 37 count += len; 38 } 39 40 public void write(byte[] data) { 41 write(data, 0, data.length); 42 } 43 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 50 public void write(int b) { 51 enlarge(1); 52 int oldCount = count; 53 buf[oldCount] = (byte)b; 54 count = oldCount + 1; 55 } 56 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 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 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 89 public void writeFloat(float v) { 90 writeInt(Float.floatToIntBits(v)); 91 } 92 93 public void writeDouble(double v) { 94 writeLong(Double.doubleToLongBits(v)); 95 } 96 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 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 158 public void write(int pos, int value) { 159 buf[pos] = (byte)value; 160 } 161 162 public void writeShort(int pos, int value) { 163 buf[pos] = (byte)(value >>> 8); 164 buf[pos + 1] = (byte)value; 165 } 166 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 174 public byte[] toByteArray() { 175 byte[] buf2 = new byte[count]; 176 System.arraycopy(buf, 0, buf2, 0, count); 177 return buf2; 178 } 179 180 public void writeTo(OutputStream out) throws IOException { 181 out.write(buf, 0, count); 182 } 183 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