objectextvalue.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,740 行 · 第 1/3 页
JAVA
1,740 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.quercus.env;import com.caucho.quercus.Location;import com.caucho.quercus.expr.Expr;import com.caucho.quercus.expr.StringLiteralExpr;import com.caucho.quercus.program.AbstractFunction;import com.caucho.vfs.WriteStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.AbstractSet;import java.util.HashMap;import java.util.IdentityHashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeSet;/** * Represents a PHP object value. */public class ObjectExtValue extends ObjectValue implements Serializable{ private static final StringValue TO_STRING = new StringBuilderValue("__toString"); private static final int DEFAULT_SIZE = 16; private MethodMap<AbstractFunction> _methodMap; private Entry []_entries; private int _hashMask; private int _size; private boolean _isFieldInit; public ObjectExtValue(QuercusClass cl) { super(cl); _methodMap = cl.getMethodMap(); _entries = new Entry[DEFAULT_SIZE]; _hashMask = _entries.length - 1; } public ObjectExtValue(Env env, ObjectExtValue copy, CopyRoot root) { super(copy.getQuercusClass()); _methodMap = copy._methodMap; _size = copy._size; _isFieldInit = copy._isFieldInit; Entry []copyEntries = copy._entries; _entries = new Entry[copyEntries.length]; _hashMask = copy._hashMask; int len = copyEntries.length; for (int i = 0; i < len; i++) { Entry entry = copyEntries[i]; for (; entry != null; entry = entry._next) { Entry entryCopy = entry.copyTree(env, root); entryCopy._next = _entries[i]; if (_entries[i] != null) _entries[i]._prev = entryCopy; _entries[i] = entryCopy; } } } private void init() { _entries = new Entry[DEFAULT_SIZE]; _hashMask = _entries.length - 1; } @Override protected void setQuercusClass(QuercusClass cl) { super.setQuercusClass(cl); _methodMap = cl.getMethodMap(); } /** * Returns the number of entries. */ @Override public int getSize() { return _size; } /** * Gets a field value. */ @Override public final Value getField(Env env, StringValue name) { int hash = name.hashCode() & _hashMask; for (Entry entry = _entries[hash]; entry != null; entry = entry._next) { if (name.equals(entry._key)) return entry._value.toValue(); } Value value = getFieldExt(env, name); if (value != null) return value; else return _quercusClass.getField(env, this, name); } /** * Gets a field value. */ @Override public Value getThisField(Env env, StringValue name) { int hash = name.hashCode() & _hashMask; for (Entry entry = _entries[hash]; entry != null; entry = entry._next) { if (name.equals(entry._key)) return entry._value.toValue(); } Value value = getFieldExt(env, name); if (value != null) return value; else return UnsetValue.UNSET; } /** * Returns fields not specified by the value. */ protected Value getFieldExt(Env env, StringValue name) { return null; } /** * Returns the array ref. */ @Override public Var getFieldRef(Env env, StringValue name) { Entry entry = createEntry(name); Value value = entry._value; if (value instanceof Var) return (Var) value; Var var = new Var(value); entry.setValue(var); return var; } /** * Returns the array ref. */ @Override public Var getThisFieldRef(Env env, StringValue name) { Entry entry = createEntry(name); Value value = entry._value; if (value instanceof Var) return (Var) value; Var var = new Var(value); entry.setValue(var); return var; } /** * Returns the value as an argument which may be a reference. */ @Override public Value getFieldArg(Env env, StringValue name) { Entry entry = getEntry(name); if (entry != null) return entry.toArg(); else return new ArgGetFieldValue(env, this, name); } /** * Returns the value as an argument which may be a reference. */ @Override public Value getThisFieldArg(Env env, StringValue name) { Entry entry = getEntry(name); if (entry != null) return entry.toArg(); else return new ArgGetFieldValue(env, this, name); } /** * Returns the value as an argument which may be a reference. */ @Override public Value getFieldArgRef(Env env, StringValue name) { Entry entry = getEntry(name); if (entry != null) return entry.toArg(); else return new ArgGetFieldValue(env, this, name); } /** * Returns the value as an argument which may be a reference. */ @Override public Value getThisFieldArgRef(Env env, StringValue name) { Entry entry = getEntry(name); if (entry != null) return entry.toArg(); else return new ArgGetFieldValue(env, this, name); } /** * Adds a new value. */ @Override public Value putField(Env env, StringValue name, Value value) { Entry entry = getEntry(name); if (entry == null) { Value oldValue = putFieldExt(env, name, value); if (oldValue != null) return oldValue; if (! _isFieldInit) { AbstractFunction fieldSet = _quercusClass.getFieldSet(); if (fieldSet != null) { _isFieldInit = true; Value retVal = fieldSet.callMethod(env, this, name, value); _isFieldInit = false; return retVal; } } } entry = createEntry(name); Value oldValue = entry._value; if (value instanceof Var) { Var var = (Var) value; // for function return optimization var.setReference(); entry._value = var; } else if (oldValue instanceof Var) { oldValue.set(value); } else { entry._value = value; } return value; } /** * Sets/adds field to this object. */ @Override public Value putThisField(Env env, StringValue name, Value value) { Entry entry = getEntry(name); if (entry == null) { Value oldValue = putFieldExt(env, name, value); if (oldValue != null) return oldValue; if (! _isFieldInit) { AbstractFunction fieldSet = _quercusClass.getFieldSet(); if (fieldSet != null) { //php/09k7 _isFieldInit = true; Value retVal = fieldSet.callMethod(env, this, name, value); _isFieldInit = false; return retVal; } } } entry = createEntry(name); Value oldValue = entry._value; if (value instanceof Var) { Var var = (Var) value; // for function return optimization var.setReference(); entry._value = var; } else if (oldValue instanceof Var) { oldValue.set(value); } else { entry._value = value; } return value; } protected Value putFieldExt(Env env, StringValue name, Value value) { return null; } /** * Adds a new value to the object. */ @Override public void initField(StringValue key, Value value) { Entry entry = createEntry(key); entry._value = value; } /** * Removes a value. */ @Override public void unsetField(StringValue name) { int hash = name.hashCode() & _hashMask; for (Entry entry = _entries[hash]; entry != null; entry = entry._next) { if (name.equals(entry.getKey())) { Entry prev = entry._prev; Entry next = entry._next; if (prev != null) prev._next = next; else _entries[hash] = next; if (next != null) next._prev = prev; _size--; return; } } } /** * Gets a new value. */ private Entry getEntry(StringValue name) { int hash = name.hashCode() & _hashMask; for (Entry entry = _entries[hash]; entry != null; entry = entry._next) { if (name.equals(entry._key)) return entry; } return null; } /** * Creates the entry for a key. */ private Entry createEntry(StringValue name) { int hash = name.hashCode() & _hashMask; for (Entry entry = _entries[hash]; entry != null; entry = entry._next) { if (name.equals(entry._key)) return entry; } _size++; Entry newEntry = new Entry(name); Entry next = _entries[hash]; if (next != null) { newEntry._next = next; next._prev = newEntry; } _entries[hash] = newEntry; // XXX: possibly resize return newEntry; } // // array methods // /** * Returns the array value with the given key. */ @Override public Value get(Value key) { ArrayDelegate delegate = _quercusClass.getArrayDelegate(); // php/066q vs. php/0906 //return getField(null, key.toString()); if (delegate != null) return delegate.get(this, key); else return super.get(key); } /** * Sets the array value with the given key. */ @Override public Value put(Value key, Value value) { // php/0d94 ArrayDelegate delegate = _quercusClass.getArrayDelegate(); if (delegate != null) return delegate.put(this, key, value); else return super.put(key, value); } /** * Appends a new array value */ @Override public Value put(Value value) { // php/0d94 ArrayDelegate delegate = _quercusClass.getArrayDelegate(); if (delegate != null) return delegate.put(this, value); else return super.put(value); } /** * Unsets the array value */ @Override public Value remove(Value key) { ArrayDelegate delegate = _quercusClass.getArrayDelegate(); if (delegate != null) return delegate.unset(this, key); else return super.remove(key); } // // Foreach/Traversable functions // /** * Returns an iterator for the key => value pairs. */ @Override public Iterator<Map.Entry<Value, Value>> getIterator(Env env) { TraversableDelegate delegate = _quercusClass.getTraversableDelegate(); if (delegate != null) return delegate.getIterator(env, this); return new EntryIterator(_entries); } /** * Returns an iterator for the keys. */ @Override public Iterator<Value> getKeyIterator(Env env) { TraversableDelegate delegate = _quercusClass.getTraversableDelegate(); if (delegate != null) return delegate.getKeyIterator(env, this); return new KeyIterator(_entries); } /** * Returns an iterator for the values. */ @Override public Iterator<Value> getValueIterator(Env env) { TraversableDelegate delegate = _quercusClass.getTraversableDelegate();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?