0

I need to read a binary file where the size of a byte array depends on an optional value as well as on a constant number. How can I achieve this using Preon?

It seems that the byte array size calculation cannot be conditional ie. size="adaptationFieldControl==0b10 || adaptationFieldControl==0b11 ? 184-adaptationFieldLength : 184"

Using a method (see sample below) to calculate the dynamic size makes Preon fail with Caused by: org.codehaus.preon.el.BindingException: Failed to create binding for bound data called getPayloadLength.

public class packet {
    @BoundNumber(size = "2")
    byte adaptationFieldControl;

    /**
     * Returns the size of the payload if present in the packet
     * @return size corrected for adaptation fields
     */
    public int getPayloadLength() {
        if(isAdaptationFieldsPresent()) {
            return 188 - (4+adaptationFieldLength);
        }
        return 188-4;
    }

    @If("adaptationFieldControl==0b10 || adaptationFieldControl==0b11")
    @BoundNumber(size="8")
    short adaptationFieldLength;

    @If("adaptationFieldControl==0b01 || adaptationFieldControl==0b11")
    @BoundList(size="payloadLength")
    byte[] payload;

...

tchristensen
  • 86
  • 1
  • 7

2 Answers2

0

Preon uses the language "Limbo" to implement the expression evaluation. In Limbo, an expression evaluated to true, would take the value of "1" (and false "0").

As consequence the expression:

size=adaptationFieldControl==0b10 || adaptationFieldControl==0b11
    ? 184-adaptationFieldLength : 184

would take probably the form of:

size=184-(adaptationFieldControl==0b10||adaptationFieldControl==0b11)
    *adaptationFieldLength

I tested it, and unfortunately it seams that the method size does not accept it. I get the exception:

org.codehaus.preon.el.InvalidExpressionException: NoViableAltException(18@[])

It seams that the logical tokens are understood only by the "@If" annotation.

As a workaround I suggest you to define two fields prefixed by a "@If" annotation, and then implement a get method witch test the two fields for "null" and return the "non-null" one.

Marco Nanni
  • 113
  • 2
  • 6
0

Unless I'm entirely mistaken, the @If annotation actually prevents the field to be registered at all if the condition is false. So, according to Preon, there is no field called addaptationFieldLenght. That, and Preon has now way to bind to methods. There is technically not much to prevent it from getting implemented, but I wanted to make sure you can alway generate a sensible HTML description of the file format, and if there's logic hiding inside the body of methods, you cannot turn it into documentation.

If you have some complicated logic that simply doesn't fit in a Limbo expression, you might be better of creating a Codec for it. That way, you can make sure that your logic is also documented in the description of the file format generated.

Wilfred Springer
  • 10,869
  • 4
  • 55
  • 69
  • Wouldn't a Codec require the bits to be in a sequence? In the above case the binary packet has a header with flags and size fields describing what follows in the payload of the packet (MPEG-TS). In short the payload isn't next to the fields describing the size. – tchristensen Feb 13 '13 at 08:05
  • I would have to see an actual example, but the expression language used in Preon allows you to reach out of the object and grab some data living somewhere else. That's what a lot of annotations are doing. They allow you to grab information from a completely different location, as long as the data has been read so far. – Wilfred Springer Feb 13 '13 at 09:32