Browse Source

Reformat rencode-java

pull/594/head
Taco 3 years ago
parent
commit
2c538e348a
  1. 9
      app/src/main/java/se/dimovski/rencode/Rencode.java
  2. 247
      app/src/main/java/se/dimovski/rencode/RencodeInputStream.java
  3. 207
      app/src/main/java/se/dimovski/rencode/RencodeOutputStream.java
  4. 44
      app/src/main/java/se/dimovski/rencode/TypeCode.java
  5. 49
      app/src/main/java/se/dimovski/rencode/Utils.java

9
app/src/main/java/se/dimovski/rencode/Rencode.java

@ -5,11 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
public class Rencode public class Rencode {
{
public static Object decode(byte[] data) throws IOException public static Object decode(byte[] data) throws IOException {
{
final InputStream is = new ByteArrayInputStream(data); final InputStream is = new ByteArrayInputStream(data);
final RencodeInputStream inputStream = new RencodeInputStream(is); final RencodeInputStream inputStream = new RencodeInputStream(is);
@ -19,8 +17,7 @@ public class Rencode
return decoded; return decoded;
} }
public static byte[] encode(Object obj) throws IOException public static byte[] encode(Object obj) throws IOException {
{
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final RencodeOutputStream output = new RencodeOutputStream(baos); final RencodeOutputStream output = new RencodeOutputStream(baos);
output.writeObject(obj); output.writeObject(obj);

247
app/src/main/java/se/dimovski/rencode/RencodeInputStream.java

@ -14,12 +14,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
public class RencodeInputStream extends FilterInputStream implements DataInput public class RencodeInputStream extends FilterInputStream implements DataInput {
{
/** /**
* The charset that is being used for {@link String}s. * The charset that is being used for {@link String}s.
*/ */
private final String charset; private final String charset;
/** /**
* Whether or not all byte-Arrays should be decoded as {@link String}s. * Whether or not all byte-Arrays should be decoded as {@link String}s.
@ -29,36 +28,31 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
/** /**
* Creates a {@link RencodeInputStream} with the default encoding. * Creates a {@link RencodeInputStream} with the default encoding.
*/ */
public RencodeInputStream(InputStream in) public RencodeInputStream(InputStream in) {
{
this(in, Utils.UTF_8, false); this(in, Utils.UTF_8, false);
} }
/** /**
* Creates a {@link RencodeInputStream} with the given encoding. * Creates a {@link RencodeInputStream} with the given encoding.
*/ */
public RencodeInputStream(InputStream in, String charset) public RencodeInputStream(InputStream in, String charset) {
{
this(in, charset, false); this(in, charset, false);
} }
/** /**
* Creates a {@link RencodeInputStream} with the default encoding. * Creates a {@link RencodeInputStream} with the default encoding.
*/ */
public RencodeInputStream(InputStream in, boolean decodeAsString) public RencodeInputStream(InputStream in, boolean decodeAsString) {
{
this(in, Utils.UTF_8, decodeAsString); this(in, Utils.UTF_8, decodeAsString);
} }
/** /**
* Creates a {@link RencodeInputStream} with the given encoding. * Creates a {@link RencodeInputStream} with the given encoding.
*/ */
public RencodeInputStream(InputStream in, String charset, boolean decodeAsString) public RencodeInputStream(InputStream in, String charset, boolean decodeAsString) {
{
super(in); super(in);
if (charset == null) if (charset == null) {
{
throw new IllegalArgumentException("charset is null"); throw new IllegalArgumentException("charset is null");
} }
@ -70,24 +64,21 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
* Returns the charset that is used to decode {@link String}s. The default * Returns the charset that is used to decode {@link String}s. The default
* value is UTF-8. * value is UTF-8.
*/ */
public String getCharset() public String getCharset() {
{
return charset; return charset;
} }
/** /**
* Returns true if all byte-Arrays are being turned into {@link String}s. * Returns true if all byte-Arrays are being turned into {@link String}s.
*/ */
public boolean isDecodeAsString() public boolean isDecodeAsString() {
{
return decodeAsString; return decodeAsString;
} }
/** /**
* Reads and returns an {@link Object}. * Reads and returns an {@link Object}.
*/ */
public Object readObject() throws IOException public Object readObject() throws IOException {
{
int token = readToken(); int token = readToken();
return readObject(token); return readObject(token);
@ -96,38 +87,22 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
/** /**
* Reads and returns an {@link Object}. * Reads and returns an {@link Object}.
*/ */
protected Object readObject(int token) throws IOException protected Object readObject(int token) throws IOException {
{ if (token == TypeCode.DICTIONARY) {
if (token == TypeCode.DICTIONARY)
{
return readMap0(Object.class); return readMap0(Object.class);
} } else if (Utils.isFixedDictionary(token)) {
else if (Utils.isFixedDictionary(token))
{
return readMap0(Object.class, token); return readMap0(Object.class, token);
} } else if (token == TypeCode.LIST) {
else if (token == TypeCode.LIST)
{
return readList0(Object.class); return readList0(Object.class);
} } else if (Utils.isFixedList(token)) {
else if (Utils.isFixedList(token))
{
return readList0(Object.class, token); return readList0(Object.class, token);
} } else if (Utils.isNumber(token)) {
else if (Utils.isNumber(token))
{
return readNumber0(token); return readNumber0(token);
} } else if (token == TypeCode.FALSE || token == TypeCode.TRUE) {
else if (token == TypeCode.FALSE || token == TypeCode.TRUE)
{
return readBoolean0(token); return readBoolean0(token);
} } else if (token == TypeCode.NULL) {
else if (token == TypeCode.NULL)
{
return null; return null;
} } else if (Utils.isDigit(token) || Utils.isFixedString(token)) {
else if (Utils.isDigit(token) || Utils.isFixedString(token))
{
return readString(token, charset); return readString(token, charset);
} }
@ -137,45 +112,38 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
/** /**
* Reads and returns a {@link Map}. * Reads and returns a {@link Map}.
*/ */
public Map<String, ?> readMap() throws IOException public Map<String, ?> readMap() throws IOException {
{
return readMap(Object.class); return readMap(Object.class);
} }
/** /**
* Reads and returns a {@link Map}. * Reads and returns a {@link Map}.
*/ */
public <T> Map<String, T> readMap(Class<T> clazz) throws IOException public <T> Map<String, T> readMap(Class<T> clazz) throws IOException {
{
int token = readToken(); int token = readToken();
if (token != TypeCode.DICTIONARY) if (token != TypeCode.DICTIONARY) {
{
throw new IOException(); throw new IOException();
} }
return readMap0(clazz); return readMap0(clazz);
} }
private <T> Map<String, T> readMap0(Class<T> clazz) throws IOException private <T> Map<String, T> readMap0(Class<T> clazz) throws IOException {
{
Map<String, T> map = new TreeMap<String, T>(); Map<String, T> map = new TreeMap<String, T>();
int token = -1; int token = -1;
while ((token = readToken()) != TypeCode.END) while ((token = readToken()) != TypeCode.END) {
{
readMapItem(clazz, token, map); readMapItem(clazz, token, map);
} }
return map; return map;
} }
private <T> Map<String, T> readMap0(Class<T> clazz, int token) throws IOException private <T> Map<String, T> readMap0(Class<T> clazz, int token) throws IOException {
{
Map<String, T> map = new TreeMap<String, T>(); Map<String, T> map = new TreeMap<String, T>();
int count = token - TypeCode.EMBEDDED.DICT_START; int count = token - TypeCode.EMBEDDED.DICT_START;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++) {
{
readMapItem(clazz, readToken(), map); readMapItem(clazz, readToken(), map);
} }
@ -183,19 +151,16 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
} }
private <T> void readMapItem(Class<T> clazz, int token, Map<String, T> map) throws UnsupportedEncodingException, private <T> void readMapItem(Class<T> clazz, int token, Map<String, T> map) throws UnsupportedEncodingException,
IOException IOException {
{
String key = readString(token, charset); String key = readString(token, charset);
T value = clazz.cast(readObject()); T value = clazz.cast(readObject());
map.put(key, value); map.put(key, value);
} }
public int readToken() throws IOException public int readToken() throws IOException {
{
int token = super.read(); int token = super.read();
if (token == -1) if (token == -1) {
{
throw new EOFException(); throw new EOFException();
} }
return token; return token;
@ -204,101 +169,81 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
/** /**
* Reads and returns a {@link List}. * Reads and returns a {@link List}.
*/ */
public List<?> readList() throws IOException public List<?> readList() throws IOException {
{
return readList(Object.class); return readList(Object.class);
} }
/** /**
* Reads and returns a {@link List}. * Reads and returns a {@link List}.
*/ */
public <T> List<T> readList(Class<T> clazz) throws IOException public <T> List<T> readList(Class<T> clazz) throws IOException {
{
int token = readToken(); int token = readToken();
if (token != TypeCode.LIST) if (token != TypeCode.LIST) {
{
throw new IOException(); throw new IOException();
} }
return readList0(clazz); return readList0(clazz);
} }
private <T> List<T> readList0(Class<T> clazz) throws IOException private <T> List<T> readList0(Class<T> clazz) throws IOException {
{
List<T> list = new ArrayList<T>(); List<T> list = new ArrayList<T>();
int token = -1; int token = -1;
while ((token = readToken()) != TypeCode.END) while ((token = readToken()) != TypeCode.END) {
{
list.add(clazz.cast(readObject(token))); list.add(clazz.cast(readObject(token)));
} }
return list; return list;
} }
private <T> List<T> readList0(Class<T> clazz, int token) throws IOException private <T> List<T> readList0(Class<T> clazz, int token) throws IOException {
{
List<T> list = new ArrayList<T>(); List<T> list = new ArrayList<T>();
int length = token - TypeCode.EMBEDDED.LIST_START; int length = token - TypeCode.EMBEDDED.LIST_START;
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++) {
{
list.add(clazz.cast(readObject())); list.add(clazz.cast(readObject()));
} }
return list; return list;
} }
public boolean readBoolean() throws IOException public boolean readBoolean() throws IOException {
{
return readBoolean0(readToken()); return readBoolean0(readToken());
} }
public boolean readBoolean0(int token) throws IOException public boolean readBoolean0(int token) throws IOException {
{ if (token == TypeCode.FALSE) {
if (token == TypeCode.FALSE)
{
return false; return false;
} } else if (token == TypeCode.TRUE) {
else if (token == TypeCode.TRUE)
{
return true; return true;
} }
throw new IOException(); throw new IOException();
} }
public byte readByte() throws IOException public byte readByte() throws IOException {
{
return (byte) readToken(); return (byte) readToken();
} }
public char readChar() throws IOException public char readChar() throws IOException {
{
return (char) readToken(); return (char) readToken();
} }
public double readDouble() throws IOException public double readDouble() throws IOException {
{
return readNumber().doubleValue(); return readNumber().doubleValue();
} }
public float readFloat() throws IOException public float readFloat() throws IOException {
{
return readNumber().floatValue(); return readNumber().floatValue();
} }
public void readFully(byte[] dst) throws IOException public void readFully(byte[] dst) throws IOException {
{
readFully(dst, 0, dst.length); readFully(dst, 0, dst.length);
} }
public void readFully(byte[] dst, int off, int len) throws IOException public void readFully(byte[] dst, int off, int len) throws IOException {
{
int total = 0; int total = 0;
while (total < len) while (total < len) {
{
int r = read(dst, total, len - total); int r = read(dst, total, len - total);
if (r == -1) if (r == -1) {
{
throw new EOFException(); throw new EOFException();
} }
@ -306,60 +251,49 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
} }
} }
public int readInt() throws IOException public int readInt() throws IOException {
{
return readNumber().intValue(); return readNumber().intValue();
} }
public String readLine() throws IOException public String readLine() throws IOException {
{
return readString(); return readString();
} }
public long readLong() throws IOException public long readLong() throws IOException {
{
return readNumber().longValue(); return readNumber().longValue();
} }
public short readShort() throws IOException public short readShort() throws IOException {
{
return readNumber().shortValue(); return readNumber().shortValue();
} }
public String readUTF() throws IOException public String readUTF() throws IOException {
{
return readString(Utils.UTF_8); return readString(Utils.UTF_8);
} }
public int readUnsignedByte() throws IOException public int readUnsignedByte() throws IOException {
{
return readByte() & 0xFF; return readByte() & 0xFF;
} }
public int readUnsignedShort() throws IOException public int readUnsignedShort() throws IOException {
{
return readShort() & 0xFFFF; return readShort() & 0xFFFF;
} }
/** /**
* Reads and returns a {@link Number}. * Reads and returns a {@link Number}.
*/ */
public Number readNumber() throws IOException public Number readNumber() throws IOException {
{
int token = readToken(); int token = readToken();
if (!Utils.isNumber(token)) if (!Utils.isNumber(token)) {
{
throw new IOException(); throw new IOException();
} }
return readNumber0(token); return readNumber0(token);
} }
private Number readNumber0(int token) throws IOException private Number readNumber0(int token) throws IOException {
{ switch (token) {
switch (token)
{
case TypeCode.BYTE: case TypeCode.BYTE:
return (int) readToBuffer(1).get(); return (int) readToBuffer(1).get();
case TypeCode.SHORT: case TypeCode.SHORT:
@ -376,67 +310,52 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
case TypeCode.NUMBER: case TypeCode.NUMBER:
return readNumber0(); return readNumber0();
} }
if (Utils.isNegativeFixedNumber(token)) if (Utils.isNegativeFixedNumber(token)) {
{
return TypeCode.EMBEDDED.INT_NEG_START - 1 - token; return TypeCode.EMBEDDED.INT_NEG_START - 1 - token;
} } else if (Utils.isPositiveFixedNumber(token)) {
else if (Utils.isPositiveFixedNumber(token))
{
return TypeCode.EMBEDDED.INT_POS_START + token; return TypeCode.EMBEDDED.INT_POS_START + token;
} }
throw new IOException("Unknown number. TypeCode: " + token); throw new IOException("Unknown number. TypeCode: " + token);
} }
private ByteBuffer readToBuffer(int count) throws IOException private ByteBuffer readToBuffer(int count) throws IOException {
{
return ByteBuffer.wrap(readBytesFixed(count)); return ByteBuffer.wrap(readBytesFixed(count));
} }
private Number readNumber0() throws IOException private Number readNumber0() throws IOException {
{
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
boolean decimal = false; boolean decimal = false;
int token = -1; int token = -1;
while ((token = readToken()) != TypeCode.END) while ((token = readToken()) != TypeCode.END) {
{ if (token == '.') {
if (token == '.')
{
decimal = true; decimal = true;
} }
buffer.append((char) token); buffer.append((char) token);
} }
try try {
{ if (decimal) {
if (decimal)
{
return new BigDecimal(buffer.toString()); return new BigDecimal(buffer.toString());
} } else {
else
{
return new BigInteger(buffer.toString()); return new BigInteger(buffer.toString());
} }
} } catch (NumberFormatException err) {
catch (NumberFormatException err)
{
throw new IOException("NumberFormatException", err); throw new IOException("NumberFormatException", err);
} }
} }
public int skipBytes(int n) throws IOException public int skipBytes(int n) throws IOException {
{
return (int) skip(n); return (int) skip(n);
} }
/** /**
* Reads and returns a byte-Array. * Reads and returns a byte-Array.
*/ */
public byte[] readBytes() throws IOException public byte[] readBytes() throws IOException {
{
int token = readToken(); int token = readToken();
return readBytes(token); return readBytes(token);
@ -445,46 +364,38 @@ public class RencodeInputStream extends FilterInputStream implements DataInput
/** /**
* Reads and returns a {@link String}. * Reads and returns a {@link String}.
*/ */
public String readString() throws IOException public String readString() throws IOException {
{
return readString(charset); return readString(charset);
} }
private String readString(String encoding) throws IOException private String readString(String encoding) throws IOException {
{
return readString(readToken(), encoding); return readString(readToken(), encoding);
} }
private String readString(int token, String charset) throws IOException private String readString(int token, String charset) throws IOException {
{ if (Utils.isFixedString(token)) {
if (Utils.isFixedString(token))
{
int length = token - TypeCode.EMBEDDED.STR_START; int length = token - TypeCode.EMBEDDED.STR_START;
return new String(readBytesFixed(length), charset); return new String(readBytesFixed(length), charset);
} }
return new String(readBytes(token), charset); return new String(readBytes(token), charset);
} }
private byte[] readBytes(int token) throws IOException private byte[] readBytes(int token) throws IOException {
{
int length = readLength(token); int length = readLength(token);
return readBytesFixed(length); return readBytesFixed(length);
} }
private byte[] readBytesFixed(int count) throws IOException private byte[] readBytesFixed(int count) throws IOException {
{
byte[] data = new byte[count]; byte[] data = new byte[count];
readFully(data); readFully(data);
return data; return data;
} }
private int readLength(int token) throws IOException private int readLength(int token) throws IOException {
{
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
buffer.append((char) token); buffer.append((char) token);
while ((token = readToken()) != TypeCode.LENGTH_DELIM) while ((token = readToken()) != TypeCode.LENGTH_DELIM) {
{
buffer.append((char) token); buffer.append((char) token);
} }

207
app/src/main/java/se/dimovski/rencode/RencodeOutputStream.java

@ -11,8 +11,7 @@ import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
public class RencodeOutputStream extends FilterOutputStream implements DataOutput public class RencodeOutputStream extends FilterOutputStream implements DataOutput {
{
/** /**
* The {@link String} charset. * The {@link String} charset.
@ -22,20 +21,17 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Creates a {@link RencodeOutputStream} with the default charset. * Creates a {@link RencodeOutputStream} with the default charset.
*/ */
public RencodeOutputStream(OutputStream out) public RencodeOutputStream(OutputStream out) {
{
this(out, Utils.UTF_8); this(out, Utils.UTF_8);
} }
/** /**
* Creates a {@link RencodeOutputStream} with the given encoding. * Creates a {@link RencodeOutputStream} with the given encoding.
*/ */
public RencodeOutputStream(OutputStream out, String charset) public RencodeOutputStream(OutputStream out, String charset) {
{
super(out); super(out);
if (charset == null) if (charset == null) {
{
throw new NullPointerException("charset"); throw new NullPointerException("charset");
} }
@ -46,66 +42,43 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
* Returns the charset that is used to encode {@link String}s. The default * Returns the charset that is used to encode {@link String}s. The default
* value is UTF-8. * value is UTF-8.
*/ */
public String getCharset() public String getCharset() {
{
return charset; return charset;
} }
/** /**
* Writes an {@link Object}. * Writes an {@link Object}.
*/ */
public void writeObject(Object value) throws IOException public void writeObject(Object value) throws IOException {
{ if (value == null) {
if (value == null)
{
writeNull(); writeNull();
} } else if (value instanceof byte[]) {
else if (value instanceof byte[])
{
writeBytes((byte[]) value); writeBytes((byte[]) value);
} } else if (value instanceof Boolean) {
else if (value instanceof Boolean)
{
writeBoolean((Boolean) value); writeBoolean((Boolean) value);
} } else if (value instanceof Character) {
else if (value instanceof Character)
{
writeChar((Character) value); writeChar((Character) value);
} } else if (value instanceof Number) {
else if (value instanceof Number)
{
writeNumber((Number) value); writeNumber((Number) value);
} } else if (value instanceof String) {
else if (value instanceof String)
{
writeString((String) value); writeString((String) value);
} } else if (value instanceof Collection<?>) {
else if (value instanceof Collection<?>)
{
writeCollection((Collection<?>) value); writeCollection((Collection<?>) value);
} } else if (value instanceof Map<?, ?>) {
else if (value instanceof Map<?, ?>)
{
writeMap((Map<?, ?>) value); writeMap((Map<?, ?>) value);
} } else if (value instanceof Enum<?>) {
else if (value instanceof Enum<?>)
{
writeEnum((Enum<?>) value); writeEnum((Enum<?>) value);
} } else if (value.getClass().isArray()) {
else if (value.getClass().isArray())
{
writeArray(value); writeArray(value);
} } else {
else
{
writeCustom(value); writeCustom(value);
} }
} }
@ -113,8 +86,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a null value * Writes a null value
*/ */
public void writeNull() throws IOException public void writeNull() throws IOException {
{
write(TypeCode.NULL); write(TypeCode.NULL);
} }
@ -122,48 +94,42 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
* Overwrite this method to write custom objects. The default implementation * Overwrite this method to write custom objects. The default implementation
* throws an {@link IOException}. * throws an {@link IOException}.
*/ */
protected void writeCustom(Object value) throws IOException protected void writeCustom(Object value) throws IOException {
{
throw new IOException("Cannot encode " + value); throw new IOException("Cannot encode " + value);
} }
/** /**
* Writes the given byte-Array * Writes the given byte-Array
*/ */
public void writeBytes(byte[] value) throws IOException public void writeBytes(byte[] value) throws IOException {
{
writeBytes(value, 0, value.length); writeBytes(value, 0, value.length);
} }
/** /**
* Writes the given byte-Array * Writes the given byte-Array
*/ */
public void writeBytes(byte[] value, int offset, int length) throws IOException public void writeBytes(byte[] value, int offset, int length) throws IOException {
{
write(value, offset, length); write(value, offset, length);
} }
/** /**
* Writes a boolean * Writes a boolean
*/ */
public void writeBoolean(boolean value) throws IOException public void writeBoolean(boolean value) throws IOException {
{
write(value ? TypeCode.TRUE : TypeCode.FALSE); write(value ? TypeCode.TRUE : TypeCode.FALSE);
} }
/** /**
* Writes a char * Writes a char
*/ */
public void writeChar(int value) throws IOException public void writeChar(int value) throws IOException {
{
writeByte(value); writeByte(value);
} }
/** /**
* Writes a byte * Writes a byte
*/ */
public void writeByte(int value) throws IOException public void writeByte(int value) throws IOException {
{
write(TypeCode.BYTE); write(TypeCode.BYTE);
write(value); write(value);
} }
@ -171,8 +137,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a short * Writes a short
*/ */
public void writeShort(int value) throws IOException public void writeShort(int value) throws IOException {
{
write(TypeCode.SHORT); write(TypeCode.SHORT);
ByteBuffer buffer = ByteBuffer.allocate(Utils.SHORT_BYTES).putShort((short) value); ByteBuffer buffer = ByteBuffer.allocate(Utils.SHORT_BYTES).putShort((short) value);
write(buffer.array()); write(buffer.array());
@ -181,8 +146,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes an int * Writes an int
*/ */
public void writeInt(int value) throws IOException public void writeInt(int value) throws IOException {
{
write(TypeCode.INT); write(TypeCode.INT);
ByteBuffer buffer = ByteBuffer.allocate(Utils.INTEGER_BYTES).putInt(value); ByteBuffer buffer = ByteBuffer.allocate(Utils.INTEGER_BYTES).putInt(value);
write(buffer.array()); write(buffer.array());
@ -191,8 +155,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a long * Writes a long
*/ */
public void writeLong(long value) throws IOException public void writeLong(long value) throws IOException {
{
write(TypeCode.LONG); write(TypeCode.LONG);
ByteBuffer buffer = ByteBuffer.allocate(Utils.LONG_BYTES).putLong(value); ByteBuffer buffer = ByteBuffer.allocate(Utils.LONG_BYTES).putLong(value);
write(buffer.array()); write(buffer.array());
@ -201,8 +164,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a float * Writes a float
*/ */
public void writeFloat(float value) throws IOException public void writeFloat(float value) throws IOException {
{
write(TypeCode.FLOAT); write(TypeCode.FLOAT);
ByteBuffer buffer = ByteBuffer.allocate(Utils.FLOAT_BYTES).putFloat(value); ByteBuffer buffer = ByteBuffer.allocate(Utils.FLOAT_BYTES).putFloat(value);
write(buffer.array()); write(buffer.array());
@ -211,8 +173,7 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a double * Writes a double
*/ */
public void writeDouble(double value) throws IOException public void writeDouble(double value) throws IOException {
{
write(TypeCode.DOUBLE); write(TypeCode.DOUBLE);
ByteBuffer buffer = ByteBuffer.allocate(Utils.DOUBLE_BYTES).putDouble(value); ByteBuffer buffer = ByteBuffer.allocate(Utils.DOUBLE_BYTES).putDouble(value);
write(buffer.array()); write(buffer.array());
@ -221,42 +182,25 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a {@link Number} * Writes a {@link Number}
*/ */
public void writeNumber(Number num) throws IOException public void writeNumber(Number num) throws IOException {
{ if (num instanceof Float) {
if (num instanceof Float)
{
writeFloat(num.floatValue()); writeFloat(num.floatValue());
} } else if (num instanceof Double) {
else if (num instanceof Double)
{
writeDouble(num.doubleValue()); writeDouble(num.doubleValue());
} }
if (0 <= num.intValue() && num.intValue() < TypeCode.EMBEDDED.INT_POS_COUNT) if (0 <= num.intValue() && num.intValue() < TypeCode.EMBEDDED.INT_POS_COUNT) {
{
write(TypeCode.EMBEDDED.INT_POS_START + num.intValue()); write(TypeCode.EMBEDDED.INT_POS_START + num.intValue());
} } else if (-TypeCode.EMBEDDED.INT_NEG_COUNT <= num.intValue() && num.intValue() < 0) {
else if (-TypeCode.EMBEDDED.INT_NEG_COUNT <= num.intValue() && num.intValue() < 0)
{
write(TypeCode.EMBEDDED.INT_NEG_START - 1 - num.intValue()); write(TypeCode.EMBEDDED.INT_NEG_START - 1 - num.intValue());
} } else if (Byte.MIN_VALUE <= num.intValue() && num.intValue() < Byte.MAX_VALUE) {
else if (Byte.MIN_VALUE <= num.intValue() && num.intValue() < Byte.MAX_VALUE)
{
writeByte(num.byteValue()); writeByte(num.byteValue());
} } else if (Short.MIN_VALUE <= num.intValue() && num.intValue() < Short.MAX_VALUE) {
else if (Short.MIN_VALUE <= num.intValue() && num.intValue() < Short.MAX_VALUE)
{
writeShort(num.shortValue()); writeShort(num.shortValue());
} } else if (Integer.MIN_VALUE <= num.longValue() && num.longValue() < Integer.MAX_VALUE) {
else if (Integer.MIN_VALUE <= num.longValue() && num.longValue() < Integer.MAX_VALUE)
{
writeInt(num.intValue()); writeInt(num.intValue());
} } else if (Long.MIN_VALUE <= num.longValue() && num.longValue() < Long.MAX_VALUE) {
else if (Long.MIN_VALUE <= num.longValue() && num.longValue() < Long.MAX_VALUE)
{
writeLong(num.longValue()); writeLong(num.longValue());
} } else {
else
{
String number = num.toString(); String number = num.toString();
write(TypeCode.NUMBER); write(TypeCode.NUMBER);
write(number.getBytes(charset)); write(number.getBytes(charset));
@ -267,15 +211,11 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a {@link String} * Writes a {@link String}
*/ */
public void writeString(String value) throws IOException public void writeString(String value) throws IOException {
{
int len = value.length(); int len = value.length();
if (len < TypeCode.EMBEDDED.STR_COUNT) if (len < TypeCode.EMBEDDED.STR_COUNT) {
{
write(TypeCode.EMBEDDED.STR_START + len); write(TypeCode.EMBEDDED.STR_START + len);
} } else {
else
{
String lenString = Integer.toString(len); String lenString = Integer.toString(len);
writeBytes(lenString.getBytes(charset)); writeBytes(lenString.getBytes(charset));
write(TypeCode.LENGTH_DELIM); write(TypeCode.LENGTH_DELIM);
@ -287,25 +227,19 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a {@link Collection}. * Writes a {@link Collection}.
*/ */
public void writeCollection(Collection<?> value) throws IOException public void writeCollection(Collection<?> value) throws IOException {
{
boolean useEndToken = value.size() >= TypeCode.EMBEDDED.LIST_COUNT; boolean useEndToken = value.size() >= TypeCode.EMBEDDED.LIST_COUNT;
if (useEndToken) if (useEndToken) {
{
write(TypeCode.LIST); write(TypeCode.LIST);
} } else {
else
{
write(TypeCode.EMBEDDED.LIST_START + value.size()); write(TypeCode.EMBEDDED.LIST_START + value.size());
} }
for (Object element : value) for (Object element : value) {
{
writeObject(element); writeObject(element);
} }
if (useEndToken) if (useEndToken) {
{
write(TypeCode.END); write(TypeCode.END);
} }
} }
@ -313,32 +247,25 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes a {@link Map}. * Writes a {@link Map}.
*/ */
public void writeMap(Map<?, ?> map) throws IOException public void writeMap(Map<?, ?> map) throws IOException {
{ if (!(map instanceof SortedMap<?, ?>)) {
if (!(map instanceof SortedMap<?, ?>))
{
map = new TreeMap<Object, Object>(map); map = new TreeMap<Object, Object>(map);
} }
boolean untilEnd = map.size() >= TypeCode.EMBEDDED.DICT_COUNT; boolean untilEnd = map.size() >= TypeCode.EMBEDDED.DICT_COUNT;
if (untilEnd) if (untilEnd) {
{
write(TypeCode.DICTIONARY); write(TypeCode.DICTIONARY);
} } else {
else
{
write(TypeCode.EMBEDDED.DICT_START + map.size()); write(TypeCode.EMBEDDED.DICT_START + map.size());
} }
for (Map.Entry<?, ?> entry : map.entrySet()) for (Map.Entry<?, ?> entry : map.entrySet()) {
{
writeObject(entry.getKey()); writeObject(entry.getKey());
writeObject(entry.getValue()); writeObject(entry.getValue());
} }
if (untilEnd) if (untilEnd) {
{
write(TypeCode.END); write(TypeCode.END);
} }
} }
@ -346,34 +273,27 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes an {@link Enum}. * Writes an {@link Enum}.
*/ */
public void writeEnum(Enum<?> value) throws IOException public void writeEnum(Enum<?> value) throws IOException {
{
writeString(value.name()); writeString(value.name());
} }
/** /**
* Writes an array * Writes an array
*/ */
public void writeArray(Object value) throws IOException public void writeArray(Object value) throws IOException {
{
int length = Array.getLength(value); int length = Array.getLength(value);
boolean useEndToken = length >= TypeCode.EMBEDDED.LIST_COUNT; boolean useEndToken = length >= TypeCode.EMBEDDED.LIST_COUNT;
if (useEndToken) if (useEndToken) {
{
write(TypeCode.LIST); write(TypeCode.LIST);
} } else {
else
{
write(TypeCode.EMBEDDED.LIST_START + length); write(TypeCode.EMBEDDED.LIST_START + length);
} }
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++) {
{
writeObject(Array.get(value, i)); writeObject(Array.get(value, i));
} }
if (useEndToken) if (useEndToken) {
{
write(TypeCode.END); write(TypeCode.END);
} }
} }
@ -381,24 +301,21 @@ public class RencodeOutputStream extends FilterOutputStream implements DataOutpu
/** /**
* Writes the given {@link String} * Writes the given {@link String}
*/ */
public void writeBytes(String value) throws IOException public void writeBytes(String value) throws IOException {
{
writeString(value); writeString(value);
} }
/** /**
* Writes the given {@link String} * Writes the given {@link String}
*/ */
public void writeChars(String value) throws IOException public void writeChars(String value) throws IOException {
{
writeString(value); writeString(value);
} }
/** /**
* Writes an UTF encoded {@link String} * Writes an UTF encoded {@link String}
*/ */
public void writeUTF(String value) throws IOException public void writeUTF(String value) throws IOException {
{
writeBytes(value.getBytes(Utils.UTF_8)); writeBytes(value.getBytes(Utils.UTF_8));
} }
} }

44
app/src/main/java/se/dimovski/rencode/TypeCode.java

@ -1,29 +1,27 @@
package se.dimovski.rencode; package se.dimovski.rencode;
public class TypeCode public class TypeCode {
{
// The bencode 'typecodes' such as i, d, etc have been // The bencode 'typecodes' such as i, d, etc have been
// extended and relocated on the base-256 character set. // extended and relocated on the base-256 character set.
public static final char LIST = 59; public static final char LIST = 59;
public static final char DICTIONARY = 60; public static final char DICTIONARY = 60;
public static final char NUMBER = 61; public static final char NUMBER = 61;
public static final char BYTE = 62; public static final char BYTE = 62;
public static final char SHORT = 63; public static final char SHORT = 63;
public static final char INT = 64; public static final char INT = 64;
public static final char LONG = 65; public static final char LONG = 65;
public static final char FLOAT = 66; public static final char FLOAT = 66;
public static final char DOUBLE = 44; public static final char DOUBLE = 44;
public static final char TRUE = 67; public static final char TRUE = 67;
public static final char FALSE = 68; public static final char FALSE = 68;
public static final char NULL = 69; public static final char NULL = 69;
public static final char END = 127; public static final char END = 127;
public static final char LENGTH_DELIM = ':'; public static final char LENGTH_DELIM = ':';
/* /*
* TypeCodes with embedded values/lengths * TypeCodes with embedded values/lengths
*/ */
public static class EMBEDDED public static class EMBEDDED {
{
// Positive integers // Positive integers
public static final int INT_POS_START = 0; public static final int INT_POS_START = 0;
public static final int INT_POS_COUNT = 44; public static final int INT_POS_COUNT = 44;
@ -33,15 +31,15 @@ public class TypeCode
public static final int INT_NEG_COUNT = 32; public static final int INT_NEG_COUNT = 32;
// Dictionaries // Dictionaries
public static final int DICT_START = 102; public static final int DICT_START = 102;
public static final int DICT_COUNT = 25; public static final int DICT_COUNT = 25;
// Strings // Strings
public static final int STR_START = 128; public static final int STR_START = 128;
public static final int STR_COUNT = 64; public static final int STR_COUNT = 64;
// Lists // Lists
public static final int LIST_START = STR_START + STR_COUNT; public static final int LIST_START = STR_START + STR_COUNT;
public static final int LIST_COUNT = 64; public static final int LIST_COUNT = 64;
} }
} }

49
app/src/main/java/se/dimovski/rencode/Utils.java

@ -1,30 +1,26 @@
package se.dimovski.rencode; package se.dimovski.rencode;
public class Utils public class Utils {
{
// Character Encodings // Character Encodings
public final static String UTF_8 = "UTF-8"; public final static String UTF_8 = "UTF-8";
public final static String ISO_8859 = "ISO-8859-1"; public final static String ISO_8859 = "ISO-8859-1";
// Byte-lengths for types // Byte-lengths for types
public static final int SHORT_BYTES = Short.SIZE / Byte.SIZE; public static final int SHORT_BYTES = Short.SIZE / Byte.SIZE;
public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE;
public static final int LONG_BYTES = Long.SIZE / Byte.SIZE; public static final int LONG_BYTES = Long.SIZE / Byte.SIZE;
public static final int FLOAT_BYTES = Float.SIZE / Byte.SIZE; public static final int FLOAT_BYTES = Float.SIZE / Byte.SIZE;
public static final int DOUBLE_BYTES = Double.SIZE / Byte.SIZE; public static final int DOUBLE_BYTES = Double.SIZE / Byte.SIZE;
// Maximum length of integer when written as base 10 string. // Maximum length of integer when written as base 10 string.
public static final int MAX_INT_LENGTH = 64; public static final int MAX_INT_LENGTH = 64;
private static boolean tokenInRange(int token, int start, int count) private static boolean tokenInRange(int token, int start, int count) {
{
return start <= token && token < (start + count); return start <= token && token < (start + count);
} }
public static boolean isNumber(int token) public static boolean isNumber(int token) {
{ switch (token) {
switch (token)
{
case TypeCode.NUMBER: case TypeCode.NUMBER:
case TypeCode.BYTE: case TypeCode.BYTE:
case TypeCode.SHORT: case TypeCode.SHORT:
@ -37,38 +33,31 @@ public class Utils
return isFixedNumber(token); return isFixedNumber(token);
} }
public static boolean isFixedNumber(int token) public static boolean isFixedNumber(int token) {
{
return isPositiveFixedNumber(token) || isNegativeFixedNumber(token); return isPositiveFixedNumber(token) || isNegativeFixedNumber(token);
} }
public static boolean isPositiveFixedNumber(int token) public static boolean isPositiveFixedNumber(int token) {
{
return tokenInRange(token, TypeCode.EMBEDDED.INT_POS_START, TypeCode.EMBEDDED.INT_POS_COUNT); return tokenInRange(token, TypeCode.EMBEDDED.INT_POS_START, TypeCode.EMBEDDED.INT_POS_COUNT);
} }
public static boolean isNegativeFixedNumber(int token) public static boolean isNegativeFixedNumber(int token) {
{
return tokenInRange(token, TypeCode.EMBEDDED.INT_NEG_START, TypeCode.EMBEDDED.INT_NEG_COUNT); return tokenInRange(token, TypeCode.EMBEDDED.INT_NEG_START, TypeCode.EMBEDDED.INT_NEG_COUNT);
} }
public static boolean isFixedList(int token) public static boolean isFixedList(int token) {
{
return tokenInRange(token, TypeCode.EMBEDDED.LIST_START, TypeCode.EMBEDDED.LIST_COUNT); return tokenInRange(token, TypeCode.EMBEDDED.LIST_START, TypeCode.EMBEDDED.LIST_COUNT);
} }
public static boolean isFixedDictionary(int token) public static boolean isFixedDictionary(int token) {
{
return tokenInRange(token, TypeCode.EMBEDDED.DICT_START, TypeCode.EMBEDDED.DICT_COUNT); return tokenInRange(token, TypeCode.EMBEDDED.DICT_START, TypeCode.EMBEDDED.DICT_COUNT);
} }
public static boolean isFixedString(int token) public static boolean isFixedString(int token) {
{
return tokenInRange(token, TypeCode.EMBEDDED.STR_START, TypeCode.EMBEDDED.STR_COUNT); return tokenInRange(token, TypeCode.EMBEDDED.STR_START, TypeCode.EMBEDDED.STR_COUNT);
} }
public static boolean isDigit(int token) public static boolean isDigit(int token) {
{
return '0' <= token && token <= '9'; return '0' <= token && token <= '9';
} }
} }

Loading…
Cancel
Save