Search in sources :

Example 1 with IteratorAggregate

use of php.runtime.lang.spl.iterator.IteratorAggregate in project jphp by jphp-compiler.

the class ObjectMemory method getNewIterator.

@Override
public ForeachIterator getNewIterator(final Environment env, boolean getReferences, boolean getKeyReferences) {
    if (value instanceof IteratorAggregate) {
        return env.invokeMethodNoThrow(value, "getIterator").getNewIterator(env, getReferences, getKeyReferences);
    } else if (value instanceof Iterator) {
        final Iterator iterator = (Iterator) value;
        final String className = value.getReflection().getName();
        final boolean isNative = value.getReflection().isInternal();
        return new ForeachIterator(getReferences, getKeyReferences, false) {

            private boolean keyInit = false;

            private boolean needNext = false;

            private boolean rewind = false;

            @Override
            public void reset() {
                rewind();
            }

            @Override
            protected boolean init() {
                return rewind();
            }

            protected boolean rewind() {
                if (getReferences && value instanceof Generator) {
                    if (!((Generator) value).isReturnReferences()) {
                        env.exception(trace, "You can only iterate a generator by-reference if it declared that it yields by-reference");
                    }
                }
                if (!rewind) {
                    if (!isNative)
                        env.pushCall(trace, ObjectMemory.this.value, null, "rewind", className, null);
                    try {
                        return iterator.rewind(env).toValue() != FALSE;
                    } finally {
                        rewind = true;
                        if (!isNative)
                            env.popCall();
                    }
                }
                return true;
            }

            @Override
            protected boolean prevValue() {
                return false;
            }

            @Override
            protected boolean nextValue() {
                return true;
            }

            @Override
            public boolean next() {
                if (!rewind())
                    return false;
                boolean valid = false;
                keyInit = false;
                if (needNext) {
                    if (!isNative)
                        env.pushCall(trace, ObjectMemory.this.value, null, "next", className, null);
                    try {
                        iterator.next(env);
                    } finally {
                        if (!isNative)
                            env.popCall();
                    }
                }
                needNext = true;
                if (!isNative)
                    env.pushCall(trace, ObjectMemory.this.value, null, "valid", className, null);
                try {
                    valid = iterator.valid(env).toBoolean();
                    if (valid) {
                        if (!isNative)
                            env.pushCall(trace, ObjectMemory.this.value, null, "current", className, null);
                        try {
                            currentValue = iterator.current(env);
                            if (!getReferences)
                                currentValue = currentValue.fast_toImmutable();
                        } finally {
                            if (!isNative)
                                env.popCall();
                        }
                    } else {
                        rewind = false;
                    }
                } finally {
                    if (!isNative)
                        env.popCall();
                }
                return valid;
            }

            @Override
            public Object getKey() {
                return getMemoryKey();
            }

            @Override
            public Memory getMemoryKey() {
                if (keyInit)
                    return (Memory) currentKey;
                if (!isNative)
                    env.pushCall(trace, ObjectMemory.this.value, null, "key", className, null);
                try {
                    currentKey = iterator.key(env).fast_toImmutable();
                    keyInit = true;
                    return (Memory) currentKey;
                } finally {
                    if (!isNative)
                        env.popCall();
                }
            }
        };
    } else if (value instanceof Traversable) {
        return ((Traversable) value).getNewIterator(env, getReferences, getKeyReferences);
    } else {
        return new ForeachIterator(getReferences, getKeyReferences, false) {

            private ForeachIterator child;

            private ClassEntity reflection;

            private ClassEntity context;

            @Override
            protected boolean init() {
                context = env.getLastClassOnStack();
                reflection = value.getReflection();
                child = value.getProperties().foreachIterator(getReferences, getKeyReferences);
                return true;
            }

            @Override
            public void reset() {
                child.reset();
            }

            @Override
            protected boolean nextValue() {
                while (true) {
                    if (!child.next())
                        return false;
                    if (child.getValue().isUninitialized()) {
                        boolean found = false;
                        while (child.next()) {
                            if (!child.getValue().isUninitialized()) {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                            return false;
                    }
                    Object key = child.getKey();
                    if (key instanceof String) {
                        String keyS = (String) key;
                        int pos = keyS.lastIndexOf('\0');
                        if (pos > -1)
                            keyS = keyS.substring(pos + 1);
                        PropertyEntity entity = reflection.isInstanceOf(context) ? context.properties.get(keyS) : reflection.properties.get(keyS);
                        int accessFlag = entity == null ? 0 : entity.canAccess(env);
                        if (accessFlag == 0) {
                            currentKey = entity == null ? keyS : entity.getName();
                            break;
                        } else
                            continue;
                    }
                    break;
                }
                // currentKey = child.getKey();
                currentValue = child.getValue();
                return true;
            }

            @Override
            protected boolean prevValue() {
                return false;
            }
        };
    }
}
Also used : ClassEntity(php.runtime.reflection.ClassEntity) Memory(php.runtime.Memory) IteratorAggregate(php.runtime.lang.spl.iterator.IteratorAggregate) PropertyEntity(php.runtime.reflection.PropertyEntity) Iterator(php.runtime.lang.spl.iterator.Iterator) IComparableObject(php.runtime.lang.support.IComparableObject) ICloneableObject(php.runtime.lang.support.ICloneableObject) Traversable(php.runtime.lang.spl.Traversable)

Aggregations

Memory (php.runtime.Memory)1 Traversable (php.runtime.lang.spl.Traversable)1 Iterator (php.runtime.lang.spl.iterator.Iterator)1 IteratorAggregate (php.runtime.lang.spl.iterator.IteratorAggregate)1 ICloneableObject (php.runtime.lang.support.ICloneableObject)1 IComparableObject (php.runtime.lang.support.IComparableObject)1 ClassEntity (php.runtime.reflection.ClassEntity)1 PropertyEntity (php.runtime.reflection.PropertyEntity)1