raydac/java-binary-block-parser

DSL signed 24bit interger?

mimil opened this issue · 4 comments

mimil commented

Hello,

from what I read in your documentation, I do not see the way to map a primary type on an abritrary bit/byte lenght. Like how could I do for:

  • 24 bits signed integer (so stored on 3 bytes)
  • 23 bits signed integer (so stored on 2 bytes + 7 bits)

Every primary types should support the notation [:1..x] not only bit type, no?

Thank you for you help,
Regards,
Cedric,

JBBP allows to define custom types and process them, for instance I implemented type for reading 3 byte int values (it may contain errors in implementation because I wrote it just as example)

  private static final class Int24CustomTypeProcessor implements JBBPCustomFieldTypeProcessor {

    private static final String[] TYPES = new String[]{"int24"};

    @Override
    public String[] getCustomFieldTypes() {
      return TYPES;
    }

    @Override
    public boolean isAllowed(final JBBPFieldTypeParameterContainer fieldType, final String fieldName, final int extraData, final boolean isArray) {
      return true;
    }

    private int readInt24(final JBBPBitInputStream in) throws IOException {
      final int part1 = in.readUnsignedShort(JBBPByteOrder.BIG_ENDIAN);
      final int part2 = in.readByte();
      return (part1 << 8) | (part2 & 0xFF);
    }

    @Override
    public JBBPAbstractField readCustomFieldType(final JBBPBitInputStream in,
        final JBBPBitOrder bitOrder,
        final int parserFlags,
        final JBBPFieldTypeParameterContainer customTypeFieldInfo,
        final JBBPNamedFieldInfo fieldName,
        final int extraData,
        final boolean readWholeStream,
        final int arrayLength) throws IOException {

      final String name = customTypeFieldInfo.getTypeName();
      if (name.equals("int24")) {
        if (arrayLength < 0) {
          return new JBBPFieldInt(fieldName, readInt24(in));
        } else if (readWholeStream) {
          int[] buffer = new int[1024];
          int pos = 0;
          while (in.hasAvailableData()) {
            final int next = readInt24(in);
            if (buffer.length == pos) {
              final int[] newbuffer = new int[buffer.length << 1];
              System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
              buffer = newbuffer;
            }
            buffer[pos++] = (int) next;
          }
          if (buffer.length == pos) {
            return new JBBPFieldArrayInt(fieldName, buffer);
          }
          final int[] result = new int[pos];
          System.arraycopy(buffer, 0, result, 0, pos);
          return new JBBPFieldArrayInt(fieldName, result);
        } else {
          final int[] array = new int[arrayLength];
          for (int i = 0; i < arrayLength; i++) {
            array[i] = readInt24(in);
          }
          return new JBBPFieldArrayInt(fieldName, array);
        }
      } else {
        throw new Error("Unexpected type");
      }
    }
  }
public static void main(String... args) throws Exception {
    final JBBPParser parser = JBBPParser.prepare("int24 v1; byte v2;",new Int24CustomTypeProcessor());
    final JBBPFieldStruct struct = parser.parse(new byte[]{0x01,0x02,0x03,0x04});
    System.out.println("v1 = 0x"+Integer.toHexString(struct.findFieldForNameAndType("v1", JBBPFieldInt.class).getAsInt()));
    System.out.println("v2 = 0x"+Integer.toHexString(struct.findFieldForNameAndType("v2", JBBPFieldByte.class).getAsInt()));
  }

as result it will print

v1 = 0x10203
v2 = 0x4
mimil commented

Hi,

thank you for this fast reply, I will use your sample code.

But do you think it makes sense to support the [:..x] notation? If I look to another java binary framework (preon), it supports such kind of feature:

@Purpose("The offset of the byte where the bitmap data can be found.")
    @BoundNumber(size = "32")
    private long bitmapDataOffset;

Regards,
Cedric

may be preon is more powerful framework and covers bigger number of cases, I developed JBBP for my own purposes and for such cases implemented points to extend behavior
I have added test case for three byte integer

mimil commented

Thanks for the other users for sharing the testcase source code in github.

it was more a question than a request to you to think about this feature. I am no expert de binary data structures, but I think (if someone/or me) wants to provide a pull request on this topic, it could be nice to have your point of view.

It is alreay a good feature to support adding new types the way you did it!

Cedric,