package php.runtime.memory.support; import php.runtime.Memory; import php.runtime.common.HintType; import php.runtime.env.Environment; import php.runtime.env.TraceInfo; import php.runtime.ext.java.JavaObject; import php.runtime.memory.*; import java.util.*; public class MemoryUtils { protected final static Map<Class<?>, Unconverter> UNCONVERTERS = new HashMap<Class<?>, Unconverter>(){{ put(Double.class, new Unconverter<Double>() { @Override public Memory run(Double value) { return new DoubleMemory(value); } }); put(Double.TYPE, get(Double.class)); put(Float.class, new Unconverter<Float>() { @Override public Memory run(Float value) { return new DoubleMemory(value); } }); put(Float.TYPE, get(Float.class)); put(Long.class, new Unconverter<Long>() { @Override public Memory run(Long value) { return LongMemory.valueOf(value); } }); put(Long.TYPE, get(Long.class)); put(Integer.class, new Unconverter<Integer>() { @Override public Memory run(Integer value) { return LongMemory.valueOf(value); } }); put(Integer.TYPE, get(Integer.class)); put(Short.class, new Unconverter<Short>() { @Override public Memory run(Short value) { return LongMemory.valueOf(value); } }); put(Short.TYPE, get(Short.class)); put(Short.class, new Unconverter<Byte>() { @Override public Memory run(Byte value) { return LongMemory.valueOf(value); } }); put(Byte.TYPE, get(Byte.class)); put(Character.class, new Unconverter<Character>() { @Override public Memory run(Character value) { return new StringMemory(value); } }); put(Character.TYPE, get(Character.class)); put(Boolean.class, new Unconverter<Boolean>() { @Override public Memory run(Boolean value) { return value ? Memory.TRUE : Memory.FALSE; } }); put(Boolean.TYPE, get(Boolean.class)); put(String.class, new Unconverter<String>() { @Override public Memory run(String value) { return new StringMemory(value); } }); put(Memory.class, new Unconverter<Memory>() { @Override public Memory run(Memory value) { return value; } }); put(Memory[].class, new Unconverter<Memory[]>() { @Override public Memory run(Memory[] value) { return new ArrayMemory(false, value); } }); }}; protected final static Map<Class<?>, Converter> CONVERTERS = new HashMap<Class<?>, Converter>(){{ // double put(Double.class, new Converter<Double>() { @Override public Double run(Environment env, TraceInfo trace, Memory value) { return value.toDouble(); } }); put(Double.TYPE, get(Double.class)); // float put(Float.class, new Converter<Float>() { @Override public Float run(Environment env, TraceInfo trace, Memory value) { return (float)value.toDouble(); } }); put(Float.TYPE, get(Float.class)); // long put(Long.class, new Converter<Long>() { @Override public Long run(Environment env, TraceInfo trace, Memory value) { return value.toLong(); } }); put(Long.TYPE, get(Long.class)); // int put(Integer.class, new Converter<Integer>() { @Override public Integer run(Environment env, TraceInfo trace, Memory value) { return (int)value.toLong(); } }); put(Integer.TYPE, get(Integer.class)); // short put(Short.class, new Converter<Short>() { @Override public Short run(Environment env, TraceInfo trace, Memory value) { return (short)value.toLong(); } }); put(Short.TYPE, get(Short.class)); // byte put(Byte.class, new Converter<Byte>() { @Override public Byte run(Environment env, TraceInfo trace, Memory value) { return (byte)value.toLong(); } }); put(Byte.TYPE, get(Byte.class)); // char put(Character.class, new Converter<Character>() { @Override public Character run(Environment env, TraceInfo trace, Memory value) { return value.toChar(); } }); put(Character.TYPE, get(Character.class)); // bool put(Boolean.class, new Converter<Boolean>() { @Override public Boolean run(Environment env, TraceInfo trace, Memory value) { return value.toBoolean(); } }); put(Boolean.TYPE, get(Boolean.class)); // string put(String.class, new Converter<String>() { @Override public String run(Environment env, TraceInfo trace, Memory value) { return value.toString(); } }); put(Memory.class, new Converter<Memory>() { @Override public Memory run(Environment env, TraceInfo trace, Memory value) { return value; } }); put(Memory[].class, new Converter<Memory[]>() { @Override public Memory[] run(Environment env, TraceInfo trace, Memory value) { if (value.isArray()){ List<Memory> result = new ArrayList<Memory>(); for(Memory one : (ArrayMemory)value){ result.add(one.toImmutable()); } return result.toArray(new Memory[]{}); } else { return null; } } }); }}; public static Converter<?> getConverter(Class<?> type){ return CONVERTERS.get(type); } public static Converter<?>[] getConverters(Class<?>[] types){ Converter<?>[] result = new Converter[types.length]; for(int i = 0; i < types.length; i++){ result[i] = getConverter(types[i]); } return result; } public static Unconverter getUnconverter(Class<?> type){ return UNCONVERTERS.get(type); } public static Object fromMemory(Memory value, Class<?> type){ if (value.instanceOf("php\\lang\\JavaObject")) return ((JavaObject)value.toValue(ObjectMemory.class).value).getObject(); Converter converter = getConverter(type); if (converter != null) return converter.run(value); else return value; } public static Object toValue(Memory value, Class<?> type){ if (type == Double.TYPE || type == Double.class) return value.toDouble(); if (type == Float.TYPE || type == Float.class) return (float)value.toDouble(); if (type == Long.TYPE || type == Long.class) return value.toLong(); if (type == Integer.TYPE || type == Integer.class) return (int)value.toLong(); if (type == Short.TYPE || type == Short.class) return (short)value.toLong(); if (type == Byte.TYPE || type == Byte.class) return (byte)value.toLong(); if (type == Character.TYPE || type == Character.class) return value.toChar(); if (type == String.class) return value.toString(); if (type == Boolean.TYPE || type == Boolean.class) return value.toBoolean(); if (type == Memory.class) return value; if (type == Memory[].class){ if (value.isArray()){ List<Memory> result = new ArrayList<Memory>(); for(Memory one : (ArrayMemory)value){ result.add(one.toImmutable()); } return result.toArray(new Memory[]{}); } else { return null; } } throw new IllegalArgumentException("Unexpected class type: " + type.getName()); } public static Memory valueOf(Object value){ return valueOf(null, value); } public static Memory valueOf(Environment env, Object value){ if (value == null) return Memory.NULL; Unconverter unconverter = getUnconverter(value.getClass()); if (unconverter != null) { return unconverter.run(value); } else { if (value instanceof Memory) return (Memory)value; if (env == null) if (value instanceof Collection){ ArrayMemory result = new ArrayMemory(); for (Object el : (Collection)value) result.add(valueOf(el)); return result; } else if (value instanceof Map){ ArrayMemory result = new ArrayMemory(); for (Map.Entry el : ((Map<?, ?>)value).entrySet()) result.refOfIndex(valueOf(el.getKey())).assign(valueOf(el.getValue())); return result; } else if (value.getClass().isArray()){ ArrayMemory result = new ArrayMemory(); for (Object el : (Object[])value) result.add(valueOf(el)); return result; } if (env != null) return new ObjectMemory(JavaObject.of(env, value)); else return null; //} } } public static Memory valueOf(String value, HintType type){ switch (type){ case STRING: return new StringMemory(value); case ANY: if (value.equals("false")) return Memory.FALSE; if (value.equals("true")) return Memory.TRUE; else if (value.equalsIgnoreCase("null")) return Memory.NULL; Memory m = StringMemory.toNumeric(value, false, null); return m != null ? m : new StringMemory(value); case DOUBLE: return new DoubleMemory(Double.parseDouble(value)); case INT: { return LongMemory.valueOf(Long.parseLong(value)); } case ARRAY: return new ArrayMemory(); case BOOLEAN: return new StringMemory(value).toBoolean() ? Memory.TRUE : Memory.FALSE; case CALLABLE: return new StringMemory(value); default: throw new IllegalArgumentException("Unsupported type - " + type); } } public static Memory valueForList(Memory memory, long index) { if (memory.isArray()) { return memory.valueOfIndex(index); } else return Memory.NULL; } abstract public static class Converter<T> { abstract public T run(Environment env, TraceInfo trace, Memory value); final public T run(Memory value) { return run(null, null, value); } } public static interface Unconverter<T> { Memory run(T value); } }