package php.runtime.memory.output; import php.runtime.Memory; import php.runtime.common.Modifier; import php.runtime.common.StringUtils; import php.runtime.env.Environment; import php.runtime.env.TraceInfo; import php.runtime.lang.Closure; import php.runtime.lang.ForeachIterator; import php.runtime.memory.*; import php.runtime.reflection.ClassEntity; import php.runtime.reflection.PropertyEntity; import java.io.Writer; import java.util.Set; public class VarDump extends Printer { private final static int PRINT_INDENT = 2; public VarDump(Environment env, Writer writer) { super(env, writer); } @Override protected void printReference(ReferenceMemory reference, int level, Set<Integer> used) { if (reference.isShortcut()) printer.write("&"); super.printReference(reference, level, used); } @Override protected void printNull() { printer.write("NULL\n"); } @Override protected void printFalse() { printer.write("bool(false)\n"); } @Override protected void printTrue() { printer.write("bool(true)\n"); } @Override protected void printLong(LongMemory value) { printer.write("int("); printer.write(value.toString()); printer.write(")\n"); } @Override protected void printDouble(DoubleMemory avalue) { printer.write("float("); double value = avalue.toDouble(); if (value == 0.0 && Double.doubleToRawLongBits(value) != Double.doubleToRawLongBits(0.0)) printer.write("-"); printer.write(avalue.toString()); printer.write(")\n"); } @Override protected void printString(StringMemory value) { String string = value.toString(); printer.write("string("); printer.write(string.length() + ""); printer.write(") \""); printer.write(string); printer.write("\"\n"); } @Override protected void printArray(ArrayMemory value, int level, Set<Integer> used) { if (used.contains(value.getPointer())){ printer.write("*RECURSION*\n"); } else { printer.write("array("); printer.write(value.size() + ""); printer.write(") {\n"); level += 1; used.add(value.getPointer()); ForeachIterator iterator = value.foreachIterator(false, false); while (iterator.next()){ Memory el = iterator.getValue(); if (el == Memory.UNDEFINED) continue; printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); Memory key = iterator.getMemoryKey(); printer.write('['); if (key.isString()){ printer.write('"'); printer.write(key.toString()); printer.write('"'); } else { printer.write(key.toString()); } printer.write("]=>\n"); printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); print(el, level, used); //printer.write('\n'); } level -= 1; printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); printer.write("}\n"); used.remove(value.getPointer()); } } @Override protected void printClosure(Closure closure, int level, Set<Integer> used) { ClassEntity classEntity = closure.getReflection(); if (used.contains(closure.getPointer())){ printer.write("*RECURSION*\n"); } else { printer.write("object("); printer.write(Closure.class.getSimpleName()); printer.write(")#" + closure.getPointer()); printer.write(" (" + closure.getUses().length + ") {\n"); level += PRINT_INDENT; used.add(closure.getPointer()); level -= PRINT_INDENT; printer.write(StringUtils.repeat(' ', level)); printer.write("}\n"); used.remove(closure.getPointer()); } } @Override protected void printObject(ObjectMemory value, int level, Set<Integer> used) { ClassEntity classEntity = value.getReflection(); if (used.contains(value.getPointer())){ printer.write("*RECURSION*\n"); } else { ArrayMemory arr; if (classEntity.methodMagicDebugInfo != null) { try { Memory tmp = env.invokeMethod(value.value, classEntity.methodMagicDebugInfo.getName()); if (tmp.isArray()) { arr = tmp.toValue(ArrayMemory.class); } else { arr = new ArrayMemory(); } } catch (RuntimeException e) { throw e; } catch (Throwable throwable) { throw new RuntimeException(throwable); } } else arr = value.getProperties(); printer.write("object("); printer.write(classEntity.getName()); printer.write(")#" + value.getPointer()); printer.write(" (" + arr.size() + ") {\n"); level += 1; used.add(value.getPointer()); if (classEntity.methodMagicDebugInfo == null) { for (PropertyEntity entity : classEntity.getProperties()) { if (entity.getGetter() != null && !entity.isHiddenInDebugInfo()) { printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); printer.write("[\""); printer.write(entity.getName()); printer.write('"'); printer.write(":getter]=>\n"); printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); try { print(entity.getValue(env, TraceInfo.UNKNOWN, value.value), level, used); } catch (RuntimeException e) { throw e; } catch (Throwable throwable) { throw new RuntimeException(throwable); } } } } ForeachIterator iterator = arr.foreachIterator(false, false); while (iterator.next()){ printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); Memory key = iterator.getMemoryKey(); printer.write('['); if (key.isString()){ String realKey = key.toString(); int pos; Modifier modifier = Modifier.PUBLIC; String className = ""; if ((pos = realKey.lastIndexOf("\0")) > -1){ if (realKey.startsWith("\0*\0")){ modifier = Modifier.PROTECTED; } else { modifier = Modifier.PRIVATE; className = realKey.substring(1, pos); } realKey = realKey.substring(pos + 1); } printer.write('"'); printer.write(realKey); printer.write('"'); switch (modifier) { case PRIVATE: printer.write(":\"" + className + "\":private"); break; case PROTECTED: printer.write(":protected"); } } else { printer.write(key.toString()); } printer.write("]=>\n"); printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); print(iterator.getValue(), level, used); //printer.write('\n'); } level -= 1; printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); printer.write("}\n"); used.remove(value.getPointer()); } } }