Skip to content

Commit c465b24

Browse files
committed
added support of reset counter and val commands
1 parent b384542 commit c465b24

File tree

2 files changed

+140
-7
lines changed

2 files changed

+140
-7
lines changed

jbbp/src/main/java/com/igormaznitsa/jbbp/utils/JBBPDslBuilder.java

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.igormaznitsa.jbbp.utils;
22

3+
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
34
import com.igormaznitsa.jbbp.io.JBBPBitNumber;
45
import com.igormaznitsa.jbbp.io.JBBPByteOrder;
56
import com.igormaznitsa.jbbp.mapper.Bin;
@@ -52,6 +53,31 @@ public static JBBPDslBuilder Begin() {
5253
return new JBBPDslBuilder();
5354
}
5455

56+
protected static String assertTextNotNullAndTrimmedNotEmpty(final String text) {
57+
if (text == null) {
58+
throw new NullPointerException("Must not be null");
59+
}
60+
if (text.trim().length() == 0) {
61+
throw new IllegalArgumentException("Must not be empty: " + text);
62+
}
63+
return text;
64+
}
65+
66+
protected static String assertNameIfNotNull(final String name) {
67+
if (name != null) {
68+
for (int i = 0; i < name.length(); i++) {
69+
final char c = name.charAt(i);
70+
if (i == 0 && Character.isDigit(c)) {
71+
throw new IllegalArgumentException("Digit can't be first char");
72+
}
73+
if (!Character.isLetterOrDigit(c)) {
74+
throw new IllegalArgumentException("Only letters and digits allowed: " + name);
75+
}
76+
}
77+
}
78+
return name;
79+
}
80+
5581
protected static String assertExpressionChars(final String expression) {
5682
if (expression == null) {
5783
throw new NullPointerException("Expression is null");
@@ -217,7 +243,7 @@ public JBBPDslBuilder Var(final String name) {
217243
/**
218244
* Add named var field.
219245
*
220-
* @param name name of the field, can be null
246+
* @param name name of the field, can be null
221247
* @param param optional parameter for the field, can be null
222248
* @return the builder instance, must not be null
223249
*/
@@ -319,6 +345,34 @@ public JBBPDslBuilder StructArray(final String name, final String sizeExpression
319345
return this;
320346
}
321347

348+
/**
349+
* Add virtual field which not be read but its value will be calculated by expression
350+
*
351+
* @param name name of the value, it must not be null or empty
352+
* @param expression expression to calculate value, it must not be null or empty
353+
* @return the builder instance, must not be null
354+
*/
355+
public JBBPDslBuilder Val(final String name, final String expression) {
356+
final Item item = new ItemVal(
357+
assertTextNotNullAndTrimmedNotEmpty(name),
358+
assertExpressionChars(assertTextNotNullAndTrimmedNotEmpty(expression)).trim()
359+
);
360+
this.items.add(item);
361+
return this;
362+
}
363+
364+
/**
365+
* Add command to reset counter of the current read stream.
366+
*
367+
* @return the builder instance, must not be null
368+
* @see JBBPBitInputStream#resetCounter()
369+
*/
370+
public JBBPDslBuilder ResetCounter() {
371+
final Item item = new ItemResetCounter();
372+
this.items.add(item);
373+
return this;
374+
}
375+
322376
/**
323377
* Create anonymous var array with fixed size.
324378
*
@@ -352,7 +406,7 @@ public JBBPDslBuilder VarArray(final String name, final int size) {
352406
/**
353407
* Create named var array with fixed size.
354408
*
355-
* @param name name of the array, can be null for anonymous one
409+
* @param name name of the array, can be null for anonymous one
356410
* @param sizeExpression expression to calculate size of the array, must not be null.
357411
* @return the builder instance, must not be null
358412
*/
@@ -363,8 +417,8 @@ public JBBPDslBuilder VarArray(final String name, final String sizeExpression) {
363417
/**
364418
* Create named var array with fixed size.
365419
*
366-
* @param name name of the array, can be null for anonymous one
367-
* @param size size of array, it can be negative if to read stream till end.
420+
* @param name name of the array, can be null for anonymous one
421+
* @param size size of array, it can be negative if to read stream till end.
368422
* @param param optional parameter for the field, can be null
369423
* @return the builder instance, must not be null
370424
*/
@@ -375,9 +429,9 @@ public JBBPDslBuilder VarArray(final String name, final int size, final String p
375429
/**
376430
* Create named var array with fixed size.
377431
*
378-
* @param name name of the array, can be null for anonymous one
432+
* @param name name of the array, can be null for anonymous one
379433
* @param sizeExpression expression to calculate size of the array, must not be null.
380-
* @param param optional parameter for the field, can be null
434+
* @param param optional parameter for the field, can be null
381435
* @return the builder instance, must not be null
382436
*/
383437
public JBBPDslBuilder VarArray(final String name, final String sizeExpression, final String param) {
@@ -1390,6 +1444,10 @@ public String End(final boolean format) {
13901444
doTabs(format, buffer, structCounter).append(item.toString());
13911445
} else if (item instanceof ItemAlign) {
13921446
doTabs(format, buffer, structCounter).append("align").append(item.sizeExpression == null ? "" : ':' + item.makeExpressionForExtraField(item.sizeExpression)).append(';');
1447+
} else if (item instanceof ItemVal) {
1448+
doTabs(format, buffer, structCounter).append("val").append(':' + item.makeExpressionForExtraField(item.sizeExpression)).append(' ').append(item.name).append(';');
1449+
} else if (item instanceof ItemResetCounter) {
1450+
doTabs(format, buffer, structCounter).append("reset$$;");
13931451
} else if (item instanceof ItemSkip) {
13941452
doTabs(format, buffer, structCounter).append("skip").append(item.sizeExpression == null ? "" : ':' + item.makeExpressionForExtraField(item.sizeExpression)).append(';');
13951453
} else if (item instanceof ItemComment) {
@@ -1662,7 +1720,7 @@ protected static class Item {
16621720

16631721
Item(final BinType type, final String name, final JBBPByteOrder byteOrder) {
16641722
this.type = type;
1665-
this.name = name;
1723+
this.name = name == null ? name : assertNameIfNotNull(assertTextNotNullAndTrimmedNotEmpty(name)).trim();
16661724
this.byteOrder = byteOrder;
16671725
}
16681726

@@ -1859,6 +1917,19 @@ protected static class ItemAlign extends Item {
18591917
}
18601918
}
18611919

1920+
protected static class ItemVal extends Item {
1921+
ItemVal(final String name, final String sizeExpression) {
1922+
super(BinType.UNDEFINED, assertTextNotNullAndTrimmedNotEmpty(name), JBBPByteOrder.BIG_ENDIAN);
1923+
this.sizeExpression = assertExpressionChars(assertTextNotNullAndTrimmedNotEmpty(sizeExpression).trim());
1924+
}
1925+
}
1926+
1927+
protected static class ItemResetCounter extends Item {
1928+
ItemResetCounter() {
1929+
super(BinType.UNDEFINED, null, JBBPByteOrder.BIG_ENDIAN);
1930+
}
1931+
}
1932+
18621933
protected static class ItemStructEnd extends Item {
18631934
private final boolean endAll;
18641935

jbbp/src/test/java/com/igormaznitsa/jbbp/utils/JBBPDslBuilderTest.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,34 @@ public void testEmptyStringForEmptyContent() {
1919
assertEquals("", Begin().End(true));
2020
}
2121

22+
@Test
23+
public void testWrongName() {
24+
assertThrows(IllegalArgumentException.class, new Executable() {
25+
@Override
26+
public void execute() throws Throwable {
27+
Begin().Int("").End();
28+
}
29+
});
30+
assertThrows(IllegalArgumentException.class, new Executable() {
31+
@Override
32+
public void execute() throws Throwable {
33+
Begin().Int(" ").End();
34+
}
35+
});
36+
assertThrows(IllegalArgumentException.class, new Executable() {
37+
@Override
38+
public void execute() throws Throwable {
39+
Begin().Int("3a").End();
40+
}
41+
});
42+
assertThrows(IllegalArgumentException.class, new Executable() {
43+
@Override
44+
public void execute() throws Throwable {
45+
Begin().Int("ab\n").End();
46+
}
47+
});
48+
}
49+
2250
@Test
2351
public void testNonFormatted() {
2452
assertEquals("bool test;{int field1;}", Begin().Bool("test").Struct().Int("field1").CloseStruct().End(false));
@@ -155,6 +183,40 @@ public void execute() throws Throwable {
155183
});
156184
}
157185

186+
@Test
187+
public void testResetCounter() {
188+
assertEquals("reset$$;", Begin().ResetCounter().End());
189+
}
190+
191+
@Test
192+
public void testVal() {
193+
assertThrows(NullPointerException.class, new Executable() {
194+
@Override
195+
public void execute() throws Throwable {
196+
Begin().Val(null, "a+b").End();
197+
}
198+
});
199+
assertThrows(NullPointerException.class, new Executable() {
200+
@Override
201+
public void execute() throws Throwable {
202+
Begin().Val("hello", null).End();
203+
}
204+
});
205+
assertThrows(IllegalArgumentException.class, new Executable() {
206+
@Override
207+
public void execute() throws Throwable {
208+
Begin().Val("", "a+b").End();
209+
}
210+
});
211+
assertThrows(IllegalArgumentException.class, new Executable() {
212+
@Override
213+
public void execute() throws Throwable {
214+
Begin().Val("hello", "").End();
215+
}
216+
});
217+
assertEquals("val:(a+b) hello;", Begin().Val("hello", "a+b").End());
218+
}
219+
158220
@Test
159221
public void testType_Align() {
160222
assertEquals("align:1;", Begin().Align().End());

0 commit comments

Comments
 (0)