package php.runtime.loader.dump.io;
import php.runtime.Memory;
import php.runtime.env.TraceInfo;
import php.runtime.lang.ForeachIterator;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.helper.ClassConstantMemory;
import php.runtime.memory.helper.ConstantMemory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class DumpOutputStream extends DataOutputStream {
public DumpOutputStream(OutputStream out) {
super(out);
}
public void writeName(String value) throws IOException {
if (value == null)
writeInt(-1);
else {
writeInt(value.length());
writeUTF(value);
}
}
public void writeTrace(TraceInfo trace) throws IOException {
writeBoolean(trace != null);
if (trace != null){
writeInt(trace.getStartLine());
writeInt(trace.getStartPosition());
writeUTF(trace.getFileName());
}
}
public void writeMemory(Memory memory) throws IOException {
if (memory == null){
writeInt(-1);
return;
}
memory = memory.toValue();
if (memory instanceof ConstantMemory){
writeInt(-2);
writeUTF(((ConstantMemory) memory).getName());
return;
} else if (memory instanceof ClassConstantMemory){
writeInt(-3);
writeUTF(((ClassConstantMemory) memory).getClassName());
writeUTF(((ClassConstantMemory) memory).getName());
return;
}
Memory.Type type = memory.getRealType();
writeInt(type.ordinal());
switch (type){
case NULL:
break;
case INT:
writeLong(memory.toLong());
break;
case STRING:
writeUTF(memory.toString());
break;
case DOUBLE:
writeDouble(memory.toDouble());
break;
case BOOL:
writeBoolean(memory.toBoolean());
break;
case ARRAY:
ArrayMemory array = memory.toValue(ArrayMemory.class);
if (array.size() > Short.MAX_VALUE)
throw new DumpException("Array is too big");
writeInt(array.size());
ForeachIterator foreachIterator = array.foreachIterator(false, false);
while (foreachIterator.next()){
Memory key = foreachIterator.getMemoryKey();
Memory value = foreachIterator.getValue();
if (value.isShortcut())
throw new DumpException("Cannot dump references");
if (value.toValue() != Memory.UNDEFINED){
writeMemory(key);
writeMemory(value.toValue());
}
}
break;
case OBJECT:
default:
throw new DumpException("Cannot dump "+ type.toString() +" memory");
}
}
public final static int MAX_LENGTH_OF_RAW_DATA = 1024 * 200; // 200 kb
public void writeRawData(byte[] bytes, int max) throws IOException {
if (bytes == null || bytes.length == 0)
writeInt(0);
else {
if (bytes.length > max)
throw new DumpException("Raw-size is too big, max " + MAX_LENGTH_OF_RAW_DATA);
writeInt(bytes.length);
write(bytes);
}
}
public void writeRawData(byte[] bytes) throws IOException {
writeRawData(bytes, MAX_LENGTH_OF_RAW_DATA);
}
public void writeEnum(Enum _enum) throws IOException {
writeInt(_enum == null ? -1 : _enum.ordinal());
}
}