mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 11:49:04 +01:00
Simplified serialisation format.
This commit is contained in:
@@ -181,7 +181,7 @@ class ReaderImpl implements Reader {
|
||||
private int readInt32Bits() throws IOException {
|
||||
readIntoBuffer(4);
|
||||
return ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) |
|
||||
((buf[2] & 0xFF) << 8) | (buf[3] & 0xFF);
|
||||
((buf[2] & 0xFF) << 8) | (buf[3] & 0xFF);
|
||||
}
|
||||
|
||||
private void readIntoBuffer(int length) throws IOException {
|
||||
@@ -220,16 +220,16 @@ class ReaderImpl implements Reader {
|
||||
private long readInt64Bits() throws IOException {
|
||||
readIntoBuffer(8);
|
||||
return ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) |
|
||||
((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) |
|
||||
((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) |
|
||||
((buf[6] & 0xFFL) << 8) | (buf[7] & 0xFFL);
|
||||
((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) |
|
||||
((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) |
|
||||
((buf[6] & 0xFFL) << 8) | (buf[7] & 0xFFL);
|
||||
}
|
||||
|
||||
public boolean hasIntAny() throws IOException {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next >= 0 || next == Tag.INT8 || next == Tag.INT16
|
||||
|| next == Tag.INT32 || next == Tag.INT64;
|
||||
|| next == Tag.INT32 || next == Tag.INT64;
|
||||
}
|
||||
|
||||
public long readIntAny() throws IOException {
|
||||
@@ -270,7 +270,7 @@ class ReaderImpl implements Reader {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.STRING
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_STRING;
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_STRING;
|
||||
}
|
||||
|
||||
public String readString() throws IOException {
|
||||
@@ -302,7 +302,7 @@ class ReaderImpl implements Reader {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next >= 0 || next == Tag.INT8 || next == Tag.INT16
|
||||
|| next == Tag.INT32;
|
||||
|| next == Tag.INT32;
|
||||
}
|
||||
|
||||
public boolean hasBytes() throws IOException {
|
||||
@@ -331,8 +331,8 @@ class ReaderImpl implements Reader {
|
||||
public boolean hasList() throws IOException {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.LIST || next == Tag.LIST_START
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_LIST;
|
||||
return next == Tag.LIST
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_LIST;
|
||||
}
|
||||
|
||||
public List<Object> readList() throws IOException {
|
||||
@@ -343,8 +343,6 @@ class ReaderImpl implements Reader {
|
||||
if(!hasList()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
if(next == Tag.LIST) {
|
||||
return readList(e, readLength());
|
||||
} else if(next == Tag.LIST_START) {
|
||||
List<E> list = new ArrayList<E>();
|
||||
while(!hasEnd()) list.add(readObject(e));
|
||||
readEnd();
|
||||
@@ -400,7 +398,7 @@ class ReaderImpl implements Reader {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.STRUCT
|
||||
|| (next & Tag.SHORT_STRUCT_MASK) == Tag.SHORT_STRUCT;
|
||||
|| (next & Tag.SHORT_STRUCT_MASK) == Tag.SHORT_STRUCT;
|
||||
}
|
||||
|
||||
private Object readStruct() throws IOException {
|
||||
@@ -441,7 +439,7 @@ class ReaderImpl implements Reader {
|
||||
public boolean hasListStart() throws IOException {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.LIST_START;
|
||||
return next == Tag.LIST;
|
||||
}
|
||||
|
||||
public void readListStart() throws IOException {
|
||||
@@ -460,8 +458,8 @@ class ReaderImpl implements Reader {
|
||||
public boolean hasMap() throws IOException {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.MAP || next == Tag.MAP_START
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_MAP;
|
||||
return next == Tag.MAP
|
||||
|| (next & Tag.SHORT_MASK) == Tag.SHORT_MAP;
|
||||
}
|
||||
|
||||
public Map<Object, Object> readMap() throws IOException {
|
||||
@@ -472,8 +470,6 @@ class ReaderImpl implements Reader {
|
||||
if(!hasMap()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
if(next == Tag.MAP) {
|
||||
return readMap(k, v, readLength());
|
||||
} else if(next == Tag.MAP_START) {
|
||||
Map<K, V> m = new HashMap<K, V>();
|
||||
while(!hasEnd()) {
|
||||
if(m.put(readObject(k), readObject(v)) != null)
|
||||
@@ -488,7 +484,7 @@ class ReaderImpl implements Reader {
|
||||
}
|
||||
|
||||
private <K, V> Map<K, V> readMap(Class<K> k, Class<V> v, int size)
|
||||
throws IOException {
|
||||
throws IOException {
|
||||
assert size >= 0;
|
||||
if(size == 0) return Collections.emptyMap();
|
||||
Map<K, V> m = new HashMap<K, V>();
|
||||
@@ -502,7 +498,7 @@ class ReaderImpl implements Reader {
|
||||
public boolean hasMapStart() throws IOException {
|
||||
if(!hasLookahead) readLookahead(true);
|
||||
if(eof) return false;
|
||||
return next == Tag.MAP_START;
|
||||
return next == Tag.MAP;
|
||||
}
|
||||
|
||||
public void readMapStart() throws IOException {
|
||||
|
||||
@@ -11,7 +11,7 @@ class SerialComponentImpl implements SerialComponent {
|
||||
}
|
||||
|
||||
public int getSerialisedListStartLength() {
|
||||
// LIST_START tag
|
||||
// LIST tag
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,30 +2,28 @@ package net.sf.briar.serial;
|
||||
|
||||
interface Tag {
|
||||
|
||||
static final byte FALSE = -1; // 1111 1111
|
||||
static final byte TRUE = -2; // 1111 1110
|
||||
static final byte INT8 = -3; // 1111 1101
|
||||
static final byte INT16 = -4; // 1111 1100
|
||||
static final byte INT32 = -5; // 1111 1011
|
||||
static final byte INT64 = -6; // 1111 1010
|
||||
static final byte FLOAT32 = -7; // 1111 1001
|
||||
static final byte FLOAT64 = -8; // 1111 1000
|
||||
static final byte STRING = -9; // 1111 0111
|
||||
static final byte BYTES = -10; // 1111 0110
|
||||
static final byte LIST = -11; // 1111 0101
|
||||
static final byte MAP = -12; // 1111 0100
|
||||
static final byte LIST_START = -13; // 1111 0011
|
||||
static final byte MAP_START = -14; // 1111 0010
|
||||
static final byte END = -15; // 1111 0001
|
||||
static final byte NULL = -16; // 1111 0000
|
||||
static final byte STRUCT = -17; // 1110 1111
|
||||
static final byte FALSE = (byte) 0xFF; // 1111 1111
|
||||
static final byte TRUE = (byte) 0xFE; // 1111 1110
|
||||
static final byte INT8 = (byte) 0xFD; // 1111 1101
|
||||
static final byte INT16 = (byte) 0xFC; // 1111 1100
|
||||
static final byte INT32 = (byte) 0xFB; // 1111 1011
|
||||
static final byte INT64 = (byte) 0xFA; // 1111 1010
|
||||
static final byte FLOAT32 = (byte) 0xF9; // 1111 1001
|
||||
static final byte FLOAT64 = (byte) 0xF8; // 1111 1000
|
||||
static final byte STRING = (byte) 0xF7; // 1111 0111
|
||||
static final byte BYTES = (byte) 0xF6; // 1111 0110
|
||||
static final byte LIST = (byte) 0xF5; // 1111 0111
|
||||
static final byte MAP = (byte) 0xF4; // 1111 0100
|
||||
static final byte END = (byte) 0xF3; // 1111 0011
|
||||
static final byte NULL = (byte) 0xF2; // 1111 0010
|
||||
static final byte STRUCT = (byte) 0xF1; // 1111 0001
|
||||
|
||||
static final int SHORT_MASK = 0xF0; // Match first four bits
|
||||
static final int SHORT_STRING = 0x80; // 1000 xxxx
|
||||
static final int SHORT_BYTES = 0x90; // 1001 xxxx
|
||||
static final int SHORT_LIST = 0xA0; // 1010 xxxx
|
||||
static final int SHORT_MAP = 0xB0; // 1011 xxxx
|
||||
|
||||
static final int SHORT_STRUCT_MASK = 0xE0; // Match first three bits
|
||||
static final int SHORT_STRUCT = 0xC0; // 110x xxxx
|
||||
|
||||
static final int SHORT_MASK = 0xF0; // Match first four bits
|
||||
static final int SHORT_STRUCT_MASK = 0xE0; // Match first three bits
|
||||
}
|
||||
|
||||
@@ -103,8 +103,9 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeString(String s) throws IOException {
|
||||
byte[] b = s.getBytes("UTF-8");
|
||||
if(b.length < 16) write((byte) (Tag.SHORT_STRING | b.length));
|
||||
else {
|
||||
if(b.length < 16) {
|
||||
write((byte) (Tag.SHORT_STRING | b.length));
|
||||
} else {
|
||||
write(Tag.STRING);
|
||||
writeLength(b.length);
|
||||
}
|
||||
@@ -120,8 +121,9 @@ class WriterImpl implements Writer {
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] b) throws IOException {
|
||||
if(b.length < 16) write((byte) (Tag.SHORT_BYTES | b.length));
|
||||
else {
|
||||
if(b.length < 16) {
|
||||
write((byte) (Tag.SHORT_BYTES | b.length));
|
||||
} else {
|
||||
write(Tag.BYTES);
|
||||
writeLength(b.length);
|
||||
}
|
||||
@@ -130,12 +132,14 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeList(Collection<?> c) throws IOException {
|
||||
int length = c.size();
|
||||
if(length < 16) write((byte) (Tag.SHORT_LIST | length));
|
||||
else {
|
||||
if(length < 16) {
|
||||
write((byte) (Tag.SHORT_LIST | length));
|
||||
for(Object o : c) writeObject(o);
|
||||
} else {
|
||||
write(Tag.LIST);
|
||||
writeLength(length);
|
||||
for(Object o : c) writeObject(o);
|
||||
write(Tag.END);
|
||||
}
|
||||
for(Object o : c) writeObject(o);
|
||||
}
|
||||
|
||||
private void writeObject(Object o) throws IOException {
|
||||
@@ -155,7 +159,7 @@ class WriterImpl implements Writer {
|
||||
}
|
||||
|
||||
public void writeListStart() throws IOException {
|
||||
write(Tag.LIST_START);
|
||||
write(Tag.LIST);
|
||||
}
|
||||
|
||||
public void writeListEnd() throws IOException {
|
||||
@@ -164,19 +168,24 @@ class WriterImpl implements Writer {
|
||||
|
||||
public void writeMap(Map<?, ?> m) throws IOException {
|
||||
int length = m.size();
|
||||
if(length < 16) write((byte) (Tag.SHORT_MAP | length));
|
||||
else {
|
||||
if(length < 16) {
|
||||
write((byte) (Tag.SHORT_MAP | length));
|
||||
for(Entry<?, ?> e : m.entrySet()) {
|
||||
writeObject(e.getKey());
|
||||
writeObject(e.getValue());
|
||||
}
|
||||
} else {
|
||||
write(Tag.MAP);
|
||||
writeLength(length);
|
||||
}
|
||||
for(Entry<?, ?> e : m.entrySet()) {
|
||||
writeObject(e.getKey());
|
||||
writeObject(e.getValue());
|
||||
for(Entry<?, ?> e : m.entrySet()) {
|
||||
writeObject(e.getKey());
|
||||
writeObject(e.getValue());
|
||||
}
|
||||
write(Tag.END);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeMapStart() throws IOException {
|
||||
write(Tag.MAP_START);
|
||||
write(Tag.MAP);
|
||||
}
|
||||
|
||||
public void writeMapEnd() throws IOException {
|
||||
|
||||
@@ -178,7 +178,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadList() throws Exception {
|
||||
setContents("F5" + "03" + "01" + "83666F6F" + "FC0080");
|
||||
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
|
||||
List<Object> l = r.readList(Object.class);
|
||||
assertNotNull(l);
|
||||
assertEquals(3, l.size());
|
||||
@@ -213,7 +213,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadShortMap() throws Exception {
|
||||
setContents("B" + "2" + "83666F6F" + "7B" + "90" + "F0");
|
||||
setContents("B" + "2" + "83666F6F" + "7B" + "90" + "F2");
|
||||
Map<Object, Object> m = r.readMap(Object.class, Object.class);
|
||||
assertNotNull(m);
|
||||
assertEquals(2, m.size());
|
||||
@@ -226,7 +226,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadMap() throws Exception {
|
||||
setContents("F4" + "02" + "83666F6F" + "7B" + "90" + "F0");
|
||||
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
|
||||
Map<Object, Object> m = r.readMap(Object.class, Object.class);
|
||||
assertNotNull(m);
|
||||
assertEquals(2, m.size());
|
||||
@@ -239,7 +239,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadMapTypeSafe() throws Exception {
|
||||
setContents("B" + "2" + "83666F6F" + "7B" + "80" + "F0");
|
||||
setContents("B" + "2" + "83666F6F" + "7B" + "80" + "F2");
|
||||
Map<String, Byte> m = r.readMap(String.class, Byte.class);
|
||||
assertNotNull(m);
|
||||
assertEquals(2, m.size());
|
||||
@@ -268,7 +268,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedList() throws Exception {
|
||||
setContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
|
||||
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
|
||||
List<Object> l = r.readList(Object.class);
|
||||
assertNotNull(l);
|
||||
assertEquals(3, l.size());
|
||||
@@ -280,7 +280,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedListElements() throws Exception {
|
||||
setContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
|
||||
setContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
|
||||
assertTrue(r.hasListStart());
|
||||
r.readListStart();
|
||||
assertFalse(r.hasListEnd());
|
||||
@@ -296,7 +296,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedListTypeSafe() throws Exception {
|
||||
setContents("F3" + "01" + "02" + "03" + "F1");
|
||||
setContents("F5" + "01" + "02" + "03" + "F3");
|
||||
List<Byte> l = r.readList(Byte.class);
|
||||
assertNotNull(l);
|
||||
assertEquals(3, l.size());
|
||||
@@ -308,7 +308,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedMap() throws Exception {
|
||||
setContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
|
||||
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
|
||||
Map<Object, Object> m = r.readMap(Object.class, Object.class);
|
||||
assertNotNull(m);
|
||||
assertEquals(2, m.size());
|
||||
@@ -321,7 +321,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedMapEntries() throws Exception {
|
||||
setContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
|
||||
setContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
|
||||
assertTrue(r.hasMapStart());
|
||||
r.readMapStart();
|
||||
assertFalse(r.hasMapEnd());
|
||||
@@ -340,7 +340,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadDelimitedMapTypeSafe() throws Exception {
|
||||
setContents("F2" + "83666F6F" + "7B" + "80" + "F0" + "F1");
|
||||
setContents("F4" + "83666F6F" + "7B" + "80" + "F2" + "F3");
|
||||
Map<String, Byte> m = r.readMap(String.class, Byte.class);
|
||||
assertNotNull(m);
|
||||
assertEquals(2, m.size());
|
||||
@@ -372,7 +372,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadStruct() throws Exception {
|
||||
setContents("C0" + "83666F6F" + "EF" + "FF" + "83666F6F");
|
||||
setContents("C0" + "83666F6F" + "F1" + "FF" + "83666F6F");
|
||||
// Add object readers for two structs
|
||||
r.addObjectReader(0, new ObjectReader<Foo>() {
|
||||
public Foo readObject(Reader r) throws IOException {
|
||||
@@ -395,7 +395,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadStructWithConsumer() throws Exception {
|
||||
setContents("C0" + "83666F6F" + "EF" + "FF" + "83666F6F");
|
||||
setContents("C0" + "83666F6F" + "F1" + "FF" + "83666F6F");
|
||||
// Add object readers for two structs
|
||||
r.addObjectReader(0, new ObjectReader<Foo>() {
|
||||
public Foo readObject(Reader r) throws IOException {
|
||||
@@ -427,7 +427,7 @@ public class ReaderImplTest extends BriarTestCase {
|
||||
assertTrue(r.hasStruct(255));
|
||||
assertEquals("foo", r.readStruct(255, Bar.class).s);
|
||||
// Check that everything was passed to the consumer
|
||||
assertEquals("C0" + "83666F6F" + "EF" + "FF" + "83666F6F",
|
||||
assertEquals("C0" + "83666F6F" + "F1" + "FF" + "83666F6F",
|
||||
StringUtils.toHexString(out.toByteArray()));
|
||||
}
|
||||
|
||||
|
||||
@@ -179,8 +179,8 @@ public class WriterImplTest extends BriarTestCase {
|
||||
List<Object> l = new ArrayList<Object>();
|
||||
for(int i = 0; i < 16; i++) l.add(i);
|
||||
w.writeList(l);
|
||||
// LIST tag, length as uint7, elements as uint7
|
||||
checkContents("F5" + "10" + "000102030405060708090A0B0C0D0E0F");
|
||||
// LIST tag, elements as uint7, END tag
|
||||
checkContents("F5" + "000102030405060708090A0B0C0D0E0F" + "F3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -191,7 +191,7 @@ public class WriterImplTest extends BriarTestCase {
|
||||
l.add(2);
|
||||
w.writeList(l);
|
||||
// SHORT_LIST tag, length, 1 as uint7, null, 2 as uint7
|
||||
checkContents("A" + "3" + "01" + "F0" + "02");
|
||||
checkContents("A" + "3" + "01" + "F2" + "02");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -212,10 +212,10 @@ public class WriterImplTest extends BriarTestCase {
|
||||
Map<Object, Object> m = new LinkedHashMap<Object, Object>();
|
||||
for(int i = 0; i < 16; i++) m.put(i, i + 1);
|
||||
w.writeMap(m);
|
||||
// MAP tag, size as uint7, entries as uint7
|
||||
checkContents("F4" + "10" + "0001" + "0102" + "0203" + "0304" + "0405"
|
||||
// MAP tag, entries as uint7, END tag
|
||||
checkContents("F4" + "0001" + "0102" + "0203" + "0304" + "0405"
|
||||
+ "0506" + "0607" + "0708" + "0809" + "090A" + "0A0B" + "0B0C"
|
||||
+ "0C0D" + "0D0E" + "0E0F" + "0F10");
|
||||
+ "0C0D" + "0D0E" + "0E0F" + "0F10" + "F3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -225,9 +225,9 @@ public class WriterImplTest extends BriarTestCase {
|
||||
w.writeString("foo"); // Written as short string
|
||||
w.writeIntAny(128L); // Written as an int16
|
||||
w.writeListEnd();
|
||||
// LIST_START tag, 1 as uint7, "foo" as short string, 128 as int16,
|
||||
// LIST tag, 1 as uint7, "foo" as short string, 128 as int16,
|
||||
// END tag
|
||||
checkContents("F3" + "01" + "83666F6F" + "FC0080" + "F1");
|
||||
checkContents("F5" + "01" + "83666F6F" + "FC0080" + "F3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -238,9 +238,9 @@ public class WriterImplTest extends BriarTestCase {
|
||||
w.writeBytes(new byte[] {}); // Written as short bytes
|
||||
w.writeNull();
|
||||
w.writeMapEnd();
|
||||
// MAP_START tag, "foo" as short string, 123 as uint7,
|
||||
// MAP tag, "foo" as short string, 123 as uint7,
|
||||
// byte[] {} as short bytes, NULL tag, END tag
|
||||
checkContents("F2" + "83666F6F" + "7B" + "90" + "F0" + "F1");
|
||||
checkContents("F4" + "83666F6F" + "7B" + "90" + "F2" + "F3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -261,7 +261,7 @@ public class WriterImplTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testWriteNull() throws IOException {
|
||||
w.writeNull();
|
||||
checkContents("F0");
|
||||
checkContents("F2");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -278,7 +278,7 @@ public class WriterImplTest extends BriarTestCase {
|
||||
w.writeStructId(32);
|
||||
w.writeStructId(255);
|
||||
// STRUCT tag, 32 as uint8, STRUCT tag, 255 as uint8
|
||||
checkContents("EF" + "20" + "EF" + "FF");
|
||||
checkContents("F1" + "20" + "F1" + "FF");
|
||||
}
|
||||
|
||||
private void checkContents(String hex) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user