Skip to content

packetGenerator documentation

L3nn0x edited this page Jun 3, 2019 · 9 revisions

Packet generator

The packet generator is a C++ code generator that reads from one or multiple files. It implements a simple IDL described here.

The format of a packet file is XML. A packet file contains only one root tag, the <packet> tag. This in turn can contain tags, definitions or nothing. The root tag has one required attribute: ePacketType.

The simplest packet file would then be:

<packet ePacketType = "PAKCS_TEST">
</packet>

The packet tag can contain any of the following:

  • an element
  • a simple type definition
  • a complex type definition
  • an include (either from an external header file or another XML file)
  • a documentation Apart from the documentation, any other tag can be added as many times as required. The order of the tags doesn't matter but for the element tag. Its order will be reflected in the resulting generated code. Any other tag will be re-arranged to solve dependencies correctly. As so, the following packet structures will be the same:
<packet ePacketType = "PAKCS_TEST">
    <element/>
    <documentation/>
    <simpleType/>
    <element/>
</packet>
<packet ePacketType = "PAKCS_TEST">
    <documentation/>
    <element/>
    <element/>
    <simpleType/>
</packet>

Element tag

The element tag is the easiest tag to understand. It represents an element in the final buffer sent and/or received from the client. The elements has the following attributes:

  • type (required) the type of the element (with the required namespaces, an example would be std::string)
  • name (required) the name of the element (the getter will be get_name() and the setter will be set_name(), with the case respected)
  • default (optional, defaults to create) The default value when creating the packet. Can be one of create, none, a value. create means to let the C++ compile decide on the default for this type, otherwise set to the provided value. The none value is similar to the create value, but doesn't add it to the packet::create() parameter list. The a value option also does not add it to the parameter list.
  • occurs (optional, defaults to none) The number of time this element should be added to the buffer. It can be either a number or unbounded. if a number is provided, the element will effectively be a std::array, otherwise it will be a std::vector.
  • occursSize (optional, defaults to none) The size of the vector size. If set, the size will be set before the vector. Otherwise, it won't. Only useful for occurs="unbounded".
  • ref (optional, defaults false) Sets if the element should be passed by reference (the packet still makes a copy internally).
  • readWrite (optional, defaults to none) Specify the way this variable should be read and written. It should only be used in very specific scenarios, the default implied way should be good enough for all cases.
  • enum (optional, defaults to none) Specify the type of the enum. Should only be used if the enum is from an external C++ header file (If the enum is declared in XML, the generator is smart enough to find its type). Example:
<packet ePacketType = "PAKCS_TEST">
    <element name="a" type="uint8_t"/>
    <element name="b" type="uint8_t" occurs="unbounded" occursSize="uint8_t"/>
</packet>

Simple type tag

You can consider the simple type as being a struct or enum in C++. This type will be set in the buffer according to its restrictions. A simple type tag only has one attribute: name. Example:

<packet ePacketType = "PAKCS_TEST">
    <simpleType name="A"/>
</packet>

Restrictions

Restrictions are what make a simple type interesting. It restricts the input/output of the simple type based on an underlying type. Currently, four restrictions are implemented: enumeration, min value, max value, and length. The restriction tag has a single attribute: base which indicates the underlying base type. Please do not mix up the different restrictions (apart from min/max value) as the generator has not been designed to deal with that.

Enumerations

Enumeration members have a value attribute and can have an id attribute. If the id attribute is not set, the id will automatically be previous_id + 1, starting from 0. To declare an enum, the format is the following:

<packet ePacketType = "PAKCS_TEST">
    <simpleType name="MyEnum">
        <restriction base = "uint8_t">
            <enumeration value = "ENUM_1"/>
            <enumeration value = "ENUM_2" id = "42"/>
        </restriction>
    </simpleType>
</packet>

This will declare the following enum:

enum MyEnum : uint8_t {
    ENUM_1 = 0,
    ENUM_2 = 42,
};

Min/max value

A restriction on the value of an integer/float/double/(complex?). It'll return false when parsing in/out if the value read/written is lower/higher than the provided value. Example:

<packet ePacketType = "PAKCS_TEST">
    <simpleType name="MyValueBetween10And20">
        <restriction base = "uint8_t">
            <minValue value = "10"/>
            <maxValue value = "20"/>
        </restriction>
    </simpleType>
</packet>

Length

This will limit the length of a std container when writing/reading. Mostly used with strings to have an array of characters. Example:

<packet ePacketType = "PAKCS_TEST">
    <simpleType name="MyStringWith10Chars">
        <restriction base = "std::string">
            <length value = "10"/>
        </restriction>
    </simpleType>
</packet>

Complex type tag

A complex type is based on the same idea as a simple type, but instead of containing restrictions, it contains other types and/or elements in a sequence or a choice. A complex type can contain simple types, but also other complex types. There is no way for a complex type to contain itself (it wouldn't make much sense). The only attribute of a complex type is name. Example:

<packet ePacketType = "PAKCS_TEST">
    <complexType name="A"/>
</packet>

Sequence

A sequence is represented as a struct in C++. As such, element tags can be added to the sequence with all of the previously described attributes available. sequence and choice tags can also be added. There is a new attribute added as well: bits, which declares a bit field in the struct. The whole struct is packed, so no padding is added in between members. When a sequence is declared inside a choice tag, it is possible to mark the sequence as inline, which will effectively inline the struct inside the union. Example:

<packet ePacketType = "PAKCS_TEST">
    <complexType name="MySequence">
        <sequence>
            <element name="a" type="uint8_t"/>
            <element name="b" type="uint16_t"/>
        </sequence>
    </complexType>
</packet>

Can be represented in C++ as:

struct MySequence {
    uint8_t a;
    uint16_t b;
};

Example of an inlined sequence:

<packet ePacketType = "PAKCS_TEST">
    <complexType name="MyInlinedSequence">
        <choice>
            <sequence inline="true">
                <element name="a" type="uint8_t"/>
                <element name="b" type="uint8_t"/>
            </sequence>
            <element name="total" type="uint16_t"/>
        </choice>
    </complexType>
</packet>

Will generate the following C++:

union MyInlinedSequence {
    struct {
        uint8_t a;
        uint8_t b;
    } /* name omitted */;
    uint16_t total;
};

Choice

A choice is basically an union in C++. A choice can contain element tags as well as sequence and choice elements. Example:

<packet ePacketType = "PAKCS_TEST">
    <complexType name="MyChoice">
        <choice>
            <element name="a" type="uint16_t"/>
            <element name="b" type="uint16_t"/>
        </choice>
    </complexType>
</packet>

Will generate the following C++:

union MyChoice {
    uint16_t a;
    uint16_t b;
};

Include tag

The include tag is actually two tags. The first one include can include external header files (with the available boolean attribute system to use angled-brackets instead of double-quotes). The second one is includeXml which includes any other xml in the file. You can have non-packet xml files with multiple declarations of simpleType or complexType in it and include those common xmls into your packets to be able to reuse them. Only simpleType and complexType at the root level (and their own elements/includes) are taken into account when resolving names.

Documentation

For every tag you can add a tag documentation in it. The text available in the documentation tag will be set before the tag that it is attached to. It will be set in the C-style documentation in the header file of the generated code.

Clone this wiki locally