/*
* 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 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;
}
}
}