/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package io.github.proxyhotswap.javassist.bytecode;
import java.io.OutputStream;
import java.io.IOException;
final class ByteStream extends OutputStream {
private byte[] buf;
private int count;
public ByteStream() { this(32); }
public ByteStream(int size) {
buf = new byte[size];
count = 0;
}
public int getPos() { return count; }
public int size() { return count; }
public void writeBlank(int len) {
enlarge(len);
count += len;
}
public void write(byte[] data) {
write(data, 0, data.length);
}
public void write(byte[] data, int off, int len) {
enlarge(len);
System.arraycopy(data, off, buf, count, len);
count += len;
}
public void write(int b) {
enlarge(1);
int oldCount = count;
buf[oldCount] = (byte)b;
count = oldCount + 1;
}
public void writeShort(int s) {
enlarge(2);
int oldCount = count;
buf[oldCount] = (byte)(s >>> 8);
buf[oldCount + 1] = (byte)s;
count = oldCount + 2;
}
public void writeInt(int i) {
enlarge(4);
int oldCount = count;
buf[oldCount] = (byte)(i >>> 24);
buf[oldCount + 1] = (byte)(i >>> 16);
buf[oldCount + 2] = (byte)(i >>> 8);
buf[oldCount + 3] = (byte)i;
count = oldCount + 4;
}
public void writeLong(long i) {
enlarge(8);
int oldCount = count;
buf[oldCount] = (byte)(i >>> 56);
buf[oldCount + 1] = (byte)(i >>> 48);
buf[oldCount + 2] = (byte)(i >>> 40);
buf[oldCount + 3] = (byte)(i >>> 32);
buf[oldCount + 4] = (byte)(i >>> 24);
buf[oldCount + 5] = (byte)(i >>> 16);
buf[oldCount + 6] = (byte)(i >>> 8);
buf[oldCount + 7] = (byte)i;
count = oldCount + 8;
}
public void writeFloat(float v) {
writeInt(Float.floatToIntBits(v));
}
public void writeDouble(double v) {
writeLong(Double.doubleToLongBits(v));
}
public void writeUTF(String s) {
int sLen = s.length();
int pos = count;
enlarge(sLen + 2);
byte[] buffer = buf;
buffer[pos++] = (byte)(sLen >>> 8);
buffer[pos++] = (byte)sLen;
for (int i = 0; i < sLen; ++i) {
char c = s.charAt(i);
if (0x01 <= c && c <= 0x7f)
buffer[pos++] = (byte)c;
else {
writeUTF2(s, sLen, i);
return;
}
}
count = pos;
}
private void writeUTF2(String s, int sLen, int offset) {
int size = sLen;
for (int i = offset; i < sLen; i++) {
int c = s.charAt(i);
if (c > 0x7ff)
size += 2; // 3 bytes code
else if (c == 0 || c > 0x7f)
++size; // 2 bytes code
}
if (size > 65535)
throw new RuntimeException(
"encoded string too long: " + sLen + size + " bytes");
enlarge(size + 2);
int pos = count;
byte[] buffer = buf;
buffer[pos] = (byte)(size >>> 8);
buffer[pos + 1] = (byte)size;
pos += 2 + offset;
for (int j = offset; j < sLen; ++j) {
int c = s.charAt(j);
if (0x01 <= c && c <= 0x7f)
buffer[pos++] = (byte) c;
else if (c > 0x07ff) {
buffer[pos] = (byte)(0xe0 | ((c >> 12) & 0x0f));
buffer[pos + 1] = (byte)(0x80 | ((c >> 6) & 0x3f));
buffer[pos + 2] = (byte)(0x80 | (c & 0x3f));
pos += 3;
}
else {
buffer[pos] = (byte)(0xc0 | ((c >> 6) & 0x1f));
buffer[pos + 1] = (byte)(0x80 | (c & 0x3f));
pos += 2;
}
}
count = pos;
}
public void write(int pos, int value) {
buf[pos] = (byte)value;
}
public void writeShort(int pos, int value) {
buf[pos] = (byte)(value >>> 8);
buf[pos + 1] = (byte)value;
}
public void writeInt(int pos, int value) {
buf[pos] = (byte)(value >>> 24);
buf[pos + 1] = (byte)(value >>> 16);
buf[pos + 2] = (byte)(value >>> 8);
buf[pos + 3] = (byte)value;
}
public byte[] toByteArray() {
byte[] buf2 = new byte[count];
System.arraycopy(buf, 0, buf2, 0, count);
return buf2;
}
public void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
public void enlarge(int delta) {
int newCount = count + delta;
if (newCount > buf.length) {
int newLen = buf.length << 1;
byte[] newBuf = new byte[newLen > newCount ? newLen : newCount];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;
}
}
}