Wiki
Clone wikidata2l / 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
...
...
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!)
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. (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
(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)
(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
Inspecting binary files
Open addressbook.dat which should be in the same folder as example definition. You should see following.
Filtering content
Using dependency language we can filter arrays. See following pictures. After the filtering should look like.
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.
Updated