Add basic template code for BEJ decoder core

This describes the interfaces we are using for the BEJ decoding.

I did not include data type decoding code here to keep the code size
smaller for this review. I will be adding different data type decoding
in the comming CLs.

I will submit unit tests for review once all the necessary data type
decoding changes are submitted.

Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Icbc5c7780da21ba76ae0eaa56ad84dd10360cfc4
diff --git a/include/bej_decoder_core.h b/include/bej_decoder_core.h
new file mode 100644
index 0000000..2c7f066
--- /dev/null
+++ b/include/bej_decoder_core.h
@@ -0,0 +1,223 @@
+#pragma once
+
+#include "rde_common.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**
+     * @brief Indicates whether a new BEJ section falls inside a BEJ array or a
+     * BEJ set or none of those.
+     */
+    enum BejSectionType
+    {
+        bejSectionNoType,
+        bejSectionSet,
+        bejSectionArray,
+    };
+
+    /**
+     * @brief These stack entries are needed to implement the decoding
+     * non-recursively.
+     */
+    struct BejStackProperty
+    {
+        // Indicates whether we are inside an array or a set or an annotation.
+        enum BejSectionType sectionType;
+        // Indicate whether we have property names for properties.
+        bool addPropertyName;
+        // Offset to the parent property in schema dictionary.
+        uint16_t mainDictPropOffset;
+        // Offset to the parent property in annotation dictionary.
+        uint16_t annoDictPropOffset;
+        // Offset to the end of the array or set or annotation.
+        uint32_t streamEndOffset;
+    };
+
+    struct BejDictionaries
+    {
+        const uint8_t* schemaDictionary;
+        const uint8_t* annotationDictionary;
+        const uint8_t* errorDictionary;
+    };
+
+    /**
+     * @brief Holds the information related to the current bejTuple being
+     * decoded.
+     */
+    struct BejDecoderStates
+    {
+        bool addPropertyName;
+        uint16_t mainDictPropOffset;
+        uint16_t annoDictPropOffset;
+        uint32_t encodedStreamOffset;
+        const uint8_t* encodedSubStream;
+    };
+
+    /**
+     * @brief Callbacks for decoded data.
+     *
+     * dataPtr in the callback functions can be used for extra arguments.
+     */
+    struct BejDecodedCallback
+    {
+        /**
+         * @brief Calls when a Set is detected.
+         */
+        int (*callbackSetStart)(const char* propertyName, void* dataPtr);
+
+        /**
+         * @brief Calls when an end of a Set is found.
+         */
+        int (*callbackSetEnd)(void* dataPtr);
+
+        /**
+         * @brief Calls when an array is detected.
+         */
+        int (*callbackArrayStart)(const char* propertyName, void* dataPtr);
+
+        /**
+         * @brief Calls when an end of an array is found.
+         */
+        int (*callbackArrayEnd)(void* dataPtr);
+
+        /**
+         * @brief Calls after a property is finished unless this is the last
+         * property in a Set or an array. In that case appropriate
+         * callbackSetEnd or callbackArrayEnd will be called.
+         */
+        int (*callbackPropertyEnd)(void* dataPtr);
+
+        /**
+         * @brief Calls when a Null property is found or the property length is
+         * 0.
+         */
+        int (*callbackNull)(const char* propertyName, void* dataPtr);
+
+        /**
+         * @brief Calls when an Integer property is found.
+         */
+        int (*callbackInteger)(const char* propertyName, uint64_t value,
+                               void* dataPtr);
+
+        /**
+         * @brief Calls when an Enum property is found.
+         */
+        int (*callbackEnum)(const char* propertyName, const char* value,
+                            void* dataPtr);
+
+        /**
+         * @brief Calls when a String property is found.
+         */
+        int (*callbackString)(const char* propertyName, const char* value,
+                              void* dataPtr);
+
+        /**
+         * @brief Calls when a Real value property is found.
+         */
+        int (*callbackReal)(const char* propertyName,
+                            const struct BejReal* value, void* dataPtr);
+
+        /**
+         * @brief Calls when a Bool property is found.
+         */
+        int (*callbackBool)(const char* propertyName, bool value,
+                            void* dataPtr);
+
+        /**
+         * @brief Calls when an Annotated property is found.
+         */
+        int (*callbackAnnotation)(const char* propertyName, void* dataPtr);
+
+        /**
+         * @brief Calls when a read only property is found.
+         */
+        int (*callbackReadonlyProperty)(uint32_t sequenceNumber, void* dataPtr);
+    };
+
+    /**
+     * @brief Stack for holding BejStackProperty types. Decoder core is not
+     * responsible for creating or deleting stack memory. User of the decoder
+     * core is responsible for creating and deleting stack memory.
+     *
+     * dataPtr in the callback functions can be used for extra arguments.
+     */
+    struct BejStackCallback
+    {
+        /**
+         * @brief Return true if the stack is empty.
+         */
+        bool (*stackEmpty)(void* dataPtr);
+
+        /**
+         * @brief View the object at the top of the stack. If the stack is
+         * empty, this will return NULL.
+         */
+        const struct BejStackProperty* (*stackPeek)(void* dataPtr);
+
+        /**
+         * @brief Removes the top most object from the stack. Client of the
+         * decoder core is responsible for destroying the memory for the removed
+         * object.
+         */
+        void (*stackPop)(void* dataPtr);
+
+        /**
+         * @brief Push an object into the stack. Returns 0 if the operation is
+         * successfull. Client of the decoder core is responsible for allocating
+         * memory for the new object.
+         */
+        int (*stackPush)(const struct BejStackProperty* const property,
+                         void* dataPtr);
+    };
+
+    /**
+     * @brief Used to pass parameters to BEJ decoding local functions.
+     */
+    struct BejHandleTypeFuncParam
+    {
+        struct BejDecoderStates state;
+        struct BejSFLV sflv;
+        const uint8_t* mainDictionary;
+        const uint8_t* annotDictionary;
+        const struct BejDecodedCallback* decodedCallback;
+        const struct BejStackCallback* stackCallback;
+        void* callbacksDataPtr;
+        void* stackDataPtr;
+    };
+
+    /**
+     * @brief Decodes a PLDM block. Maximum encoded stream size the decoder
+     * supports is 32bits.
+     *
+     * @param[in] dictionaries - dictionaries needed for decoding.
+     * @param[in] encodedPldmBlock - encoded PLDM block.
+     * @param[in] blockLength - length of the PLDM block.
+     * @param[in] stackCallback - callbacks for stack handlers. callbacks in
+     * stackCallback struct should be set to valid functions.
+     * @param[in] decodedCallback - callbacks for extracting decoded
+     * properties. callbacks in decodedCallback struct should be set to
+     * NULL or valid functions.
+     * @param[in] callbacksDataPtr - data pointer to pass to decoded callbacks.
+     * This can be used pass additional data.
+     * @param[in] stackDataPtr - data pointer to pass to stack callbacks. This
+     * can be used pass additional data.
+     *
+     * @return 0 if successful.
+     */
+    int bejDecodePldmBlock(const struct BejDictionaries* dictionaries,
+                           const uint8_t* encodedPldmBlock,
+                           uint32_t blockLength,
+                           const struct BejStackCallback* stackCallback,
+                           const struct BejDecodedCallback* decodedCallback,
+                           void* callbacksDataPtr, void* stackDataPtr);
+
+#ifdef __cplusplus
+}
+#endif