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