panda.net.p2p.Bencode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of panda-nets Show documentation
Show all versions of panda-nets Show documentation
Panda Nets is a client side library of many basic Internet protocols.
package panda.net.p2p;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import panda.codec.Decoder;
import panda.codec.DecoderException;
import panda.codec.Encoder;
import panda.codec.EncoderException;
import panda.io.Streams;
import panda.io.stream.ByteArrayOutputStream;
import panda.lang.Charsets;
import panda.lang.Strings;
public class Bencode implements Encoder, Decoder {
/**
* This creates a new instance of Bencode class
*/
public Bencode() {
}
@Override
public Object decode(Object source) throws DecoderException {
try {
if (source instanceof byte[]) {
return parse((byte[])source);
}
if (source instanceof InputStream) {
return parse((InputStream)source);
}
}
catch (IOException e) {
throw new DecoderException(e);
}
throw new DecoderException("Parameter supplied to Bencode decode is not a byte[] or a InputStream");
}
/**
* This method encode the object to byte[]
*/
@Override
public Object encode(Object source) throws EncoderException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
write(source, baos);
}
catch (IOException e) {
throw new EncoderException(e);
}
return baos.toByteArray();
}
public static void write(Object object, OutputStream os) throws IOException {
if (object instanceof Long) {
os.write('i');
os.write(((Long)object).toString().getBytes());
os.write('e');
}
else if (object instanceof byte[]) {
byte[] bs = ((byte[])object);
os.write(Integer.toString(bs.length).getBytes());
os.write(':');
os.write(bs);
}
else if (object instanceof List) {
List> list = (List>)object;
os.write('l');
for (Object elem : list) {
write(elem, os);
}
os.write('e');
}
else if (object instanceof Map) {
Map, ?> map = (Map, ?>)object;
os.write('d');
for (Object elem : map.entrySet()) {
Map.Entry, ?> entry = (Map.Entry, ?>)elem;
write(entry.getKey().toString().getBytes(), os);
write(entry.getValue(), os);
}
os.write('e');
}
else {
throw new IllegalStateException("Unexcepted object: " + object);
}
}
public static Object parse(byte[] bs) throws IOException {
return parse(new ByteArrayInputStream(bs));
}
public static Object parse(InputStream is) throws IOException {
if (is instanceof PushbackInputStream) {
return _parse((PushbackInputStream)is);
}
return _parse(new PushbackInputStream(is, 1));
}
public static Object _parse(PushbackInputStream is) throws IOException {
int ch = is.read();
switch (ch) {
case 'i':
return parseInteger(is);
case 'l':
return parseList(is);
case 'd':
return parseDictionary(is);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
is.unread(ch);
return parseBytes(is);
default:
throw new IOException("Problem parsing bencoded file: unexpected char " + (char)ch);
}
}
private static Long parseInteger(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
Streams.copyUntil(is, sb, 'e');
// System.out.println("Loaded int: " + buff);
return Long.parseLong(sb.toString());
}
private static List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy