// Copyright (c) 2003 Dustin Sallings <dustin@spy.net>
package net.spy.util;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import net.spy.SpyObject;
/**
* Decode netstrings.
*
* See <a href="http://cr.yp.to/proto/netstrings.txt">netstring spec</a>.
*/
public class NetStringDecoder extends SpyObject {
// Maximum length of the length
private static final int MAX_LEN_LEN=6;
// Maximum length of the string
private static final int MAX_LEN=65535;
private final String encoding;
/**
* Get an instance of NetStringDecoder.
*/
public NetStringDecoder(String enc) {
super();
encoding=enc;
}
/**
* Pull a netstring from the given InputStream and decode it.
*
* @param is a stream containing a netstring
* @return the String representing the netstring at the beginning of
* this stream
* @throws IOException if there is a problem decoding the netstring
*/
public String decodeString(InputStream is) throws IOException {
StringBuilder sizeBuf=new StringBuilder(10);
boolean haveSize=false;
while(!haveSize) {
int c=is.read();
if(c==-1) {
throw new EOFException("End of stream reading size");
}
// Check for a size character
if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4'
|| c == '5' || c == '6' || c == '7' || c == '8' || c == '9') {
sizeBuf.append( (char)c);
if(sizeBuf.length() > MAX_LEN_LEN) {
throw new IOException(
"Length of netstring length too long: " + sizeBuf);
}
} else if(c == ':') {
haveSize = true;
} else {
throw new IOException("Illegal character in netstring size: "
+ (char)c);
}
} // Getting the size
// Get the size
int size=Integer.parseInt(sizeBuf.toString());
if(size > MAX_LEN) {
throw new IOException("Netstring too long: " + size);
}
// Read enough data
byte[] tmp=new byte[size];
int bytesread=0;
while(bytesread < size) {
int r=is.read(tmp, bytesread, (size-bytesread));
if(r == -1) {
throw new EOFException("EOF waiting for netstring");
}
bytesread+=r;
}
int c=is.read();
if(c != ',') {
throw new IOException("Expected comma");
}
// Stringify the data
String rv=new String(tmp, encoding);
return(rv);
}
}