Permalink
Browse files

Work on parsing, implemented prototypes

  • Loading branch information...
djspiewak committed Apr 3, 2008
1 parent 5fe0640 commit b1b5d0430ac4c01392f57f324b42954cef8d0e67
View
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -5,67 +5,87 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import com.googlecode.jbencode.factories.DictionaryValueFactory;
import com.googlecode.jbencode.factories.IntegerValueFactory;
import com.googlecode.jbencode.factories.ListValueFactory;
import com.googlecode.jbencode.factories.StringValueFactory;
import com.googlecode.jbencode.factories.ValueFactory;
import com.googlecode.jbencode.composite.DictionaryValue;
import com.googlecode.jbencode.composite.ListValue;
import com.googlecode.jbencode.primitive.IntegerValue;
import com.googlecode.jbencode.primitive.StringValue;
/**
* @author Daniel Spiewak
*/
public final class Parser {
private final Map<Byte, ValueFactory<?>> factories;
private final ValueFactory<StringValue> stringFactory = new StringValueFactory();
private final Map<Byte, Class<? extends Value<?>>> valueTypes;
public Parser() {
factories = new HashMap<Byte, ValueFactory<?>>();
valueTypes = new HashMap<Byte, Class<? extends Value<?>>>();
addFactory(new IntegerValueFactory());
addFactory(new ListValueFactory());
addFactory(new DictionaryValueFactory());
addType(IntegerValue.class);
addType(ListValue.class);
addType(DictionaryValue.class);
}
public void addFactory(ValueFactory<?> factory) {
factories.put(factory.getPrefix(), factory);
private final void addType(Class<? extends Value<?>> type) {
valueTypes.put(type.getAnnotation(Prefix.class).value(), type);
}
public Value<?> parse(InputStream is) throws IOException {
public Class<? extends Value<?>> getValueType(byte b) {
return valueTypes.get(b);
}
public final Value<?> parse(InputStream is) throws IOException {
int i = is.read();
if (i < 255) {
if (i >= 0) {
byte b = (byte) i;
ValueFactory<?> factory = factories.get(b);
Class<? extends Value<?>> valueType = getValueType(b);
if (factory != null) {
return factory.createValue(is);
if (valueType != null) {
return createValue(valueType, this, is);
} else if (b > '0' && b < '9') {
return readString(is, b - '0');
} else if (b == ' ' || b == '\n' || b == '\r' || b == '\t') {
return parse(is); // loop state
} else {
throw new IOException("Unexpected character in the parse stream: " + Character.forDigit(i, 10));
}
}
throw new IOException("Unexpected character in the parse stream: " + Character.forDigit(i, 10));
throw new IOException("Unexpected end of stream durring parse");
}
private StringValue readString(InputStream is, long length) throws IOException {
private final StringValue readString(InputStream is, long length) throws IOException {
int i = is.read();
if (i < 255) {
if (i >= 0) {
byte b = (byte) i;
if (b == ':') {
return stringFactory.createValue(new SubStream(is, length));
return createValue(StringValue.class, this, new SubStream(is, length));
} else if (b > '0' && b < '9') {
return readString(is, (length * 10) + b - '0');
} else {
throw new IOException("Unexpected character in string value: " + Character.forDigit(i, 10));
}
}
throw new IOException("Unexpected character in the parse stream: " + Character.forDigit(i, 10));
throw new IOException("Unexpected end of stream in string value");
}
public static final <T extends Value<?>> T createValue(Class<T> type, Parser p, InputStream is) {
try {
return type.getConstructor(Parser.class, InputStream.class).newInstance(p, is);
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
}
return null;
}
}
@@ -0,0 +1,18 @@
/*
* Created on Apr 2, 2008
*/
package com.googlecode.jbencode;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Daniel Spiewak
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Prefix {
byte value();
}
@@ -9,7 +9,7 @@
/**
* @author Daniel Spiewak
*/
class SubStream extends InputStream {
public class SubStream extends InputStream {
private final InputStream is;
private final long length;
@@ -3,9 +3,11 @@
*/
package com.googlecode.jbencode;
import java.io.IOException;
/**
* @author Daniel Spiewak
*/
public interface Value<T> {
public T resolve();
public T resolve() throws IOException;
}
@@ -3,10 +3,19 @@
*/
package com.googlecode.jbencode.composite;
import java.io.InputStream;
import com.googlecode.jbencode.Parser;
import com.googlecode.jbencode.Prefix;
/**
* @author Daniel Spiewak
*/
@Prefix('d')
public class DictionaryValue extends CompositeValue<DictionaryValue, EntryPair> {
DictionaryValue(Parser p, InputStream is) {
}
public DictionaryValue resolve() {
return this;
@@ -3,22 +3,126 @@
*/
package com.googlecode.jbencode.composite;
import java.io.IOException;
import java.io.InputStream;
import com.googlecode.jbencode.Parser;
import com.googlecode.jbencode.Prefix;
import com.googlecode.jbencode.SubStream;
import com.googlecode.jbencode.Value;
import com.googlecode.jbencode.primitive.StringValue;
import com.googlecode.jbencode.util.None;
import com.googlecode.jbencode.util.Option;
import com.googlecode.jbencode.util.Some;
/**
* @author Daniel Spiewak
*/
@Prefix('l')
public class ListValue extends CompositeValue<ListValue, Value<?>> {
private final Parser parser;
private final InputStream is;
private boolean resolved = false;
private Option<Byte> readAhead;
ListValue(Parser parser, InputStream is) {
this.parser = parser;
this.is = is;
readAhead = new None<Byte>();
}
public ListValue resolve() {
public ListValue resolve() throws IOException {
if (resolved) {
throw new IOException("Value already resolved");
}
resolved = true;
for (Value<?> value : this) {
value.resolve();
}
return this;
}
public boolean hasNext() {
return false;
if (readAhead instanceof Some && readAhead.value() == 'e') {
return false;
}
try {
byte b = read();
if (b < 0) {
return false;
}
readAhead = new Some<Byte>(b);
if (b == 'e') {
return false;
}
return true;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Value<?> next() {
return null;
try {
return parse();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private final Value<?> parse() throws IOException {
byte b = -1;
if (readAhead instanceof Some) {
b = readAhead.value();
readAhead = new None<Byte>();
} else {
b = read();
}
if (b >= 0) {
Class<? extends Value<?>> valueType = parser.getValueType(b);
if (valueType != null) {
return Parser.createValue(valueType, parser, is);
} else if (b > '0' && b < '9') {
return readString(b - '0');
} else if (b == ' ' || b == '\n' || b == '\r' || b == '\t') {
return parse(); // loop state
} else {
throw new IOException("Unexpected character in the parse stream: " + Character.forDigit(b, 10));
}
}
throw new IOException("Unexpected end of stream in list value");
}
private final StringValue readString(long length) throws IOException {
int i = is.read();
if (i >= 0) {
byte b = (byte) i;
if (b == ':') {
return Parser.createValue(StringValue.class, parser, new SubStream(is, length));
} else if (b > '0' && b < '9') {
return readString((length * 10) + b - '0');
} else {
throw new IOException("Unexpected character in string value: " + Character.forDigit(i, 10));
}
}
throw new IOException("Unexpected end of stream in string value");
}
private final byte read() throws IOException {
return (byte) is.read();
}
}

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
Oops, something went wrong.

0 comments on commit b1b5d04

Please sign in to comment.