Wiki

Clone wiki

data2l / help-tutorial

Tutorial - the very start

BMP header definition - the "Hello World" example

Elements of description

Data2l supports following datatypes.

  • Void - always empty
  • Basic - string, word, byte, dword,...
  • Struct - universal container, can contain basics, arrays, structs or alternatives
  • Array - have array of anything, similar to struct but with an "index feature"
  • Alternative - runtime type selections according the selector code - explanation comes later

Using these and using language which defines dependencies one can describe very complex binary structures. Let's have a look on the simplest example. A BMP header file description.

BMP header description examples (hello world)

As you see below, to describe BMP is very simple there are few elements contained in one structure. These elements are simply placed one after another, there is no relation between them.

This C++ description is equal to following .d2l notation

struct BMP_Header {
    char            Magic[2];
    unsigned int    FileSize;
    unsigned int    Reserved;
    unsigned int     DataOffsetStart;
    ...
    ...
};

Later in this book we will use following notation to describe the binary structures which fits better to Data2l capabilities.

#comment
struct BMP_Header:
    string  Magic:
        size: 2
    dword   FileSize
    dword   Reserved
    dword   DataOffsetStart
    ...
    ...

header If we have the description inside Data2l we can do a few things with it. Inspect binary files using this definition. Access the inspected values via DOM or SAX interface. Generate optimized code for the values access...

None of it is having too much sense for such a simple definition, except of File inspection. So lets try it.

Click the Inspect File icon, find some .BMP file on your computer and open it. You should see following. (the colors can be highlighted using the context menu. Test it out!) inspection

AddressBook project

Requirements

We already know the foundation description types. Now we need to learn how to define dependencies between entities. Let's define following requirements for out second project.

We want a binary structure where we can store some number records with strings containing person name and street where he/she lives. Additional requirement is that we want to use as little space as possible for this record. In .dtl it could look like following.

struct AddrRec:
    byte        NameLen
    char[]      PersonName:
        size: NameLen
    byte        StreetLen
    char[]      Street:
        size: StreetLen
}

Additionally we want to do a random access to any of such a record using index number.

Defining the structure

Let's start from inside - define AddrRec in Data2l. AddrRec struct is not anymore C++ compatible we see that the PersonName length depends on value of previous byte and the same way in the Street member.

That's an example of simple dependence in Data2l. example1 (definition file can be found at %your_Data2l_folder%/examples/file_defs)

Array of AddrRec

Now we organize the records to an array. Our requirements states that we need to find the correct record based on index.

Via context menu we create Array and name it AddressArray (F2 or double click). We insert 2 members:

  • AddrRecOffs - Dword value representing offset to variable sized Addrrec
  • AddrRec - Structure which content was mentioned already above

example2 (definition file can be found at %your_Data2l_folder%/examples/file_defs)

Addressing

Our binary content will first contain values of offsets (after the value of number of records inside). Set of double words which will help us to jump to a correct AddrRec record.

Picture bellow shows how to calculate offset for AddrRecOffs member. Once the offset is calculated a DWord value will be read from the offset.

  • offsetof(AddressArray) - gives us offset from where AddressArray started to load itself
  • actindexof(AddressArray) - gives us the value of current index of array
  • sizeof(AddrRecOffs) - gives us static size of the specific element - in this case DWord (4 bytes)

example3 (Please forget now that there is "On Save" defined, it's not important for our purpose.)

The last thing - correct addressing of AddRec

Last piece to the puzzle. Let's explain the addressing

  • arraysizeof(AddressArray)*4 - the size of addressing records, number of records in array * sizeof(DWord)
  • AddrRecOffs - there are our data records, this value represent cumulative size of AddrRec records

example4

Inspecting binary files

Open addressbook.dat which should be in the same folder as example definition. You should see following. example5

Filtering content

Using dependency language we can filter arrays. See following pictures. filtering1 After the filtering should look like. filtering2

Validation

Using the dependency language we can define various validation rules which control the consistency of the structured file.

In our .BMP header description we can check whether the first "magic ID" element is equal to "BM". If everything is correct 1 (True) is returned if it is not, then we we return 0. This way we let know to the validation engine, what is Ok and what is not.

validation1

Updated