use of php.runtime.lang.spl.Traversable 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.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).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;
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;
}
};
}
}
Aggregations