mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 15:19:53 +01:00
Encoder for structured metadata.
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
package org.briarproject.api.data;
|
||||||
|
|
||||||
|
import org.briarproject.api.FormatException;
|
||||||
|
import org.briarproject.api.db.Metadata;
|
||||||
|
|
||||||
|
public interface MetadataEncoder {
|
||||||
|
|
||||||
|
Metadata encode(BdfDictionary d) throws FormatException;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.google.inject.AbstractModule;
|
|||||||
|
|
||||||
import org.briarproject.api.data.BdfReaderFactory;
|
import org.briarproject.api.data.BdfReaderFactory;
|
||||||
import org.briarproject.api.data.BdfWriterFactory;
|
import org.briarproject.api.data.BdfWriterFactory;
|
||||||
|
import org.briarproject.api.data.MetadataEncoder;
|
||||||
import org.briarproject.api.data.MetadataParser;
|
import org.briarproject.api.data.MetadataParser;
|
||||||
|
|
||||||
public class DataModule extends AbstractModule {
|
public class DataModule extends AbstractModule {
|
||||||
@@ -13,5 +14,6 @@ public class DataModule extends AbstractModule {
|
|||||||
bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.class);
|
bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.class);
|
||||||
bind(BdfWriterFactory.class).to(BdfWriterFactoryImpl.class);
|
bind(BdfWriterFactory.class).to(BdfWriterFactoryImpl.class);
|
||||||
bind(MetadataParser.class).to(MetadataParserImpl.class);
|
bind(MetadataParser.class).to(MetadataParserImpl.class);
|
||||||
|
bind(MetadataEncoder.class).to(MetadataEncoderImpl.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
173
briar-core/src/org/briarproject/data/MetadataEncoderImpl.java
Normal file
173
briar-core/src/org/briarproject/data/MetadataEncoderImpl.java
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package org.briarproject.data;
|
||||||
|
|
||||||
|
import org.briarproject.api.FormatException;
|
||||||
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.api.data.BdfList;
|
||||||
|
import org.briarproject.api.data.MetadataEncoder;
|
||||||
|
import org.briarproject.api.db.Metadata;
|
||||||
|
import org.briarproject.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.briarproject.data.Types.DICTIONARY;
|
||||||
|
import static org.briarproject.data.Types.END;
|
||||||
|
import static org.briarproject.data.Types.FALSE;
|
||||||
|
import static org.briarproject.data.Types.FLOAT_64;
|
||||||
|
import static org.briarproject.data.Types.INT_16;
|
||||||
|
import static org.briarproject.data.Types.INT_32;
|
||||||
|
import static org.briarproject.data.Types.INT_64;
|
||||||
|
import static org.briarproject.data.Types.INT_8;
|
||||||
|
import static org.briarproject.data.Types.LIST;
|
||||||
|
import static org.briarproject.data.Types.NULL;
|
||||||
|
import static org.briarproject.data.Types.RAW_16;
|
||||||
|
import static org.briarproject.data.Types.RAW_32;
|
||||||
|
import static org.briarproject.data.Types.RAW_8;
|
||||||
|
import static org.briarproject.data.Types.STRING_16;
|
||||||
|
import static org.briarproject.data.Types.STRING_32;
|
||||||
|
import static org.briarproject.data.Types.STRING_8;
|
||||||
|
import static org.briarproject.data.Types.TRUE;
|
||||||
|
|
||||||
|
class MetadataEncoderImpl implements MetadataEncoder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Metadata encode(BdfDictionary d) throws FormatException {
|
||||||
|
Metadata m = new Metadata();
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
for (Map.Entry<String, Object> e : d.entrySet()) {
|
||||||
|
if (e.getValue() == null) {
|
||||||
|
// Special case: if the value is null, the key is being removed
|
||||||
|
m.put(e.getKey(), null);
|
||||||
|
} else {
|
||||||
|
encodeObject(out, e.getValue());
|
||||||
|
m.put(e.getKey(), out.toByteArray());
|
||||||
|
out.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeObject(ByteArrayOutputStream out, Object o)
|
||||||
|
throws FormatException {
|
||||||
|
if (o == null) out.write(NULL);
|
||||||
|
else if (o instanceof Boolean) out.write((Boolean) o ? TRUE : FALSE);
|
||||||
|
else if (o instanceof Byte) encodeInteger(out, (Byte) o);
|
||||||
|
else if (o instanceof Short) encodeInteger(out, (Short) o);
|
||||||
|
else if (o instanceof Integer) encodeInteger(out, (Integer) o);
|
||||||
|
else if (o instanceof Long) encodeInteger(out, (Long) o);
|
||||||
|
else if (o instanceof Float) encodeFloat(out, (Float) o);
|
||||||
|
else if (o instanceof Double) encodeFloat(out, (Double) o);
|
||||||
|
else if (o instanceof String) encodeString(out, (String) o);
|
||||||
|
else if (o instanceof byte[]) encodeRaw(out, (byte[]) o);
|
||||||
|
else if (o instanceof BdfList) encodeList(out, (BdfList) o);
|
||||||
|
else if (o instanceof BdfDictionary) encodeDictionary(out,
|
||||||
|
(BdfDictionary) o);
|
||||||
|
else throw new FormatException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeInteger(ByteArrayOutputStream out, byte i) {
|
||||||
|
out.write(INT_8);
|
||||||
|
out.write(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeInteger(ByteArrayOutputStream out, short i) {
|
||||||
|
if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
|
||||||
|
encodeInteger(out, (byte) i);
|
||||||
|
} else {
|
||||||
|
out.write(INT_16);
|
||||||
|
out.write((byte) (i >> 8));
|
||||||
|
out.write((byte) ((i << 8) >> 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeInteger(ByteArrayOutputStream out, int i) {
|
||||||
|
if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
|
||||||
|
encodeInteger(out, (short) i);
|
||||||
|
} else {
|
||||||
|
out.write(INT_32);
|
||||||
|
out.write((byte) (i >> 24));
|
||||||
|
out.write((byte) ((i << 8) >> 24));
|
||||||
|
out.write((byte) ((i << 16) >> 24));
|
||||||
|
out.write((byte) ((i << 24) >> 24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeInteger(ByteArrayOutputStream out, long i) {
|
||||||
|
if (i >= Integer.MIN_VALUE && i <= Integer.MAX_VALUE) {
|
||||||
|
encodeInteger(out, (int) i);
|
||||||
|
} else {
|
||||||
|
out.write(INT_64);
|
||||||
|
out.write((byte) (i >> 56));
|
||||||
|
out.write((byte) ((i << 8) >> 56));
|
||||||
|
out.write((byte) ((i << 16) >> 56));
|
||||||
|
out.write((byte) ((i << 24) >> 56));
|
||||||
|
out.write((byte) ((i << 32) >> 56));
|
||||||
|
out.write((byte) ((i << 40) >> 56));
|
||||||
|
out.write((byte) ((i << 48) >> 56));
|
||||||
|
out.write((byte) ((i << 56) >> 56));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeFloat(ByteArrayOutputStream out, float f) {
|
||||||
|
encodeFloat(out, (double) f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeFloat(ByteArrayOutputStream out, double d) {
|
||||||
|
long i = Double.doubleToLongBits(d);
|
||||||
|
out.write(FLOAT_64);
|
||||||
|
out.write((byte) (i >> 56));
|
||||||
|
out.write((byte) ((i << 8) >> 56));
|
||||||
|
out.write((byte) ((i << 16) >> 56));
|
||||||
|
out.write((byte) ((i << 24) >> 56));
|
||||||
|
out.write((byte) ((i << 32) >> 56));
|
||||||
|
out.write((byte) ((i << 40) >> 56));
|
||||||
|
out.write((byte) ((i << 48) >> 56));
|
||||||
|
out.write((byte) ((i << 56) >> 56));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeString(ByteArrayOutputStream out, String s) {
|
||||||
|
byte[] b = StringUtils.toUtf8(s);
|
||||||
|
if (b.length <= Byte.MAX_VALUE) {
|
||||||
|
out.write(STRING_8);
|
||||||
|
encodeInteger(out, (byte) b.length);
|
||||||
|
} else if (b.length <= Short.MAX_VALUE) {
|
||||||
|
out.write(STRING_16);
|
||||||
|
encodeInteger(out, (short) b.length);
|
||||||
|
} else {
|
||||||
|
out.write(STRING_32);
|
||||||
|
encodeInteger(out, b.length);
|
||||||
|
}
|
||||||
|
out.write(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeRaw(ByteArrayOutputStream out, byte[] b) {
|
||||||
|
if (b.length <= Byte.MAX_VALUE) {
|
||||||
|
out.write(RAW_8);
|
||||||
|
encodeInteger(out, (byte) b.length);
|
||||||
|
} else if (b.length <= Short.MAX_VALUE) {
|
||||||
|
out.write(RAW_16);
|
||||||
|
encodeInteger(out, (short) b.length);
|
||||||
|
} else {
|
||||||
|
out.write(RAW_32);
|
||||||
|
encodeInteger(out, b.length);
|
||||||
|
}
|
||||||
|
out.write(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeList(ByteArrayOutputStream out, BdfList list)
|
||||||
|
throws FormatException {
|
||||||
|
out.write(LIST);
|
||||||
|
for (Object o : list) encodeObject(out, o);
|
||||||
|
out.write(END);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeDictionary(ByteArrayOutputStream out,
|
||||||
|
BdfDictionary dict) throws FormatException {
|
||||||
|
out.write(DICTIONARY);
|
||||||
|
for (Map.Entry<String, Object> e : dict.entrySet()) {
|
||||||
|
encodeString(out, e.getKey());
|
||||||
|
encodeObject(out, e.getValue());
|
||||||
|
}
|
||||||
|
out.write(END);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ import org.briarproject.api.data.BdfDictionary;
|
|||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.data.MetadataParser;
|
import org.briarproject.api.data.MetadataParser;
|
||||||
import org.briarproject.api.db.Metadata;
|
import org.briarproject.api.db.Metadata;
|
||||||
|
import org.briarproject.util.StringUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.briarproject.data.Types.DICTIONARY;
|
import static org.briarproject.data.Types.DICTIONARY;
|
||||||
@@ -129,11 +129,7 @@ class MetadataParserImpl implements MetadataParser {
|
|||||||
if (len < 0) throw new FormatException();
|
if (len < 0) throw new FormatException();
|
||||||
byte[] b = new byte[len];
|
byte[] b = new byte[len];
|
||||||
if (in.read(b, 0, len) != len) throw new FormatException();
|
if (in.read(b, 0, len) != len) throw new FormatException();
|
||||||
try {
|
return StringUtils.fromUtf8(b, 0, len);
|
||||||
return new String(b, 0, len, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] parseRaw(ByteArrayInputStream in, int len)
|
private byte[] parseRaw(ByteArrayInputStream in, int len)
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ public class StringUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String fromUtf8(byte[] bytes, int off, int len) {
|
||||||
|
try {
|
||||||
|
return new String(bytes, off, len, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Converts the given byte array to a hex character array. */
|
/** Converts the given byte array to a hex character array. */
|
||||||
public static char[] toHexChars(byte[] bytes) {
|
public static char[] toHexChars(byte[] bytes) {
|
||||||
char[] hex = new char[bytes.length * 2];
|
char[] hex = new char[bytes.length * 2];
|
||||||
|
|||||||
Reference in New Issue
Block a user