diff --git a/bson/src/main/org/bson/BsonBinaryWriter.java b/bson/src/main/org/bson/BsonBinaryWriter.java index dd0a3e1ffa..7764cd718a 100644 --- a/bson/src/main/org/bson/BsonBinaryWriter.java +++ b/bson/src/main/org/bson/BsonBinaryWriter.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Stack; +import static java.lang.Math.max; import static java.lang.String.format; import static org.bson.assertions.Assertions.notNull; @@ -37,13 +38,34 @@ public class BsonBinaryWriter extends AbstractBsonWriter { private final BsonOutput bsonOutput; private final Stack<Integer> maxDocumentSizeStack = new Stack<>(); - private static final int ARRAY_INDEXES_CACHE_SIZE = 256; - private static final String[] ARRAY_INDEXES_CACHE = new String[ARRAY_INDEXES_CACHE_SIZE]; + private static final int ARRAY_INDEXES_CACHE_SIZE = 1000; + private static final byte[] ARRAY_INDEXES_BUFFER; + private static final int[] ARRAY_INDEXES_OFFSETS; + private static final int[] ARRAY_INDEXES_LENGTHS; private Mark mark; static { + ARRAY_INDEXES_LENGTHS = new int[ARRAY_INDEXES_CACHE_SIZE]; + ARRAY_INDEXES_OFFSETS = new int[ARRAY_INDEXES_CACHE_SIZE]; + int totalSize = 0; for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) { - ARRAY_INDEXES_CACHE[i] = Integer.toString(i); + totalSize += (int) (Math.log10(max(i, 1)) + + 1 // number of digits + + 1); // +1 for null terminator + } + ARRAY_INDEXES_BUFFER = new byte[totalSize]; + + // Fill buffer + int offset = 0; + for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) { + String string = Integer.toString(i); + int length = string.length(); + for (int j = 0; j < length; j++) { + ARRAY_INDEXES_BUFFER[offset++] = (byte) string.charAt(j); + } + ARRAY_INDEXES_BUFFER[offset++] = 0; + ARRAY_INDEXES_OFFSETS[i] = offset - (length + 1); + ARRAY_INDEXES_LENGTHS[i] = length + 1; // +1 for null terminator } } @@ -409,7 +431,9 @@ private void writeCurrentName() { if (index >= ARRAY_INDEXES_CACHE_SIZE) { bsonOutput.writeCString(Integer.toString(index)); } else { - bsonOutput.writeCString(ARRAY_INDEXES_CACHE[index]); + bsonOutput.writeBytes(ARRAY_INDEXES_BUFFER, + ARRAY_INDEXES_OFFSETS[index], + ARRAY_INDEXES_LENGTHS[index]); } } else { bsonOutput.writeCString(getName()); diff --git a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java index 84f2aeca65..0b067fc816 100644 --- a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java +++ b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java @@ -66,7 +66,7 @@ public void shouldThrowWhenMaxDocumentSizeIsExceeded() { writer.writeEndDocument(); fail(); } catch (BsonMaximumSizeExceededException e) { - assertEquals("Document size of 1037 is larger than maximum of 1024.", e.getMessage()); + assertEquals("Document size of 12917 is larger than maximum of 12904.", e.getMessage()); } } @@ -201,16 +201,16 @@ public void testWriteArray() { public void testWriteArrayElements() throws IOException { ByteArrayOutputStream expectedOutput = new ByteArrayOutputStream(); expectedOutput.write(new byte[]{ - 88, 11, 0, 0, //document length + -52, 25, 0, 0, //document length 4, // array type 97, 49, 0, // "a1" name + null terminator - 79, 11, 0, 0}); // array length + -61, 25, 0, 0}); // array length writer.writeStartDocument(); writer.writeStartArray("a1"); int arrayIndex = 0; - while (arrayIndex < 500) { + while (arrayIndex < 1100) { writer.writeBoolean(true); expectedOutput.write(BsonType.BOOLEAN.getValue());