/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.debug.core.zend.debugger;
import static org.eclipse.php.internal.debug.core.model.IPHPDataType.DataType.*;
import static org.eclipse.php.internal.debug.core.model.IVariableFacet.Facet.KIND_ARRAY_MEMBER;
import static org.eclipse.php.internal.debug.core.model.IVariableFacet.Facet.KIND_OBJECT_MEMBER;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
public class ExpressionsValueDeserializer {
private String fEncoding;
public ExpressionsValueDeserializer(String encoding) {
fEncoding = encoding;
}
public ExpressionValue deserializer(Expression expression, byte[] value) {
if (value == null) {
// the expression is Illeagal.
value = new byte[] { 'N' };
}
return build(expression, new VariableReader(value));
}
private String getText(byte[] buf) {
try {
return new String(buf, fEncoding);
} catch (UnsupportedEncodingException e) {
}
return new String(buf);
}
private ExpressionValue build(Expression expression, VariableReader reader) {
char type = reader.readType();
switch (type) {
case 'i':
return buildIntType(reader);
case 'd':
return buildFloatType(reader);
case 's':
return buildSringType(reader);
case 'b':
return buildBooleanType(reader);
case 'r':
return buildResourceType(reader);
case 'a':
return buildArrayType(expression, reader);
case 'O':
return buildObjectType(expression, reader);
}
return ExpressionValue.NULL_VALUE;
}
private ExpressionValue buildIntType(VariableReader reader) {
String value = reader.readToken();
String valueAsString = value; // $NON-NLS-1$
return new ExpressionValue(PHP_INT, value, valueAsString, null);
}
private ExpressionValue buildFloatType(VariableReader reader) {
String value = reader.readToken();
String valueAsString = value; // $NON-NLS-1$
return new ExpressionValue(PHP_FLOAT, value, valueAsString, null);
}
private ExpressionValue buildSringType(VariableReader reader) {
String value = reader.readString();
String valueAsString = "\"" + value + "\""; //$NON-NLS-1$ //$NON-NLS-2$
return new ExpressionValue(PHP_STRING, value, valueAsString, null);
}
private ExpressionValue buildBooleanType(VariableReader reader) {
String value = reader.readToken();
String valueAsString = ((value.equals("0")) ? "false" : "true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return new ExpressionValue(PHP_BOOL, value, valueAsString, null);
}
private ExpressionValue buildResourceType(VariableReader reader) {
int resourceNumber = reader.readInt();
reader.readInt();
String value = reader.readToken();
String valueAsString = "resource (" + resourceNumber + ") of type (" //$NON-NLS-1$ //$NON-NLS-2$
+ value + ')';
return new ExpressionValue(PHP_RESOURCE, value, valueAsString, null);
}
private ExpressionValue buildArrayType(Expression expression, VariableReader reader) {
int objectLength = reader.readInt();
int originalLength = objectLength;
if (reader.isLastEnd()) {
objectLength = 0;
}
Expression[] variableNodes = new Expression[objectLength];
for (int i = 0; i < objectLength; i++) {
char type = reader.readType();
// System.out.println("type " + type);
String name;
if (type == 'i') {
name = Integer.toString(reader.readInt());
} else if (type == 's') {
name = reader.readString();
} else {
// fall back when type is invalid
return ExpressionValue.NULL_VALUE;
}
if (expression == null) {
variableNodes[i] = createDefaultVariable(name);
} else {
variableNodes[i] = expression.createChildExpression(name, '[' + name + ']', KIND_ARRAY_MEMBER);
}
variableNodes[i].setValue(build(expression, reader));
}
return new ExpressionValue(PHP_ARRAY, "Array", //$NON-NLS-1$
"Array [" + originalLength + ']', variableNodes, originalLength); //$NON-NLS-1$
}
private ExpressionValue buildObjectType(Expression expression, VariableReader reader) {
String className = reader.readString();
int objectLength = reader.readInt();
int originalLength = objectLength;
if (reader.isLastEnd()) {
objectLength = 0;
}
Expression[] expressionNodes = new Expression[objectLength];
for (int i = 0; i < objectLength; i++) {
char type = reader.readType();
// System.out.println("type " + type);
String name;
if (type == 'i') {
name = Integer.toString(reader.readInt());
} else if (type == 's') {
name = reader.readString();
} else {
// fall back when type is invalid
return ExpressionValue.NULL_VALUE;
}
if (expression == null) {
expressionNodes[i] = createDefaultVariable(name);
} else {
expressionNodes[i] = expression.createChildExpression(name, "->" + name, KIND_OBJECT_MEMBER); //$NON-NLS-1$
}
expressionNodes[i].setValue(build(expression, reader));
}
String valueAsString = "Object of: " + PHPModelUtils.extractElementName(className); //$NON-NLS-1$
return new ExpressionValue(PHP_OBJECT, className, valueAsString, expressionNodes, originalLength);
}
private Expression createDefaultVariable(String name) {
return new DefaultExpression('$' + name);
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// variable reader.
// ////////////////////////////////////////////////////////////////////////////////////////////////
private class VariableReader extends ByteArrayInputStream {
private VariableReader(byte[] result) {
super(result);
}
private char readType() {
char curr;
do {
int temp = super.read();
if (temp == -1) {
return ' ';
}
curr = (char) temp;
} while (curr == ';' || curr == ':' || curr == '{' || curr == '}');
return curr;
}
private String readToken() {
StringBuffer buffer = new StringBuffer(6);
char curr;
do {
curr = (char) super.read();
} while (curr == ';' || curr == ':');
while (curr != ';' && curr != ':') {
buffer.append(curr);
curr = (char) super.read();
}
return buffer.toString();
}
private String readString() {
int length = readInt();
while ((char) super.read() != '"')
;
byte[] bytes = new byte[length];
read(bytes, 0, length);
super.read(); // read '"'
return getText(bytes);
}
public int readInt() {
int result = 0;
char curr;
boolean isMinus = false;
do {
curr = (char) super.read();
if (curr == '-') {
isMinus = true;
}
} while (!Character.isDigit(curr));
do {
result *= 10;
result += Character.getNumericValue(curr);
this.mark(1);
} while (Character.isDigit(curr = (char) super.read()));
if (isMinus) {
result *= -1;
}
return result;
}
private boolean isLastEnd() {
this.reset();
char curr = (char) super.read();
return curr == ';';
}
}
}