Skip to content

Commit e900566

Browse files
committed
improved byte code to add extra flag byte for seldom cases (whole stream or expression to calculate length)
1 parent 79c8e28 commit e900566

File tree

3 files changed

+63
-38
lines changed

3 files changed

+63
-38
lines changed

src/main/java/com/igormaznitsa/jbbp/JBBPParser.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,30 +132,34 @@ private List<JBBPAbstractField> parseStruct(final JBBPBitInputStream inStream, f
132132
break;
133133
}
134134

135-
final int code = compiled[positionAtCompiledBlock.getAndIncrement()] & 0xFF;
136-
135+
final int c = compiled[positionAtCompiledBlock.getAndIncrement()] & 0xFF;
136+
final boolean noExtraField = (c & JBBPCompiler.FLAG_EXTRA_FLAGS) == 0;
137+
final int ec = noExtraField ? 0 : compiled[positionAtCompiledBlock.getAndIncrement()] & 0xFF;
138+
139+
final int code = (ec<<8) | c;
140+
137141
final JBBPNamedFieldInfo name = (code & JBBPCompiler.FLAG_NAMED) == 0 ? null : compiledBlock.getNamedFields()[positionAtNamedFieldList.getAndIncrement()];
138142
final JBBPByteOrder byteOrder = (code & JBBPCompiler.FLAG_LITTLE_ENDIAN) == 0 ? JBBPByteOrder.BIG_ENDIAN : JBBPByteOrder.LITTLE_ENDIAN;
139143

140144
final boolean resultNotIgnored = !skipStructureFields;
141145
final boolean wholeStreamArray;
142146
final int arrayLength;
143147
final int packedArraySizeOffset;
144-
switch (code & (JBBPCompiler.FLAG_ARRAY | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM)) {
148+
switch (code & (JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM<<8))) {
145149
case JBBPCompiler.FLAG_ARRAY: {
146150
final int pos = positionAtCompiledBlock.get();
147151
arrayLength = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
148152
packedArraySizeOffset = positionAtCompiledBlock.get() - pos;
149153
wholeStreamArray = false;
150154
}
151155
break;
152-
case JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM: {
156+
case (JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM << 8): {
153157
wholeStreamArray = resultNotIgnored;
154158
packedArraySizeOffset = 0;
155159
arrayLength = 0;
156160
}
157161
break;
158-
case JBBPCompiler.FLAG_ARRAY | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM: {
162+
case JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM << 8): {
159163
final JBBPIntegerValueEvaluator evaluator = this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors.getAndIncrement()];
160164
arrayLength = resultNotIgnored ? evaluator.eval(inStream, positionAtCompiledBlock.get(), this.compiledBlock, namedNumericFieldMap) : 0;
161165
packedArraySizeOffset = 0;
@@ -359,7 +363,7 @@ private List<JBBPAbstractField> parseStruct(final JBBPBitInputStream inStream, f
359363
final int structStart = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
360364

361365
if (inStream.hasAvailableData()) {
362-
positionAtCompiledBlock.set(structStart + 1);
366+
positionAtCompiledBlock.set(structStart + (noExtraField ? 1 : 2));
363367
}
364368
}
365369

@@ -386,7 +390,7 @@ private List<JBBPAbstractField> parseStruct(final JBBPBitInputStream inStream, f
386390
// not the last
387391
positionAtNamedFieldList.set(nameFieldCurrent);
388392
positionAtVarLengthProcessors.set(varLenProcCurrent);
389-
positionAtCompiledBlock.set(structBodyStart + packedArraySizeOffset + 1);
393+
positionAtCompiledBlock.set(structBodyStart + packedArraySizeOffset + (noExtraField ? 1 : 2));
390394
}
391395
}
392396
}

