1 #pragma once
2 
3 #include "stream.hpp"
4 
5 #include <cstdint>
6 
7 namespace attn
8 {
9 namespace pel
10 {
11 
12 /**
13  * @class SectionHeader
14  *
15  * @brief This 8-byte header is at the start of every PEL section.
16  *
17  * |--------+------------+------------+-----------+------------|
18  * | length | byte0      | byte1      | byte2     | byte3      |
19  * |--------+------------+------------+-----------+------------|
20  * | 4      | Section ID              | Section Length         |
21  * |--------+------------+-------------------------------------|
22  * | 4      | Version    | Sub-type   | Component ID           |
23  * |--------+--------------------------------------------------|
24  *
25  * Section ID:
26  * A two-ASCII character field which uniquely identifies the type of section.
27  *
28  * Section length:
29  * Length in bytes of the section, including the entire section header.
30  *
31  * Section Version:
32  * A one byte integer intended to identify differences in header structures.
33  *
34  * Section sub-type:
35  * Optional. Additional identifier describing the section.
36  *
37  * Component IDs:
38  * Optional. By convention the creator's component ID is placed in the
39  * component ID field of the Private Header and the committing component
40  * ID is placed in the component ID field of the User Header.
41  */
42 struct SectionHeader
43 {
44   public:
45     /**
46      * @brief Constructor
47      */
48     SectionHeader() : id(0), size(0), version(0), subType(0), componentID(0) {}
49 
50     /**
51      * @brief Constructor
52      *
53      * @param[in] id - the ID field
54      * @param[in] size - the size field
55      * @param[in] version - the version field
56      * @param[in] subType - the sub-type field
57      * @param[in] componentID - the component ID field
58      */
59     SectionHeader(uint16_t id, uint16_t size, uint8_t version, uint8_t subType,
60                   uint16_t componentID) :
61         id(id),
62         size(size), version(version), subType(subType), componentID(componentID)
63     {}
64 
65     /**
66      * @brief A two character ASCII field which identifies the section type.
67      */
68     uint16_t id;
69 
70     /**
71      * @brief The size of the section in bytes, including this section header.
72      */
73     uint16_t size;
74 
75     /**
76      * @brief The section format version.
77      */
78     uint8_t version;
79 
80     /**
81      * @brief The section sub-type.
82      */
83     uint8_t subType;
84 
85     /**
86      * @brief The component ID, which has various meanings depending on the
87      * section.
88      */
89     uint16_t componentID;
90 
91     /**
92      * @brief Returns the size of header when flattened into a PEL.
93      *
94      * @return size_t - the size of the header
95      */
96     static constexpr size_t flattenedSize()
97     {
98         return sizeof(id) + sizeof(size) + sizeof(version) + sizeof(subType) +
99                sizeof(componentID);
100     }
101 };
102 
103 /**
104  * @brief Stream extraction operator for the SectionHeader
105  *
106  * @param[in] s - the stream
107  * @param[out] header - the SectionHeader object
108  */
109 inline Stream& operator>>(Stream& s, SectionHeader& header)
110 {
111     s >> header.id >> header.size >> header.version >> header.subType >>
112         header.componentID;
113     return s;
114 }
115 
116 /**
117  * @brief Stream insertion operator for the section header
118  *
119  * @param[out] s - the stream
120  * @param[in] header - the SectionHeader object
121  */
122 inline Stream& operator<<(Stream& s, const SectionHeader& header)
123 {
124     s << header.id << header.size << header.version << header.subType
125       << header.componentID;
126     return s;
127 }
128 
129 } // namespace pel
130 } // namespace attn
131