1 #pragma once
2 
3 #include "bej_common.h"
4 
5 #include <stdbool.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #ifdef __cplusplus
10 extern "C"
11 {
12 #endif
13 
14 /**
15  * @brief Indicates whether a new BEJ section falls inside a BEJ array or a
16  * BEJ set or none of those.
17  */
18 enum BejSectionType
19 {
20     bejSectionNoType,
21     bejSectionSet,
22     bejSectionArray,
23 };
24 
25 /**
26  * @brief These stack entries are needed to implement the decoding
27  * non-recursively.
28  */
29 struct BejStackProperty
30 {
31     // Indicates whether we are inside an array or a set or an annotation.
32     enum BejSectionType sectionType;
33     // Indicate whether we have property names for properties.
34     bool addPropertyName;
35     // Offset to the parent property in schema dictionary.
36     uint16_t mainDictPropOffset;
37     // Offset to the parent property in annotation dictionary.
38     uint16_t annoDictPropOffset;
39     // Offset to the end of the array or set or annotation.
40     uint32_t streamEndOffset;
41 };
42 
43 /**
44  * @brief Holds the information related to the current bejTuple being
45  * decoded.
46  */
47 struct BejDecoderStates
48 {
49     bool addPropertyName;
50     uint16_t mainDictPropOffset;
51     uint16_t annoDictPropOffset;
52     uint32_t encodedStreamOffset;
53     const uint8_t* encodedSubStream;
54 };
55 
56 /**
57  * @brief Callbacks for decoded data.
58  *
59  * dataPtr in the callback functions can be used for extra arguments.
60  */
61 struct BejDecodedCallback
62 {
63     /**
64      * @brief Calls when a Set is detected.
65      */
66     int (*callbackSetStart)(const char* propertyName, void* dataPtr);
67 
68     /**
69      * @brief Calls when an end of a Set is found.
70      */
71     int (*callbackSetEnd)(void* dataPtr);
72 
73     /**
74      * @brief Calls when an array is detected.
75      */
76     int (*callbackArrayStart)(const char* propertyName, void* dataPtr);
77 
78     /**
79      * @brief Calls when an end of an array is found.
80      */
81     int (*callbackArrayEnd)(void* dataPtr);
82 
83     /**
84      * @brief Calls after a property is finished unless this is the last
85      * property in a Set or an array. In that case appropriate
86      * callbackSetEnd or callbackArrayEnd will be called.
87      */
88     int (*callbackPropertyEnd)(void* dataPtr);
89 
90     /**
91      * @brief Calls when a Null property is found or the property length is
92      * 0.
93      */
94     int (*callbackNull)(const char* propertyName, void* dataPtr);
95 
96     /**
97      * @brief Calls when an Integer property is found.
98      */
99     int (*callbackInteger)(const char* propertyName, int64_t value,
100                            void* dataPtr);
101 
102     /**
103      * @brief Calls when an Enum property is found.
104      */
105     int (*callbackEnum)(const char* propertyName, const char* value,
106                         void* dataPtr);
107 
108     /**
109      * @brief Calls when a String property is found.
110      */
111     int (*callbackString)(const char* propertyName, const char* value,
112                           void* dataPtr);
113 
114     /**
115      * @brief Calls when a Real value property is found.
116      */
117     int (*callbackReal)(const char* propertyName, const struct BejReal* value,
118                         void* dataPtr);
119 
120     /**
121      * @brief Calls when a Bool property is found.
122      */
123     int (*callbackBool)(const char* propertyName, bool value, void* dataPtr);
124 
125     /**
126      * @brief Calls when an Annotated property is found.
127      */
128     int (*callbackAnnotation)(const char* propertyName, void* dataPtr);
129 
130     /**
131      * @brief Calls when a read only property is found.
132      */
133     int (*callbackReadonlyProperty)(uint32_t sequenceNumber, void* dataPtr);
134 };
135 
136 /**
137  * @brief Stack for holding BejStackProperty types. Decoder core is not
138  * responsible for creating or deleting stack memory. User of the decoder
139  * core is responsible for creating and deleting stack memory.
140  *
141  * dataPtr in the callback functions can be used for extra arguments.
142  */
143 struct BejStackCallback
144 {
145     /**
146      * @brief Return true if the stack is empty.
147      */
148     bool (*stackEmpty)(void* dataPtr);
149 
150     /**
151      * @brief View the object at the top of the stack. If the stack is
152      * empty, this will return NULL.
153      */
154     const struct BejStackProperty* (*stackPeek)(void* dataPtr);
155 
156     /**
157      * @brief Removes the top most object from the stack. Client of the
158      * decoder core is responsible for destroying the memory for the removed
159      * object.
160      */
161     void (*stackPop)(void* dataPtr);
162 
163     /**
164      * @brief Push an object into the stack. Returns 0 if the operation is
165      * successfull. Client of the decoder core is responsible for allocating
166      * memory for the new object.
167      */
168     int (*stackPush)(const struct BejStackProperty* const property,
169                      void* dataPtr);
170 };
171 
172 /**
173  * @brief Used to pass parameters to BEJ decoding local functions.
174  */
175 struct BejHandleTypeFuncParam
176 {
177     struct BejDecoderStates state;
178     struct BejSFLV sflv;
179     const uint8_t* mainDictionary;
180     const uint8_t* annotDictionary;
181     const struct BejDecodedCallback* decodedCallback;
182     const struct BejStackCallback* stackCallback;
183     void* callbacksDataPtr;
184     void* stackDataPtr;
185 };
186 
187 /**
188  * @brief Decodes a PLDM block. Maximum encoded stream size the decoder
189  * supports is 32bits.
190  *
191  * @param[in] dictionaries - dictionaries needed for decoding.
192  * @param[in] encodedPldmBlock - encoded PLDM block.
193  * @param[in] blockLength - length of the PLDM block.
194  * @param[in] stackCallback - callbacks for stack handlers. callbacks in
195  * stackCallback struct should be set to valid functions.
196  * @param[in] decodedCallback - callbacks for extracting decoded
197  * properties. callbacks in decodedCallback struct should be set to
198  * NULL or valid functions.
199  * @param[in] callbacksDataPtr - data pointer to pass to decoded callbacks.
200  * This can be used pass additional data.
201  * @param[in] stackDataPtr - data pointer to pass to stack callbacks. This
202  * can be used pass additional data.
203  *
204  * @return 0 if successful.
205  */
206 int bejDecodePldmBlock(const struct BejDictionaries* dictionaries,
207                        const uint8_t* encodedPldmBlock, uint32_t blockLength,
208                        const struct BejStackCallback* stackCallback,
209                        const struct BejDecodedCallback* decodedCallback,
210                        void* callbacksDataPtr, void* stackDataPtr);
211 
212 #ifdef __cplusplus
213 }
214 #endif
215