src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiler.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,16 @@ private StructStackItem(final int namedFieldCounter, final int startStructureOff
165165
public static final int FLAG_LITTLE_ENDIAN = 0x40;
166166

167167
/**
168-
* The Byte-Code Flag shows that the field is an array which size is defined
168+
* The Flag shows that next byte contains extra flags.
169+
*/
170+
public static final int FLAG_EXTRA_FLAGS = 0x80;
171+
172+
/**
173+
* The Extra flag shows that the field is an array which size is defined
169174
* by an expression or the array is unsized and must be read till the end of a
170175
* stream.
171176
*/
172-
public static final int FLAG_EXPRESSION_OR_WHOLESTREAM = 0x80;
177+
public static final int EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM = 0x01;
173178

174179
public static JBBPCompiledBlock compile(final String script) throws IOException {
175180
return compile(script, null);
@@ -213,9 +218,20 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
213218
final int code = prepareCodeForToken(token, customTypeFieldProcessor);
214219
final int startFieldOffset = offset;
215220

221+
final int extracode = code >>> 8;
222+
216223
out.write(code);
217224
offset++;
218225

226+
final int backOffset;
227+
if ((code & FLAG_EXTRA_FLAGS)!=0){
228+
out.write(extracode);
229+
offset++;
230+
backOffset = 2;
231+
}else{
232+
backOffset = 1;
233+
}
234+
219235
StructStackItem currentClosedStructure = null;
220236
boolean extraFieldPresented = false;
221237
int extraField = -1;
@@ -359,7 +375,7 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
359375
}
360376
break;
361377
case CODE_STRUCT_START: {
362-
structureStack.add(new StructStackItem(namedFields.size() + ((code & JBBPCompiler.FLAG_NAMED) == 0 ? 0 : 1), offset - 1, code, token));
378+
structureStack.add(new StructStackItem(namedFields.size() + ((code & JBBPCompiler.FLAG_NAMED) == 0 ? 0 : 1), startFieldOffset, code, token));
363379
}
364380
break;
365381
case CODE_STRUCT_END: {
@@ -377,13 +393,13 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
377393
}
378394

379395
if ((code & FLAG_ARRAY) != 0) {
380-
if ((code & FLAG_EXPRESSION_OR_WHOLESTREAM) != 0) {
396+
if ((extracode & EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM) != 0) {
381397
if ("_".equals(token.getArraySizeAsString())) {
382398
if (fieldUnrestrictedArrayOffset >= 0) {
383399
throw new JBBPCompilationException("Detected two or more unlimited arrays [" + script + ']', token);
384400
}
385401
else {
386-
fieldUnrestrictedArrayOffset = offset - 1;
402+
fieldUnrestrictedArrayOffset = startFieldOffset;
387403
}
388404
}
389405
else {
@@ -522,7 +538,7 @@ private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFi
522538
final JBBPFieldTypeParameterContainer descriptor = token.getFieldTypeParameters();
523539

524540
result = descriptor.getByteOrder() == JBBPByteOrder.LITTLE_ENDIAN ? FLAG_LITTLE_ENDIAN : 0;
525-
result |= token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_EXPRESSION_OR_WHOLESTREAM : FLAG_ARRAY);
541+
result |= token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_EXTRA_FLAGS | (EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM<<8) : FLAG_ARRAY);
526542
result |= token.getFieldName() == null ? 0 : FLAG_NAMED;
527543

528544
final String name = descriptor.getTypeName().toLowerCase(Locale.ENGLISH);
@@ -584,7 +600,7 @@ else if ("reset$$".equals(name)) {
584600
}
585601
break;
586602
case STRUCT_START: {
587-
result = token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_EXPRESSION_OR_WHOLESTREAM : FLAG_ARRAY);
603+
result = token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_EXTRA_FLAGS | (EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM << 8) : FLAG_ARRAY);
588604
result |= token.getFieldName() == null ? 0 : FLAG_NAMED;
589605
result |= CODE_STRUCT_START;
590606
}

src/test/java/com/igormaznitsa/jbbp/compiler/JBBPCompilerTest.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ public void testCompile_ErrorForWrongChar() throws Exception {
4040
@Test
4141
public void testCompile_StructForWholeStreamAsSecondField() throws Exception {
4242
final JBBPCompiledBlock block = JBBPCompiler.compile("byte;test [_] {byte;}");
43-
assertEquals(5, block.getCompiledData().length);
43+
assertEquals(6, block.getCompiledData().length);
4444
assertEquals(JBBPCompiler.CODE_BYTE, block.getCompiledData()[0]);
45-
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM | JBBPCompiler.FLAG_NAMED, block.getCompiledData()[1] & 0xFF);
46-
assertEquals(JBBPCompiler.CODE_BYTE, block.getCompiledData()[2]);
47-
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[3]);
48-
assertEquals(1, block.getCompiledData()[4]);
45+
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_EXTRA_FLAGS | JBBPCompiler.FLAG_NAMED, block.getCompiledData()[1] & 0xFF);
46+
assertEquals(JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM, block.getCompiledData()[2] & 0xFF);
47+
assertEquals(JBBPCompiler.CODE_BYTE, block.getCompiledData()[3]);
48+
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[4]);
49+
assertEquals(1, block.getCompiledData()[5]);
4950
}
5051

5152
@Test
@@ -62,24 +63,26 @@ public void testCompile_ErrorForFieldAfterWholeStreamArray() throws Exception {
6263
@Test
6364
public void testCompile_WholeStreamArrayInsideStructure() throws Exception {
6465
final JBBPCompiledBlock block = JBBPCompiler.compile("test {byte [_];}");
65-
assertEquals(4, block.getCompiledData().length);
66+
assertEquals(5, block.getCompiledData().length);
6667
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED, block.getCompiledData()[0]);
67-
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM, block.getCompiledData()[1] & 0xFF);
68-
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[2]);
69-
assertEquals(0, block.getCompiledData()[3]);
68+
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_EXTRA_FLAGS, block.getCompiledData()[1] & 0xFF);
69+
assertEquals(JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM, block.getCompiledData()[2] & 0xFF);
70+
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[3]);
71+
assertEquals(0, block.getCompiledData()[4]);
7072
}
7173

