📄 stringvalue.java
字号:
/* * 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.Quercus;import com.caucho.quercus.QuercusException;import com.caucho.quercus.QuercusModuleException;import com.caucho.quercus.QuercusRuntimeException;import com.caucho.quercus.lib.file.BinaryInput;import com.caucho.vfs.TempBuffer;import com.caucho.vfs.TempCharBuffer;import com.caucho.vfs.TempStream;import com.caucho.vfs.WriteStream;import java.io.*;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.IdentityHashMap;/** * Represents a Quercus string value. */abstract public class StringValue extends Value implements CharSequence { public static final StringValue EMPTY = new StringBuilderValue(""); private final static StringValue []CHAR_STRINGS; protected static final int IS_STRING = 0; protected static final int IS_LONG = 1; protected static final int IS_DOUBLE = 2; /** * Creates the string. */ public static Value create(String value) { // XXX: needs updating for i18n, currently php5 only if (value == null) return NullValue.NULL; else return new StringBuilderValue(value); } /** * Creates the string. */ public static StringValue create(char value) { // XXX: needs updating for i18n, currently php5 only if (value < CHAR_STRINGS.length) return CHAR_STRINGS[value]; else return new StringBuilderValue(String.valueOf(value)); } /** * Creates the string. */ public static Value create(Object value) { // XXX: needs updating for i18n, currently php5 only if (value == null) return NullValue.NULL; else return new StringBuilderValue(value.toString()); } /* * Decodes the Unicode str from charset. * * @param str should be a Unicode string * @param charset to decode string from */ public StringValue create(Env env, StringValue unicodeStr, String charset) { if (! unicodeStr.isUnicode()) return unicodeStr; try { StringValue sb = createStringBuilder(); byte []bytes = unicodeStr.toString().getBytes(charset); sb.append(bytes); return sb; } catch (UnsupportedEncodingException e) { env.warning(e); return unicodeStr; } } /** * Creates a string builder of the same type. */ abstract public StringValue createStringBuilder(); /** * Creates a string builder of the same type. */ abstract public StringValue createStringBuilder(int length); /* * Returns the immutable empty string of same type. */ abstract public StringValue getEmptyString(); // // Predicates and relations // /** * Returns the type. */ public String getType() { return "string"; } /** * Returns the ValueType. */ @Override public ValueType getValueType() { return ValueType.STRING; } /** * Returns true for a long */ public boolean isLongConvertible() { return getValueType().isLongCmp(); } /** * Returns true for a double */ public boolean isDoubleConvertible() { return getValueType().isNumberCmp(); } /** * Returns true for a number */ public boolean isNumber() { return false; } /** * Returns true for is_numeric */ @Override public boolean isNumeric() { // php/120y return getValueType().isNumberCmp(); } /** * Returns true for a scalar */ public boolean isScalar() { return true; } /** * Returns true for StringValue */ @Override public boolean isString() { return true; } /* * Returns true if this is a PHP5 string. */ public boolean isPHP5String() { return false; } /** * Returns true if the value is empty */ @Override public boolean isEmpty() { return length() == 0 || length() == 1 && charAt(0) == '0'; } /** * Returns true for equality */ public int cmp(Value rValue) { if (isNumberConvertible() || rValue.isNumberConvertible()) { double l = toDouble(); double r = rValue.toDouble(); if (l == r) return 0; else if (l < r) return -1; else return 1; } else { int result = toString().compareTo(rValue.toString()); if (result == 0) return 0; else if (result > 0) return 1; else return -1; } } /** * Returns true for equality */ @Override public boolean eq(Value rValue) { ValueType typeA = getValueType(); ValueType typeB = rValue.getValueType(); if (typeB.isNumber()) { double l = toDouble(); double r = rValue.toDouble(); return l == r; } else if (typeB.isBoolean()) { return toBoolean() == rValue.toBoolean(); } else if (typeA.isNumberCmp() && typeB.isNumberCmp()) { double l = toDouble(); double r = rValue.toDouble(); return l == r; } else { return toString().equals(rValue.toString()); } } /** * Compare two strings */ public int cmpString(StringValue rValue) { return toString().compareTo(rValue.toString()); } // Conversions /** * Converts to a string value. */ public StringValue toStringValue() { return this; } /** * Converts to a long. */ public static long toLong(String string) { return parseLong(string); } /** * String to long conversion routines used by this module * and other modules in this package. These methods are * only invoked by other implementations of a "string" object. * The 3 implementations should be identical except for the * char data source. */ static long parseLong(char []buffer, int offset, int len) { if (len == 0) return 0; long value = 0; long sign = 1; boolean isResultSet = false; long result = 0; int end = offset + len; if (buffer[offset] == '-') { sign = -1; offset++; } else if (buffer[offset] == '+') { sign = +1; offset++; } while (offset < end) { int ch = buffer[offset++]; if ('0' <= ch && ch <= '9') { long newValue = 10 * value + ch - '0'; if (newValue < value) { // long value overflowed, set result to 0 result = 0; isResultSet = true; break; } value = newValue; } else { result = sign * value; isResultSet = true; break; } } if (!isResultSet) result = sign * value; return result; } static long parseLong(byte []buffer, int offset, int len) { if (len == 0) return 0; long value = 0; long sign = 1; boolean isResultSet = false; long result = 0; int end = offset + len; if (buffer[offset] == '-') { sign = -1; offset++; } else if (buffer[offset] == '+') { sign = +1; offset++; } while (offset < end) { int ch = buffer[offset++]; if ('0' <= ch && ch <= '9') { long newValue = 10 * value + ch - '0'; if (newValue < value) { // long value overflowed, set result to 0 result = 0; isResultSet = true; break; } value = newValue; } else { result = sign * value; isResultSet = true; break; } } if (!isResultSet) result = sign * value; return result; } static long parseLong(CharSequence string) { final int len = string.length(); if (len == 0) return 0; long value = 0; long sign = 1; boolean isResultSet = false; long result = 0; int offset = 0; int i = 0; int end = offset + len; if (string.charAt(offset) == '-') { sign = -1; offset++; } else if (string.charAt(offset) == '+') { sign = +1; offset++; } while (offset < end) { int ch = string.charAt(offset++); if ('0' <= ch && ch <= '9') { long newValue = 10 * value + ch - '0'; if (newValue < value) { // long value overflowed, set result to 0 result = 0; isResultSet = true; break; } value = newValue; } else { result = sign * value; isResultSet = true; break; } } if (!isResultSet) result = sign * value; return result; } /** * Converts to a double. */ public double toDouble() { return toDouble(toString()); } /** * Converts to a double. */ public static double toDouble(String s) { int len = s.length(); int i = 0; int ch = 0; if (i < len && ((ch = s.charAt(i)) == '+' || ch == '-')) { i++; } for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) { } if (ch == '.') { for (i++; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) { } } if (ch == 'e' || ch == 'E') { int e = i++; if (i < len && (ch = s.charAt(i)) == '+' || ch == '-') { i++; } for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) { } if (i == e + 1) i = e; } if (i == 0) return 0; else if (i == len) return Double.parseDouble(s); else return Double.parseDouble(s.substring(0, i)); } /** * Converts to a boolean. */ public boolean toBoolean() { int length = length(); if (length == 0) return false; else if (length > 1) return true; else return charAt(0) != '0'; } /** * Converts to a key. */ public Value toKey() { int len = length(); if (len == 0) return this; int sign = 1; long value = 0; int i = 0; char ch = charAt(i); if (ch == '-') { sign = -1; i++; } for (; i < len; i++) { ch = charAt(i); if ('0' <= ch && ch <= '9') value = 10 * value + ch - '0'; else return this; } return LongValue.create(sign * value); } /** * Converts to an object. */ @Override final public Value toAutoObject(Env env) { return env.createObject(); } /** * Converts to a Java object. */ public Object toJavaObject() { return toString(); } /** * Takes the values of this array, unmarshalls them to objects of type * <i>elementType</i>, and puts them in a java array. */ @Override public Object valuesToArray(Env env, Class elementType) { if (char.class.equals(elementType)) { return toUnicodeValue(env).toCharArray(); } else if (Character.class.equals(elementType)) { char[] chars = toUnicodeValue(env).toCharArray(); int length = chars.length; Character[] charObjects = new Character[length]; for (int i = 0; i <length; i++) { charObjects[i] = Character.valueOf(chars[i]); } return charObjects; } else if (byte.class.equals(elementType)) { return toBinaryValue(env).toBytes(); } else if (Byte.class.equals(elementType)) { byte[] bytes = toBinaryValue(env).toBytes(); int length = bytes.length; Byte[] byteObjects = new Byte[length]; for (int i = 0; i <length; i++) { byteObjects[i] = Byte.valueOf(bytes[i]); } return byteObjects; } else { env.error(L.l("Can't assign {0} with type {1} to {2}", this, this.getClass(), elementType)); return null; } } /** * Converts to an array if null. */ public Value toAutoArray() { if (length() == 0) return new ArrayValueImpl(); else return this; } // Operations /** * Returns the character at an index */ public Value get(Value key) { return charValueAt(key.toLong()); } /** * Returns the character at an index */ public Value getArg(Value key) { // php/03ma return charValueAt(key.toLong()); } /** * Returns the character at an index */ public Value getRef(Value key) { return charValueAt(key.toLong()); } /** * Returns the character at an index */ @Override public Value charValueAt(long index) { int len = length(); if (index < 0 || len <= index) return UnsetUnicodeValue.UNSET; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -