package php.runtime.ext.spl; import php.runtime.Memory; import php.runtime.common.StringUtils; import php.runtime.env.Environment; import php.runtime.env.SplClassLoader; import php.runtime.env.TraceInfo; import php.runtime.ext.support.compile.FunctionsContainer; import php.runtime.invoke.Invoker; import php.runtime.lang.ForeachIterator; import php.runtime.lang.IObject; import php.runtime.lang.spl.Countable; import php.runtime.lang.spl.Traversable; import php.runtime.memory.ArrayMemory; import php.runtime.memory.LongMemory; import php.runtime.memory.ObjectMemory; import php.runtime.memory.StringMemory; import php.runtime.reflection.ClassEntity; import java.io.File; import java.util.Set; public class SPLFunctions extends FunctionsContainer { public static long iterator_apply(Environment env, TraceInfo trace, Memory object, Memory callback, Memory args) throws Throwable { if (expectingImplement(env, trace, 1, object, Traversable.class)){ Invoker invoker = expectingCallback(env, trace, 2, callback); if (invoker == null) return 0; if (args != null && !expecting(env, trace, 3, args, Memory.Type.ARRAY)){ return 0; } ForeachIterator iterator = object.getNewIterator(env, false, false); Memory[] values = args == null ? null : args.toValue(ArrayMemory.class).values(true); int i = 0; while (iterator.next()){ if (!invoker.call(values).toBoolean()) break; i++; } return i; } else return 0; } public static long iterator_apply(Environment env, TraceInfo trace, Memory object, Memory callback) throws Throwable { return iterator_apply(env, trace, object, callback, null); } public static long iterator_count(Environment env, TraceInfo trace, Memory object) { if (expectingImplement(env, trace, 1, object, Traversable.class)){ IObject tmp = object.toValue(ObjectMemory.class).value; if (tmp instanceof Countable){ return ((Countable)tmp).count(env).toLong(); } else { ForeachIterator iterator = object.getNewIterator(env, true, false); int i = 0; while (iterator.next()) i++; return i; } } else return 0; } public static Memory iterator_to_array(Environment env, TraceInfo trace, Memory object, boolean useKeys){ if (expectingImplement(env, trace, 1, object, Traversable.class)){ ArrayMemory result = new ArrayMemory(); ForeachIterator iterator = object.getNewIterator(env, false, false); while (iterator.next()){ if (useKeys){ result.refOfIndex(iterator.getMemoryKey()).assign(iterator.getValue()); } else { result.add(iterator.getValue()); } } return result.toConstant(); } return Memory.NULL; } public static Memory iterator_to_array(Environment env, TraceInfo trace, Memory object){ return iterator_to_array(env, trace, object, true); } public static Memory class_parents(Environment env, TraceInfo trace, Memory object, boolean autoLoad){ ClassEntity entity; if (object.isObject()){ entity = object.toValue(ObjectMemory.class).getReflection(); } else { entity = env.fetchClass(object.toString(), autoLoad); } if (entity == null) { env.warning(trace, "class_parents(): Class %s does not exist and could not be loaded", object.toString()); return Memory.FALSE; } ArrayMemory result = new ArrayMemory(); do { entity = entity.getParent(); if (entity == null) break; result.refOfIndex(entity.getName()).assign(entity.getName()); } while (true); return result.toConstant(); } public static Memory class_parents(Environment env, TraceInfo trace, Memory object){ return class_parents(env, trace, object, true); } public static Memory class_implements(Environment env, TraceInfo trace, Memory object, boolean autoLoad){ ClassEntity entity; if (object.isObject()){ entity = object.toValue(ObjectMemory.class).getReflection(); } else { entity = env.fetchClass(object.toString(), autoLoad); } if (entity == null) { env.warning(trace, "class_implements(): Class %s does not exist and could not be loaded", object.toString()); return Memory.FALSE; } ArrayMemory result = new ArrayMemory(); do { for (ClassEntity el : entity.getInterfaces().values()){ result.refOfIndex(el.getName()).assign(el.getName()); } entity = entity.getParent(); if (entity == null) break; } while (true); return result.toConstant(); } public static Memory class_implements(Environment env, TraceInfo trace, Memory object){ return class_implements(env, trace, object, true); } public static Memory spl_object_hash(Environment env, TraceInfo trace, Memory object){ if (expecting(env, trace, 1, object, Memory.Type.OBJECT)){ return LongMemory.valueOf(object.getPointer()); } else return Memory.FALSE; } public static boolean spl_autoload_register(Environment env, TraceInfo trace, Memory callback, boolean _throw, boolean prepend){ Invoker invoker = expectingCallback(env, trace, 1, callback); if (invoker == null) return false; env.registerAutoloader(new SplClassLoader(invoker, callback), prepend); return true; } public static boolean spl_autoload_register(Environment env, TraceInfo trace, Memory callback, boolean _throw){ return spl_autoload_register(env, trace, callback, _throw, false); } public static boolean spl_autoload_register(Environment env, TraceInfo trace, Memory callback){ return spl_autoload_register(env, trace, callback, true, false); } public static boolean spl_autoload_register(Environment env, TraceInfo trace){ return spl_autoload_register(env, trace, new StringMemory("spl_autoload"), true, false); } private static final StringMemory __autoloadMethod = new StringMemory("__autoload"); public static Memory spl_autoload_functions(Environment env){ ArrayMemory result = new ArrayMemory(); for (SplClassLoader loader : env.getClassLoaders()){ result.add(loader.getCallback().toImmutable()); } if (result.size() == 0){ if (env.__autoload == null){ Invoker invoker = Invoker.valueOf(env, null, __autoloadMethod); if (invoker != null) { env.__autoload = new SplClassLoader(invoker, __autoloadMethod); result.add(env.__autoload.getCallback().toImmutable()); } } } return result.toConstant(); } public static boolean spl_autoload_unregister(Environment env, TraceInfo trace, Memory callback){ Invoker invoker = expectingCallback(env, trace, 1, callback); if (invoker == null) return false; return env.unRegisterAutoloader(new SplClassLoader(invoker, callback)); } public static final StringMemory defaultExtensions = new StringMemory(".inc,.php"); public static String spl_autoload_extensions(Environment env, String extensions){ env.getOrCreateStatic("spl$autoload_extensions", defaultExtensions).assign(extensions); return extensions; } public static String spl_autoload_extensions(Environment env){ return env.getOrCreateStatic("spl$autoload_extensions", defaultExtensions).toString(); } public static void __$jphp_spl_autoload(Environment env, String className, String fileExtensions){ if (env.__autoload == null){ Invoker invoker = Invoker.valueOf(env, null, __autoloadMethod); if (invoker != null) env.__autoload = new SplClassLoader(invoker, __autoloadMethod); } if (env.__autoload != null) env.__autoload.load(new StringMemory(className), new StringMemory(fileExtensions)); } public static void __$jphp_spl_autoload(Environment env, String className){ __$jphp_spl_autoload(env, className, spl_autoload_extensions(env)); } public static void spl_autoload(Environment env, String className, String fileExtensions) throws Throwable { String[] extensions = StringUtils.split(fileExtensions, ",", 255); Set<String> includePaths = env.getIncludePaths(); for(String path : includePaths){ for(String e : extensions){ File file = new File(path, className + e); if (file.exists()){ env.__include(file.getPath()); return; } } } } public static void spl_autoload(Environment env, String className) throws Throwable { spl_autoload(env, className, spl_autoload_extensions(env)); } }