Add a class to handle RDE BEJ dictionary data

This class is used to store RDE BEJ dictionary data transmitted
through bios-bmc circular buffer interface.

Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Idf7726a9f4647885ede615229d507f233ffb13c5
diff --git a/include/rde/rde_dictionary_manager.hpp b/include/rde/rde_dictionary_manager.hpp
new file mode 100644
index 0000000..099ac24
--- /dev/null
+++ b/include/rde/rde_dictionary_manager.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <span>
+#include <unordered_map>
+#include <vector>
+
+namespace bios_bmc_smm_error_logger
+{
+namespace rde
+{
+
+/**
+ * @brief Resource ID for the annotation dictionary. The other entity
+ * communicating with the BMC (Eg: BIOS) should use the same resource ID for the
+ * annotation dictionary.
+ */
+constexpr uint32_t annotationResourceId = 0;
+
+/**
+ * @brief Holds an RDE BEJ dictionary entry.
+ */
+struct DictionaryEntry
+{
+    DictionaryEntry(bool valid, const std::span<const uint8_t> data) :
+        valid(valid), data(data.begin(), data.end())
+    {}
+    // True indicates that the dictionary data is ready to be used.
+    bool valid;
+    std::vector<uint8_t> data;
+};
+
+/**
+ * @brief Manages RDE BEJ dictionaries.
+ */
+class DictionaryManager
+{
+  public:
+    DictionaryManager();
+
+    /**
+     * @brief Starts a dictionary entry with the provided data.
+     *
+     * @param[in] resourceId - PDR resource id corresponding to the dictionary.
+     * @param[in] data - dictionary data.
+     */
+    void startDictionaryEntry(uint32_t resourceId,
+                              const std::span<const uint8_t> data);
+
+    /**
+     * @brief Set the dictionary valid status. Until this is called, dictionary
+     * data is considered to be incomplete for use.
+     *
+     * @param[in] resourceId - PDR resource id corresponding to the dictionary.
+     * @return true if successful.
+     */
+    bool markDataComplete(uint32_t resourceId);
+
+    /**
+     * @brief Add more dictionary data for an existing entry. Adding data to a
+     * completed dictionary will mark the dictionary as incomplete.
+     *
+     * @param[in] resourceId - PDR resource id corresponding to the dictionary.
+     * @param[in] data - dictionary data.
+     * @return true if successful.
+     */
+    bool addDictionaryData(uint32_t resourceId,
+                           const std::span<const uint8_t> data);
+
+    /**
+     * @brief Get a dictionary.
+     *
+     * @param[in] resourceId - PDR resource id corresponding to the dictionary.
+     * @return a pointer to the dictionary, if the dictionary is complete else
+     * std::nullopt.
+     */
+    std::optional<std::span<const uint8_t>> getDictionary(uint32_t resourceId);
+
+    /**
+     * @brief Get the annotation dictionary.
+     *
+     * @return a pointer to the annotation dictionary, if the dictionary is
+     * complete else std::nullopt.
+     */
+    std::optional<std::span<const uint8_t>> getAnnotationDictionary();
+
+    /**
+     * @brief Get the completed dictionary count.
+     *
+     * @return number of completed dictionaries available.
+     */
+    uint32_t getDictionaryCount();
+
+    /**
+     * @brief Invalidate all dictionaries.
+     */
+    void invalidateDictionaries();
+
+  private:
+    uint32_t validDictionaryCount;
+    std::unordered_map<uint32_t, std::unique_ptr<DictionaryEntry>> dictionaries;
+
+    /**
+     * @brief Set a dictionary entry to be invalid and reduce the valid
+     * dictionary count.
+     *
+     * @param[in] entry - A dictionary entry.
+     */
+    void invalidateDictionaryEntry(DictionaryEntry& entry);
+
+    /**
+     * @brief Set the dictionary entry valid flag and increase the valid
+     * dictionary count.
+     *
+     * @param[in] entry - A dictionary entry.
+     */
+    void validateDictionaryEntry(DictionaryEntry& entry);
+};
+
+} // namespace rde
+} // namespace bios_bmc_smm_error_logger