at.spardat.xma.serializer.AsciiDeserializer Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* 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:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
//@(#) $Id: AsciiDeserializer.java 2089 2007-11-28 13:56:13Z s3460 $
package at.spardat.xma.serializer;
import java.io.IOException;
import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.util.ByteArray;
/**
* Reads byte sequences produced by class AsciiSerializer.
*
* @author MS, Feb 11, 2005 7:48:04 PM
*/
public class AsciiDeserializer implements Deserializer {
/**
* The input byte array
*/
private byte[] fData;
/**
* input data
*/
protected ByteArray fArr;
/**
* Constructor
*
* @param data serialized array of data
* @param length first length bytes in data are used.
*/
public AsciiDeserializer (byte[] data, int length) {
this (data, 0, length);
}
/**
* Constructor
*
* @param data serialized array of data
*/
public AsciiDeserializer (byte [] data) {
this (data, 0, data.length);
}
/**
* Constructor
*
* @param data input array
* @param offset offset where data starts
* @param length num bytes from offset
*/
public AsciiDeserializer (byte [] data, int offset, int length) {
fData = data;
fArr = new ByteArray (data, length+offset);
fArr.setPosition(offset);
}
/**
* @see at.spardat.xma.serializer.XmaInput#readString()
*/
public String readString() throws IOException {
return readStringEscaped();
}
/**
* @see at.spardat.xma.serializer.XmaInput#readStringN()
*/
public String readStringN() throws IOException {
boolean isNull = readBoolean();
if (!isNull) return readString();
else return null;
}
/**
* @see at.spardat.xma.serializer.XmaInput#readInt()
*/
public int readInt() throws IOException {
return readNumeric();
}
/**
* @see at.spardat.xma.serializer.XmaInput#readShort()
*/
public short readShort() throws IOException {
return (short)readNumeric();
}
/**
* @see at.spardat.xma.serializer.XmaInput#readLong()
*/
public long readLong() throws IOException {
return (long) readNumericLong();
}
/**
* @see at.spardat.xma.serializer.XmaInput#readBoolean()
*/
public boolean readBoolean() throws IOException {
return readStringEscaped().equals("1");
}
/**
* @see at.spardat.xma.serializer.XmaInput#readByte()
*/
public byte readByte() throws IOException {
return (byte) readNumeric();
}
/**
* @see at.spardat.xma.serializer.XmaInput#readSerializedBytes()
*/
public byte[] readSerializedBytes() throws IOException {
if (!fArr.hasRemaining()) throw new SysException ("{ expected");
if (fArr.get() != '{') throw new SysException ("{ expected");
int startPosition = fArr.getPosition();
int nestingLevel = 1;
while (fArr.hasRemaining()) {
int ch = fArr.get();
int chBefore = fArr.getRel(-2);
if (ch == '{' && chBefore != '\\') nestingLevel++;
if (ch == '}' && chBefore != '\\') {
nestingLevel--;
if (nestingLevel == 0) break;
}
}
if (nestingLevel != 0) throw new SysException ("missing }");
int stopPosition = fArr.getPosition()-1; // index of }
byte[] result = new byte[stopPosition-startPosition];
System.arraycopy(fArr.getBuffer(), startPosition, result, 0, stopPosition-startPosition);
// read trailing ','
if (fArr.get() != ',') throw new SysException ("comma expected");
return result;
}
/**
* @see at.spardat.xma.serializer.XmaInput#readObject()
*/
public Object readObject() throws ClassNotFoundException, IOException {
String type = readString();
if ("S".equals(type)) {
return readString();
} else if ("B".equals(type)) {
return new Boolean (readBoolean());
} else if ("H".equals(type)) {
return new Short (readShort());
} else if ("I".equals(type)) {
return new Integer (readInt());
} else if ("J".equals(type)) {
byte [] bytes = readSerializedBytes();
return Util.deserialize(Util.hexDecode(bytes));
} else {
// an XmaSerializable
Object obj = null;
try {
obj = Class.forName(type).newInstance();
} catch (Exception x) {
throw new SysException (x, "cannot create instance of " + type);
}
((XmaSerializable)obj).deserialize(this);
return obj;
}
}
private int readNumeric () {
return Integer.parseInt(readStringEscaped());
}
private long readNumericLong () {
return Long.parseLong (readStringEscaped());
}
/**
* Reads a string written by AsciiSerializer.writeStringEscaped.
* The string stops at either ',' or '=' (characters are not included in string).
* Those termination characters are consumed in fArr (i.e., get has been called
* on them).
*/
protected String readStringEscaped () {
StringBuffer result = new StringBuffer();
while (fArr.hasRemaining()) {
int act = fArr.get();
// escape
if (act == '\\') {
if (!fArr.hasRemaining()) throw new SysException ("premature end");
int act2 = fArr.getRel(0);
if (act2 >= '0' && act2 <= '9' || act2 >= 'a' && act2 <= 'f') {
// hex character follows; we expect \xxxx unicode character
if (fArr.remaining() < 4) throw new SysException ("premature end");
String hex = null;
try {
hex = new String (fData, fArr.getPosition(), 4, "US-ASCII");
} catch (Exception x) {
throw new SysException (x);
}
fArr.setPosition(fArr.getPosition()+4);
int hexAsInt = Integer.parseInt (hex, 16);
result.append ((char)hexAsInt);
} else {
// character after escape is taken literally
fArr.get();
result.append((char)act2);
}
} else {
if (act == ',') {
if (fArr.hasRemaining() && fArr.getRel(0) == '\n') fArr.get();
break;
} else if (act == '=') {
break;
}
else if (act == '\n') continue;
else {
// plain character
result.append ((char)act);
}
}
}
return result.toString();
}
}