Skip to content

Commit

Permalink
More testing, some refactoring wrt #201
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Apr 8, 2020
1 parent 6cedcc4 commit ae1b4f4
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 45 deletions.
Expand Up @@ -589,8 +589,25 @@ public void writeArray(int[] array, int offset, int length) throws IOException
// short-cut, do not create child array context etc
_verifyValueWrite("write int array");
_writeLengthMarker(PREFIX_TYPE_ARRAY, length);
for (int i = offset, end = offset+length; i < end; ++i) {
_writeIntNoCheck(array[i]);

if (_cfgMinimalInts) {
for (int i = offset, end = offset+length; i < end; ++i) {
final int value = array[i];
if (value < 0) {
_writeIntMinimal(PREFIX_TYPE_INT_NEG, -value - 1);
} else {
_writeIntMinimal(PREFIX_TYPE_INT_POS, value);
}
}
} else {
for (int i = offset, end = offset+length; i < end; ++i) {
final int value = array[i];
if (value < 0) {
_writeIntFull(PREFIX_TYPE_INT_NEG, -value - 1);
} else {
_writeIntFull(PREFIX_TYPE_INT_POS, value);
}
}
}
}

Expand Down Expand Up @@ -626,33 +643,24 @@ private final void _pushRemainingElements() {
_elementCounts[_elementCountsPtr++] = _currentRemainingElements;
}

private final void _writeIntNoCheck(int i) throws IOException {
int marker;
if (i < 0) {
i = -i - 1;
marker = PREFIX_TYPE_INT_NEG;
} else {
marker = PREFIX_TYPE_INT_POS;
}

// if ((_outputTail + needed) >= _outputEnd) { _flushBuffer(); }
private final void _writeIntMinimal(int markerBase, int i) throws IOException
{
_ensureRoomForOutput(5);

byte b0;
if (_cfgMinimalInts) {
if (i >= 0) {
if (i < 24) {
_outputBuffer[_outputTail++] = (byte) (marker + i);
_outputBuffer[_outputTail++] = (byte) (markerBase + i);
return;
}
if (i <= 0xFF) {
_outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT8_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT8_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) i;
return;
}
b0 = (byte) i;
i >>= 8;
if (i <= 0xFF) {
_outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT16_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT16_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) i;
_outputBuffer[_outputTail++] = b0;
return;
Expand All @@ -661,46 +669,27 @@ private final void _writeIntNoCheck(int i) throws IOException {
b0 = (byte) i;
i >>= 8;
}
_outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT32_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT32_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) (i >> 16);
_outputBuffer[_outputTail++] = (byte) (i >> 8);
_outputBuffer[_outputTail++] = (byte) i;
_outputBuffer[_outputTail++] = b0;
}

private final void _writeIntMinimal(int markerBase, int i) throws IOException
private final void _writeIntFull(int markerBase, int i) throws IOException
{
// if ((_outputTail + needed) >= _outputEnd) { _flushBuffer(); }
_ensureRoomForOutput(5);
byte b0;
if (i >= 0) {
if (i < 24) {
_outputBuffer[_outputTail++] = (byte) (markerBase + i);
return;
}
if (i <= 0xFF) {
_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT8_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) i;
return;
}
b0 = (byte) i;
i >>= 8;
if (i <= 0xFF) {
_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT16_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) i;
_outputBuffer[_outputTail++] = b0;
return;
}
} else {
b0 = (byte) i;
i >>= 8;
}

_outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT32_ELEMENTS);
_outputBuffer[_outputTail++] = (byte) (i >> 24);
_outputBuffer[_outputTail++] = (byte) (i >> 16);
_outputBuffer[_outputTail++] = (byte) (i >> 8);
_outputBuffer[_outputTail++] = (byte) i;
_outputBuffer[_outputTail++] = b0;
}


// Helper method that works like `writeNumber(long)` but DOES NOT
// check internal output state. It does, however, check need for minimization
private final void _writeLongNoCheck(long l) throws IOException {
if (_cfgMinimalInts) {
if (l >= 0) {
Expand Down
Expand Up @@ -31,7 +31,69 @@ public void testDoubleArray() throws Exception
_testDoubleArray();
}

public void testMinimalIntValues2() throws Exception
public void testMinimalIntValuesForInt() throws Exception
{
// Array with 3 values, with different sizing
_testMinimalIntValuesForInt(1, -1, 3, 11); // single-byte
_testMinimalIntValuesForInt(200, -200, 5, 11); // two-byte (marker, 0xFF)
_testMinimalIntValuesForInt(0xC831, -50000, 7, 11); // three-byte (marker, 0xFFFF)
_testMinimalIntValuesForInt(0x35690001, -(0x7FFFFFF0), 11, 11); // full
}

private void _testMinimalIntValuesForInt(int v1, int v2,
int minLen, int fullLen) throws Exception
{
final int[] input = new int[] { v1, v2 };
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
CBORGenerator gen = FACTORY.createGenerator(bytes);
assertTrue(gen.isEnabled(CBORGenerator.Feature.WRITE_MINIMAL_INTS));
gen.writeArray(input, 0, 2);
gen.close();

// With default settings, should get:
byte[] encoded = bytes.toByteArray();
assertEquals(minLen, encoded.length);

// then verify contents

CBORParser p = FACTORY.createParser(encoded);
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.INT, p.getNumberType());
assertEquals(input[0], p.getIntValue());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.INT, p.getNumberType());
assertEquals(input[1], p.getIntValue());
assertToken(JsonToken.END_ARRAY, p.nextToken());
p.close();

// but then also check without minimization
bytes = new ByteArrayOutputStream();
gen = FACTORY.createGenerator(bytes);
gen.disable(CBORGenerator.Feature.WRITE_MINIMAL_INTS);

gen.writeArray(input, 0, 2);
gen.close();

// With default settings, should get:
encoded = bytes.toByteArray();
assertEquals(fullLen, encoded.length);

// then verify contents

p = FACTORY.createParser(encoded);
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.INT, p.getNumberType());
assertEquals(input[0], p.getIntValue());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.INT, p.getNumberType());
assertEquals(input[1], p.getIntValue());
assertToken(JsonToken.END_ARRAY, p.nextToken());
p.close();
}

public void testMinimalIntValuesForLong() throws Exception
{
// Array with 2 values that can't be passed as `int`s but DO fit
// CBOR 5-byte int (sign + 32-bits)
Expand Down Expand Up @@ -63,6 +125,29 @@ public void testMinimalIntValues2() throws Exception
p.close();

// but then also check without minimization
bytes = new ByteArrayOutputStream();
gen = FACTORY.createGenerator(bytes);
gen.disable(CBORGenerator.Feature.WRITE_MINIMAL_INTS);

gen.writeArray(input, 0, 2);
gen.close();

// With default settings, should get:
encoded = bytes.toByteArray();
assertEquals(19, encoded.length);

// then verify contents

p = FACTORY.createParser(encoded);
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.LONG, p.getNumberType());
assertEquals(input[0], p.getLongValue());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(NumberType.LONG, p.getNumberType());
assertEquals(input[1], p.getLongValue());
assertToken(JsonToken.END_ARRAY, p.nextToken());
p.close();
}

private void _testIntArray() throws Exception {
Expand Down

0 comments on commit ae1b4f4

Please sign in to comment.