implement BList decoding, fix numerous bugs in BList
This commit is contained in:
parent
695d21f851
commit
24e9568f89
4 changed files with 71 additions and 12 deletions
|
|
@ -36,6 +36,12 @@ public class BList extends BValue {
|
|||
|
||||
// builder
|
||||
public BList append(BValue item) {
|
||||
// do not allow any nulls pass into list, because it fucks up everything
|
||||
if (item == null) {
|
||||
// fail earlier than fail horribly
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
BValue first = getFirst();
|
||||
BValue last = getLast();
|
||||
if (first == null) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import java.util.Arrays;
|
|||
import com.mykola2312.retracker.bencode.error.BDecodeError;
|
||||
import com.mykola2312.retracker.bencode.error.BDecodeMalformed;
|
||||
import com.mykola2312.retracker.bencode.error.BDecodeParseError;
|
||||
import com.mykola2312.retracker.bencode.error.BDecodeUnknown;
|
||||
|
||||
public class BTree {
|
||||
private BValue root = null;
|
||||
|
|
@ -39,8 +40,7 @@ public class BTree {
|
|||
private static final byte BE_END = (byte)'e';
|
||||
|
||||
public BValue decode() throws BDecodeError {
|
||||
BType type;
|
||||
if (data.length < 2) {
|
||||
if (data.length - offset < 2) {
|
||||
/* no bencode data can be less than 2 bytes: for integer must be 'i0e' atleast,
|
||||
* strings must be at least '0:' and lists and dicts can be empty
|
||||
*/
|
||||
|
|
@ -48,15 +48,9 @@ public class BTree {
|
|||
}
|
||||
|
||||
// consume and determine type
|
||||
switch (data[offset]) {
|
||||
case BE_INTEGER: type = BType.INTEGER; break;
|
||||
case BE_LIST: type = BType.LIST; break;
|
||||
case BE_DICT: type = BType.DICT; break;
|
||||
default: type = BType.STRING;
|
||||
}
|
||||
offset++;
|
||||
byte type = data[offset++];
|
||||
|
||||
if (type.equals(BType.INTEGER)) {
|
||||
if (type == BDecoder.BE_INTEGER) {
|
||||
// advance until we hit end marker
|
||||
int end = offset;
|
||||
while (end < data.length && data[end] != BDecoder.BE_END) {
|
||||
|
|
@ -67,10 +61,23 @@ public class BTree {
|
|||
}
|
||||
// convert bytes to string and string to integer
|
||||
byte[] bytes = Arrays.copyOfRange(data, offset, end);
|
||||
// after parsing integer set new offset and advance past terminator
|
||||
offset = end + 1;
|
||||
|
||||
return new BInteger(parseLong(bytes));
|
||||
} else if (type == BDecoder.BE_LIST) {
|
||||
BList list = new BList();
|
||||
// we're going to use recursion to read elements until we hit end
|
||||
while (offset < data.length && data[offset] != BDecoder.BE_END) {
|
||||
BValue item = decode();
|
||||
list.append(item);
|
||||
}
|
||||
// advance past terminator
|
||||
offset++;
|
||||
return list;
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new BDecodeUnknown(data, offset, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ public class BDecodeUnknown extends BDecodeError {
|
|||
byte unknown;
|
||||
|
||||
public BDecodeUnknown(byte[] data, int offset, byte unknown) {
|
||||
super(data, offset, String.format("Unknown symbol 0x%x at offset %d", unknown));
|
||||
super(data, offset, String.format("Unknown symbol 0x%x at offset %d", unknown, offset));
|
||||
this.unknown = unknown;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,4 +36,50 @@ public class BTreeTest {
|
|||
tree.decode(data);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyList() throws BDecodeError {
|
||||
final byte[] data = "le".getBytes();
|
||||
|
||||
BTree tree = new BTree();
|
||||
assertDoesNotThrow(() -> {
|
||||
tree.decode(data);
|
||||
|
||||
BValue root = tree.getRoot();
|
||||
assertNotNull(root);
|
||||
assertEquals(((BList)root).getLength(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testList() throws BDecodeError {
|
||||
final byte[] data = "li1ei2345678eli69eee".getBytes();
|
||||
|
||||
BTree tree = new BTree();
|
||||
assertDoesNotThrow(() -> {
|
||||
tree.decode(data);
|
||||
|
||||
assertNotNull(tree.getRoot());
|
||||
|
||||
BList list = (BList)tree.getRoot();
|
||||
{
|
||||
System.out.println(String.format("BDecode'd list size: %d", list.getLength()));
|
||||
System.out.println("BDecode'd list contents:");
|
||||
for (BValue item : list) {
|
||||
System.out.println(item.toString());
|
||||
}
|
||||
}
|
||||
assertDoesNotThrow(() -> {
|
||||
assertEquals(list.get(BType.INTEGER, 0), new BInteger(1));
|
||||
assertEquals(list.get(BType.INTEGER, 1), new BInteger(2345678));
|
||||
|
||||
BInteger value = list
|
||||
.<BList>get(BType.LIST, 2)
|
||||
.<BInteger>get(BType.INTEGER, 0);
|
||||
assertNotNull(value);
|
||||
assertEquals(value, new BInteger(69));
|
||||
System.out.println("value from nested list: " + value);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue