Add helper functions for BEJ dictionaries

Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: I50f2ccec155434639dfecd96193608cf6c5a1787
diff --git a/src/bej_dictionary.c b/src/bej_dictionary.c
new file mode 100644
index 0000000..a86720b
--- /dev/null
+++ b/src/bej_dictionary.c
@@ -0,0 +1,100 @@
+#include "bej_dictionary.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+
+/**
+ * @brief Get the index for a property offset. First property will be at index
+ * 0.
+ *
+ * @param[in] propertyOffset - a valid property offset.
+ * @return index of the property.
+ */
+static uint16_t bejGetPropertyEntryIndex(uint16_t propertyOffset)
+{
+    return (propertyOffset - bejDictGetPropertyHeadOffset()) /
+           sizeof(struct BejDictionaryProperty);
+}
+
+/**
+ * @brief  Validate a property offset.
+ *
+ * @param[in] propertyOffset - offset needed to be validated.
+ * @return true if propertyOffset is a valid offset.
+ */
+static bool bejValidatePropertyOffset(uint16_t propertyOffset)
+{
+    // propertyOffset should be greater than or equal to first property offset.
+    if (propertyOffset < bejDictGetPropertyHeadOffset())
+    {
+        fprintf(
+            stderr,
+            "Invalid property offset. Pointing to Dictionary header data\n");
+        return false;
+    }
+
+    // propertyOffset should be a multiple of sizeof(BejDictionaryProperty)
+    // starting from first property within the dictionary.
+    if ((propertyOffset - bejDictGetPropertyHeadOffset()) %
+        sizeof(struct BejDictionaryProperty))
+    {
+        fprintf(stderr, "Invalid property offset. Does not point to beginning "
+                        "of property\n");
+        return false;
+    }
+
+    return true;
+}
+
+uint16_t bejDictGetPropertyHeadOffset()
+{
+    // First property is present soon after the dictionary header.
+    return sizeof(struct BejDictionaryHeader);
+}
+
+uint16_t bejDictGetFirstAnnotatedPropertyOffset()
+{
+    // The first property available is the "Annotations" set which is the parent
+    // for all properties. Next immediate property is the first property we
+    // need.
+    return sizeof(struct BejDictionaryHeader) +
+           sizeof(struct BejDictionaryProperty);
+}
+
+int bejDictGetProperty(const uint8_t* dictionary,
+                       uint16_t startingPropertyOffset, uint16_t sequenceNumber,
+                       const struct BejDictionaryProperty** property)
+{
+    uint16_t propertyOffset = startingPropertyOffset;
+    const struct BejDictionaryHeader* header =
+        (const struct BejDictionaryHeader*)dictionary;
+
+    if (!bejValidatePropertyOffset(propertyOffset))
+    {
+        return bejErrorInvalidPropertyOffset;
+    }
+    uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
+
+    for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
+    {
+        const struct BejDictionaryProperty* p =
+            (const struct BejDictionaryProperty*)(dictionary + propertyOffset);
+        if (p->sequenceNumber == sequenceNumber)
+        {
+            *property = p;
+            return 0;
+        }
+        propertyOffset += sizeof(struct BejDictionaryProperty);
+    }
+    return bejErrorUnknownProperty;
+}
+
+const char* bejDictGetPropertyName(const uint8_t* dictionary,
+                                   uint16_t nameOffset, uint8_t nameLength)
+{
+    if (nameLength == 0)
+    {
+        return "";
+    }
+    return (const char*)(dictionary + nameOffset);
+}
diff --git a/src/meson.build b/src/meson.build
index 0d2703d..e8d9958 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,6 +1,7 @@
 libbej_lib = static_library(
   'libbej',
   'rde_common.c',
+  'bej_dictionary.c',
   include_directories : libbej_incs,
   implicit_include_directories: false
 )