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 PrintR extends Printer { protected int PRINT_INDENT = 4; public PrintR(Environment env, Writer writer) { super(env, writer); } @Override protected void printNull() { // nop; } @Override protected void printFalse() { // nop; } @Override protected void printTrue() { printer.write("1"); } @Override protected void printLong(LongMemory value) { printer.write(value.toString()); } @Override protected void printDouble(DoubleMemory value) { printer.write(value.toString()); } @Override protected void printString(StringMemory value) { printer.write(value.toString()); } protected void writeArrayHeader(){ printer.write("Array\n"); } protected void writeClose(){ printer.write(")\n"); } protected void writeSeparator(boolean isLast){ printer.write('\n'); } protected void writeOpen(){ printer.write("(\n"); } @Override protected void printArray(ArrayMemory value, int level, Set<Integer> used) { writeArrayHeader(); if (used.contains(value.getPointer())){ printer.write(" *RECURSION*"); } else { printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); writeOpen(); level += 1; used.add(value.getPointer()); ForeachIterator iterator = value.foreachIterator(false, false); int i = 0; int size = value.size(); 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('['); printer.write(key.toString()); printer.write("] => "); print(el, level + 1, used); writeSeparator(i == size - 1); i++; } level -= 1; printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); writeClose(); used.remove(value.getPointer()); } } protected void writeObjectHeader(String name){ printer.write(name); printer.write(" Object\n"); } @Override protected void printClosure(Closure closure, int level, Set<Integer> used) { ClassEntity classEntity = closure.getReflection(); writeObjectHeader(Closure.class.getSimpleName()); if (used.contains(closure.getPointer())){ printer.write(" *RECURSION*"); } else { printer.write(StringUtils.repeat(' ', level)); writeOpen(); level += PRINT_INDENT; used.add(closure.getPointer()); level -= PRINT_INDENT; printer.write(StringUtils.repeat(' ', level)); writeClose(); used.remove(closure.getPointer()); } } @Override protected void printObject(ObjectMemory value, int level, Set<Integer> used) { ClassEntity classEntity = value.getReflection(); writeObjectHeader(classEntity.getName()); if (used.contains(value.getPointer())){ printer.write(" *RECURSION*"); } else { printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); writeOpen(); level += 1; used.add(value.getPointer()); ArrayMemory props; if (env != null && classEntity.methodMagicDebugInfo != null) { try { Memory tmp = env.invokeMethod(value.value, classEntity.methodMagicDebugInfo.getName()); if (tmp.isArray()) { props = tmp.toValue(ArrayMemory.class); } else { props = new ArrayMemory(); } } catch (RuntimeException e) { throw e; } catch (Throwable throwable) { throw new RuntimeException(throwable); } } else { props = value.getProperties(); } 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(":getter] => "); try { print(entity.getValue(env, TraceInfo.UNKNOWN, value.value)); } catch (RuntimeException e) { throw e; } catch (Throwable throwable) { throw new RuntimeException(throwable); } writeSeparator(false); } } } if (props != null) { ForeachIterator iterator = props.foreachIterator(false, false); int i = 0; int size = classEntity.properties.size(); while (iterator.next()){ printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); Object key = iterator.getKey(); printer.write('['); 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(realKey); switch (modifier) { case PRIVATE: printer.write(":" + className + ":private"); break; case PROTECTED: printer.write(":protected"); } printer.write("] => "); print(iterator.getValue(), level + 1, used); writeSeparator(i == size - 1); i++; } } level -= 1; printer.write(StringUtils.repeat(' ', level * PRINT_INDENT)); writeClose(); used.remove(value.getPointer()); } } }