Add fast path for writing BdfDictionaries.

This commit is contained in:
akwizgran
2023-02-20 11:56:13 +00:00
parent 0ced10b3a9
commit ccd6ed9ff0
2 changed files with 39 additions and 12 deletions

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.data;
import org.briarproject.bramble.api.Bytes; import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfWriter; import org.briarproject.bramble.api.data.BdfWriter;
import org.briarproject.nullsafety.NotNullByDefault; import org.briarproject.nullsafety.NotNullByDefault;
@@ -11,6 +12,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe; import javax.annotation.concurrent.NotThreadSafe;
@@ -171,16 +173,24 @@ final class BdfWriterImpl implements BdfWriter {
@Override @Override
public void writeDictionary(Map<?, ?> m) throws IOException { public void writeDictionary(Map<?, ?> m) throws IOException {
out.write(DICTIONARY); out.write(DICTIONARY);
// Write entries in canonical order if (m instanceof BdfDictionary) {
List<String> keys = new ArrayList<>(m.size()); // Entries are already sorted and keys are known to be strings
for (Object k : m.keySet()) { for (Entry<String, Object> e : ((BdfDictionary) m).entrySet()) {
if (!(k instanceof String)) throw new FormatException(); writeString(e.getKey());
keys.add((String) k); writeObject(e.getValue());
} }
sort(keys); } else {
for (String key : keys) { // Check that keys are strings, write entries in canonical order
writeString(key); List<String> keys = new ArrayList<>(m.size());
writeObject(m.get(key)); for (Object k : m.keySet()) {
if (!(k instanceof String)) throw new FormatException();
keys.add((String) k);
}
sort(keys);
for (String key : keys) {
writeString(key);
writeObject(m.get(key));
}
} }
out.write(END); out.write(END);
} }

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.data; package org.briarproject.bramble.data;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.junit.Test; import org.junit.Test;
@@ -168,9 +169,11 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteDictionary() throws IOException { public void testWriteDictionary() throws IOException {
// Use LinkedHashMap to get predictable iteration order // Add entries to dictionary in descending order - they should be
// output in ascending order. Use LinkedHashMap to get predictable
// iteration order
Map<String, Object> m = new LinkedHashMap<>(); Map<String, Object> m = new LinkedHashMap<>();
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i); for (int i = 3; i >= 0; i--) m.put(String.valueOf(i), i);
w.writeDictionary(m); w.writeDictionary(m);
// DICTIONARY tag, keys as strings and values as integers, END tag // DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" + checkContents("70" + "41" + "01" + "30" + "21" + "00" +
@@ -179,6 +182,20 @@ public class BdfWriterImplTest extends BrambleTestCase {
"41" + "01" + "33" + "21" + "03" + "80"); "41" + "01" + "33" + "21" + "03" + "80");
} }
@Test
public void testWriteBdfDictionary() throws IOException {
// Add entries to dictionary in descending order - they should be
// output in ascending order
BdfDictionary d = new BdfDictionary();
for (int i = 3; i >= 0; i--) d.put(String.valueOf(i), i);
w.writeDictionary(d);
// DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
"41" + "01" + "31" + "21" + "01" +
"41" + "01" + "32" + "21" + "02" +
"41" + "01" + "33" + "21" + "03" + "80");
}
@Test @Test
public void testWriteNestedDictionariesAndLists() throws IOException { public void testWriteNestedDictionariesAndLists() throws IOException {
Map<String, Object> inner = new LinkedHashMap<>(); Map<String, Object> inner = new LinkedHashMap<>();