7274
@Test
7375
public void testCompile_WholeStreamStructureArrayInsideStructure() throws Exception {
7476
final JBBPCompiledBlock block = JBBPCompiler.compile("test { whole[_]{ byte;}}");
75-
assertEquals(7, block.getCompiledData().length);
77+
assertEquals(8, block.getCompiledData().length);
7678
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED, block.getCompiledData()[0]);
77-
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM, block.getCompiledData()[1] & 0xFF);
78-
assertEquals(JBBPCompiler.CODE_BYTE, block.getCompiledData()[2]);
79-
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[3]);
80-
assertEquals(1, block.getCompiledData()[4]);
81-
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[5]);
82-
assertEquals(0, block.getCompiledData()[6]);
79+
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_EXTRA_FLAGS, block.getCompiledData()[1] & 0xFF);
80+
assertEquals(JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM, block.getCompiledData()[2] & 0xFF);
81+
assertEquals(JBBPCompiler.CODE_BYTE, block.getCompiledData()[3]);
82+
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[4]);
83+
assertEquals(1, block.getCompiledData()[5]);
84+
assertEquals(JBBPCompiler.CODE_STRUCT_END, block.getCompiledData()[6]);
85+
assertEquals(0, block.getCompiledData()[7]);
8386
}
8487

8588
@Test
@@ -459,15 +462,16 @@ public void testCompile_FixedLengthByteArrayInStructure() throws Exception {
459462
public void testCompile_VarLengthByteArrayInStructure() throws Exception {
460463
final JBBPCompiledBlock block = JBBPCompiler.compile("out { int len; some {byte [len] HeLLo;} }");
461464
final byte[] compiled = block.getCompiledData();
462-
assertEquals(8, compiled.length);
465+
assertEquals(9, compiled.length);
463466
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED, compiled[0]);
464467
assertEquals(JBBPCompiler.CODE_INT | JBBPCompiler.FLAG_NAMED, compiled[1] & 0xFF);
465468
assertEquals(JBBPCompiler.CODE_STRUCT_START | JBBPCompiler.FLAG_NAMED, compiled[2]);
466-
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_ARRAY | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM, compiled[3] & 0xFF);
467-
assertEquals(JBBPCompiler.CODE_STRUCT_END, compiled[4]);
468-
assertEquals(2, compiled[5]);
469-
assertEquals(JBBPCompiler.CODE_STRUCT_END, compiled[6]);
470-
assertEquals(0, compiled[7]);
469+
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_ARRAY | JBBPCompiler.FLAG_EXTRA_FLAGS, compiled[3] & 0xFF);
470+
assertEquals(JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM, compiled[4] & 0xFF);
471+
assertEquals(JBBPCompiler.CODE_STRUCT_END, compiled[5]);
472+
assertEquals(2, compiled[6]);
473+
assertEquals(JBBPCompiler.CODE_STRUCT_END, compiled[7]);
474+
assertEquals(0, compiled[8]);
471475
assertEquals(4, block.getNamedFields().length);
472476
assertEquals("out", block.getNamedFields()[0].getFieldPath());
473477
assertEquals("out.len", block.getNamedFields()[1].getFieldPath());
@@ -499,10 +503,11 @@ public void testCompile_ErrorForUnknownFieldAsArrayLength() throws Exception {
499503
public void testCompile_ArrayWithUndefinedLength() throws Exception {
500504
final JBBPCompiledBlock compiled = JBBPCompiler.compile("byte [_] HeLLo;");
501505
final JBBPNamedFieldInfo field = compiled.findFieldForPath("hello");
502-
assertEquals(1, compiled.getCompiledData().length);
506+
assertEquals(2, compiled.getCompiledData().length);
503507
assertNotNull(field);
504508
assertEquals(0, field.getFieldOffsetInCompiledBlock());
505-
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_EXPRESSION_OR_WHOLESTREAM, compiled.getCompiledData()[0] & 0xFF);
509+
assertEquals(JBBPCompiler.CODE_BYTE | JBBPCompiler.FLAG_NAMED | JBBPCompiler.FLAG_EXTRA_FLAGS, compiled.getCompiledData()[0] & 0xFF);
510+
assertEquals(JBBPCompiler.EXTRAFLAG_EXPRESSION_OR_WHOLESTREAM, compiled.getCompiledData()[1] & 0xFF);
506511
}
507512

508513
@Test

0 commit comments

Comments
 (0)