unserializereader.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 759 行

JAVA
759
字号
/* * 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.lib;import com.caucho.quercus.env.*;import com.caucho.util.IntMap;import com.caucho.util.IntSet;import com.caucho.util.L10N;import com.caucho.util.LruCache;import java.io.IOException;import java.util.ArrayList;import java.util.logging.Logger;public final class UnserializeReader {  private static final L10N L = new L10N(UnserializeReader.class);  private static final Logger log    = Logger.getLogger(UnserializeReader.class.getName());  private static final LruCache<StringKey,StringValue> _keyCache    = new LruCache<StringKey,StringValue>(4096);  private final char []_buffer;  private final int _length;  private int _index;  private StringKey _key = new StringKey();    private ArrayList<Value> _valueList    = new ArrayList<Value>();    private ArrayList<Boolean> _referenceList    = new ArrayList<Boolean>();    private boolean _useReference;  public UnserializeReader(StringValue s)    throws IOException  {    _buffer = s.toCharArray();    _length = _buffer.length;        if (s.indexOf("R:") >= 0)      initReferenceList();  }  public UnserializeReader(String s)     throws IOException  {    _buffer = s.toCharArray();    _length = _buffer.length;        if (s.indexOf("R:") >= 0)      initReferenceList();  }  boolean useReference()  {    return _useReference;  }  public Value unserialize(Env env)    throws IOException  {    int ch = read();    switch (ch) {    case 'b':      {        expect(':');        long v = readInt();        expect(';');                Value value = v == 0 ? BooleanValue.FALSE : BooleanValue.TRUE;                if (_useReference)          value = createReference(value);                return value;      }    case 's':    case 'S':      {        expect(':');        int len = (int) readInt();        expect(':');        expect('"');        Value value = readStringValue(env, len);        expect('"');        expect(';');                if (_useReference)          value = createReference(value);        return value;      }    case 'u':    case 'U':      {        expect(':');        int len = (int) readInt();        expect(':');        expect('"');        Value value = readUnicodeValue(env, len);        expect('"');        expect(';');                if (_useReference)          value = createReference(value);        return value;      }    case 'i':      {        expect(':');        long l = readInt();        expect(';');                Value value = LongValue.create(l);                 if (_useReference)          value = createReference(value);        return value;      }    case 'd':      {        expect(':');        StringBuilder sb = new StringBuilder();        for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {          sb.append((char) ch);        }        if (ch != ';')          throw new IOException(L.l("expected ';'"));        Value value = new DoubleValue(Double.parseDouble(sb.toString()));                if (_useReference)          value = createReference(value);                return value;      }    case 'a':      {        expect(':');        int len = (int) readInt();        expect(':');        expect('{');                Value array = new ArrayValueImpl(len);        if (_useReference)          array = createReference(array);                for (int i = 0; i < len; i++) {          Value key = unserializeKey(env);          Value value = unserialize(env);          array.put(key, value);        }        expect('}');        return array;      }    case 'O':      {        expect(':');        int len = (int) readInt();        expect(':');        expect('"');        String className = readString(len);        expect('"');        expect(':');        int count = (int) readInt();        expect(':');        expect('{');        QuercusClass qClass = env.findClass(className);        Value obj;        if (qClass != null)          obj = qClass.callNew(env, Env.EMPTY_VALUE);        else {          log.fine(L.l("{0} is an undefined class in unserialize",                   className));                    obj = env.createObject();          obj.putField(env,		       "__Quercus_Incomplete_Class_name",		       env.createString(className));        }                if (_useReference)          obj = createReference(obj);        for (int i = 0; i < count; i++) {          String key = unserializeString();          Value value = unserialize(env);          obj.putField(env, key, value);        }        expect('}');        return obj;      }    case 'N':      {        expect(';');                Value value = NullValue.NULL;                if (_useReference)          value = createReference(value);        return value;      }    case 'R':      {        _useReference = true;	        expect(':');        int value = (int) readInt();        expect(';');                Value ref = _valueList.get(value - 1);                return ref;      }    default:      return BooleanValue.FALSE;    }  }    public Value createReference(Value value)  {    if (_referenceList.get(_valueList.size()) == Boolean.FALSE) {            _valueList.add(value);      return value;    }    else {      Var var = new Var(value);            _valueList.add(var);      return var;    }  }  private void initReferenceList()    throws IOException  {    populateReferenceList();        _index = 0;  }    private void populateReferenceList()    throws IOException  {    int ch = read();    switch (ch) {      case 'b':      {        _referenceList.add(Boolean.FALSE);                expect(':');        for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {        }                return;      }      case 's':      case 'S':      {        _referenceList.add(Boolean.FALSE);                expect(':');        int len = (int) readInt();        expect(':');        expect('"');        _index += len;        expect('"');        expect(';');                return;      }      case 'u':      case 'U':      {        _referenceList.add(Boolean.FALSE);                expect(':');        int len = (int) readInt();        expect(':');        expect('"');        _index += len;        expect('"');        expect(';');                return;      }      case 'i':      {        _referenceList.add(Boolean.FALSE);                expect(':');        for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {        }                return;      }      case 'd':      {        _referenceList.add(Boolean.FALSE);                expect(':');        for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {        }                return;      }      case 'a':      {        _referenceList.add(Boolean.FALSE);                expect(':');        int len = (int) readInt();        expect(':');        expect('{');        for (int i = 0; i < len; i++) {          switch (read()) {          case 's':          case 'S':            {              expect(':');              int keyLen = (int) readInt();              expect(':');              expect('"');              _index += keyLen;              expect('"');              expect(';');                            break;                          }          case 'i':            {              expect(':');              for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {              }                            break;            }          }          populateReferenceList();        }        expect('}');                return;      }      case 'O':      {        _referenceList.add(Boolean.FALSE);                expect(':');        int len = (int) readInt();        expect(':');        expect('"');        _index += len;        expect('"');        expect(':');        int count = (int) readInt();        expect(':');        expect('{');        for (int i = 0; i < count; i++) {          switch (read()) {            case 's':            case 'S':              {                expect(':');                int keyLen = (int) readInt();                expect(':');                expect('"');                _index += keyLen;                expect('"');                expect(';');                                break;              }            case 'i':              {                expect(':');                for (ch = read(); ch >= 0 && ch != ';'; ch = read()) {                }                                break;              }          }          populateReferenceList();        }        expect('}');                return;      }      case 'N':      {        _referenceList.add(Boolean.FALSE);                expect(';');                return;      }      case 'R':      {        _useReference = true;                _referenceList.add(Boolean.FALSE);                expect(':');        int value = (int) readInt();        expect(';');                _referenceList.set(value - 1, Boolean.TRUE);                return;      }    }  }  public Value unserializeKey(Env env)    throws IOException  {    int ch = read();    switch (ch) {    case 's':    case 'S':      {        expect(':');        int len = (int) readInt();        expect(':');        expect('"');        StringValue v;        if (len < 32) {          _key.init(_buffer, _index, len);          v = _keyCache.get(_key);          if (v != null) {            _index += len;          }          else {            StringKey key = new StringKey(_buffer, _index, len);            v = readStringValue(env, len);            _keyCache.put(key, v);          }        }        else {          v = readStringValue(env, len);        }        expect('"');        expect(';');        return v;      }    case 'i':      {        expect(':');        long value = readInt();        expect(';');        return LongValue.create(value);      }    default:      return BooleanValue.FALSE;    }  }  private String unserializeString()    throws IOException  {    int ch = read();        if (ch != 's' && ch != 'S') {      throw new IOException(L.l("expected 's' at '{1}' (0x{2})",                                String.valueOf((char) ch),                                Integer.toHexString(ch)));    }    expect(':');    int len = (int) readInt();    expect(':');    expect('"');    String s = readString(len);    expect('"');    expect(';');    return s;  }  public final void expect(int expectCh)    throws IOException  {    if (_length <= _index)      throw new IOException(L.l("expected '{0}' at end of string",                                String.valueOf((char) expectCh)));    int ch = _buffer[_index++];    if (ch != expectCh) {      String context = String.valueOf((char) ch);            if (_index - 2 >= 0)        context = _buffer[_index - 2] + context;      if (_index < _buffer.length)        context += _buffer[_index];            throw new IOException(L.l("expected '{0}' at '{1}' (0x{2}) (context '{3}')",                                String.valueOf((char) expectCh),                                String.valueOf((char) ch),                                Integer.toHexString(ch),                                context));    }  }  public final long readInt()  {    int ch = read();    long sign = 1;    long value = 0;    if (ch == '-') {      sign = -1;      ch = read();    }    else if (ch == '+') {      ch = read();    }    for (; '0' <= ch && ch <= '9'; ch = read()) {      value = 10 * value + ch - '0';    }    unread();    return sign * value;  }  public final String readString(int len)  {    String s = new String(_buffer, _index, len);    _index += len;    return s;  }  public final StringValue readStringValue(Env env, int len)  {    StringValue s = env.createString(_buffer, _index, len);    _index += len;    return s;  }    public final StringValue readUnicodeValue(Env env, int len)  {    StringValue s = new UnicodeBuilderValue(_buffer, _index, len);    _index += len;    return s;  }  public final int read()  {    if (_index < _length)      return _buffer[_index++];    else      return -1;  }  public final int read(char []buffer, int offset, int length)  {    System.arraycopy(_buffer, _index, buffer, offset, length);    _index += length;    return length;  }  public final void unread()  {    _index--;  }  public final static class StringKey  {    char []_buffer;    int _offset;    int _length;    StringKey()    {    }    StringKey(char []buffer, int offset, int length)    {      _buffer = new char[length];      System.arraycopy(buffer, offset, _buffer, 0, length);      _offset = 0;      _length = length;    }    void init(char []buffer, int offset, int length)    {      _buffer = buffer;      _offset = offset;      _length = length;    }    public int hashCode()    {      char []buffer = _buffer;      int offset = _offset;      int end = offset + _length;      int hash = 17;      for (; offset < end; offset++)        hash = 65521 * hash + buffer[offset];      return hash;    }    public boolean equals(Object o)    {      if (! (o instanceof StringKey))        return false;      StringKey key = (StringKey) o;      int length = _length;      if (length != key._length)        return false;      char []aBuf = _buffer;      char []bBuf = key._buffer;      int aOffset = _offset;      int bOffset = key._offset;      int aEnd = aOffset + length;      while (aOffset < aEnd) {        if (aBuf[aOffset++] != bBuf[bOffset++])          return false;      }      return true;    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?