Add more support to bej_tree API

This change adds bejString, bejReal and bejBoolean node types,
and also 2 new APIs, UpdateNodeFlags() and IsParentType().

Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: I94d36a63dd95893acd3517d30790c8fe71917989
diff --git a/include/libbej/bej_tree.h b/include/libbej/bej_tree.h
index 2539b00..8250e85 100644
--- a/include/libbej/bej_tree.h
+++ b/include/libbej/bej_tree.h
@@ -119,6 +119,35 @@
     };
 
     /**
+     * @brief bejString type property node.
+     */
+    struct RedfishPropertyLeafString
+    {
+        struct RedfishPropertyLeaf leaf;
+        const char* value;
+    };
+
+    /**
+     * @brief bejReal type property node.
+     */
+    struct RedfishPropertyLeafReal
+    {
+        struct RedfishPropertyLeaf leaf;
+        double value;
+        // bejReal representation of the value. Populated during bej encoding.
+        struct BejReal bejReal;
+    };
+
+    /**
+     * @brief bejBoolean type property node.
+     */
+    struct RedfishPropertyLeafBool
+    {
+        struct RedfishPropertyLeaf leaf;
+        bool value;
+    };
+
+    /**
      * @brief Initialize a bejSet type node.
      *
      * @param[in] node - pointer to a RedfishPropertyParent struct.
@@ -144,6 +173,14 @@
                                       const char* name);
 
     /**
+     * @brief Check if a node is a parent type node.
+     *
+     * @param node - node to be checked.
+     * @return true if the node is a parent type node.
+     */
+    bool bejTreeIsParentType(struct RedfishPropertyNode* node);
+
+    /**
      * @brief Add a bejInteger type node to a parent node.
      *
      * @param[in] parent - a pointer to an initialized parent struct.
@@ -177,6 +214,50 @@
                         const char* value);
 
     /**
+     * @brief Add a bejString type node to a parent node.
+     *
+     * @param[in] parent - a pointer to an initialized parent struct.
+     * @param[in] child - a pointer to an uninitialized bejString type node.
+     * @param[in] name - name of the bejString type property.
+     * @param[in] value - value of the bejString type property.
+     */
+    void bejTreeAddString(struct RedfishPropertyParent* parent,
+                          struct RedfishPropertyLeafString* child,
+                          const char* name, const char* value);
+
+    /**
+     * @brief Add a bejReal type node to a parent node.
+     *
+     * @param[in] parent - a pointer to an initialized parent struct.
+     * @param[in] child - a pointer to an uninitialized bejReal type node.
+     * @param[in] name - name of the bejReal type property.
+     * @param[in] value - value of the bejReal type property.
+     */
+    void bejTreeAddReal(struct RedfishPropertyParent* parent,
+                        struct RedfishPropertyLeafReal* child, const char* name,
+                        double value);
+
+    /**
+     * @brief Set a new value in bejReal type node.
+     *
+     * @param[in] node - initialized bejReal type node.
+     * @param[in] newValue - new double value.
+     */
+    void bejTreeSetReal(struct RedfishPropertyLeafReal* node, double newValue);
+
+    /**
+     * @brief Add a bejBoolean type node to a parent node.
+     *
+     * @param[in] parent - a pointer to an initialized parent struct.
+     * @param[in] child - a pointer to an uninitialized bejBoolean type node.
+     * @param[in] name - name of the bejBoolean type property.
+     * @param[in] value - value of the bejBoolean type property.
+     */
+    void bejTreeAddBool(struct RedfishPropertyParent* parent,
+                        struct RedfishPropertyLeafBool* child, const char* name,
+                        bool value);
+
+    /**
      * @brief Link a node to its parent.
      *
      * @param[in] parent  - a pointer to an initialized parent struct.
@@ -185,6 +266,18 @@
     void bejTreeLinkChildToParent(struct RedfishPropertyParent* parent,
                                   void* child);
 
+    /**
+     * @brief Set Bej format flags of a node.
+     *
+     * @param node - an initialized node.
+     * @param deferredBinding - set deferred binding flag.
+     * @param readOnlyProperty - set read only property flag.
+     * @param nullableProperty - set nullable property flag.
+     */
+    void bejTreeUpdateNodeFlags(struct RedfishPropertyNode* node,
+                                bool deferredBinding, bool readOnlyProperty,
+                                bool nullableProperty);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/bej_tree.c b/src/bej_tree.c
index 5aeda4f..6bec216 100644
--- a/src/bej_tree.c
+++ b/src/bej_tree.c
@@ -30,6 +30,13 @@
     bejTreeInitParent(node, name, bejPropertyAnnotation);
 }
 
+bool bejTreeIsParentType(struct RedfishPropertyNode* node)
+{
+    return node->format.principalDataType == bejSet ||
+           node->format.principalDataType == bejArray ||
+           node->format.principalDataType == bejPropertyAnnotation;
+}
+
 static void bejTreeInitChildNode(struct RedfishPropertyLeaf* node,
                                  const char* name,
                                  enum BejPrincipalDataType type)
@@ -65,6 +72,38 @@
     bejTreeLinkChildToParent(parent, child);
 }
 
+void bejTreeAddString(struct RedfishPropertyParent* parent,
+                      struct RedfishPropertyLeafString* child, const char* name,
+                      const char* value)
+{
+    bejTreeInitChildNode((struct RedfishPropertyLeaf*)child, name, bejString);
+    child->value = value;
+    bejTreeLinkChildToParent(parent, child);
+}
+
+void bejTreeAddReal(struct RedfishPropertyParent* parent,
+                    struct RedfishPropertyLeafReal* child, const char* name,
+                    double value)
+{
+    bejTreeInitChildNode((struct RedfishPropertyLeaf*)child, name, bejReal);
+    child->value = value;
+    bejTreeLinkChildToParent(parent, child);
+}
+
+void bejTreeSetReal(struct RedfishPropertyLeafReal* node, double newValue)
+{
+    node->value = newValue;
+}
+
+void bejTreeAddBool(struct RedfishPropertyParent* parent,
+                    struct RedfishPropertyLeafBool* child, const char* name,
+                    bool value)
+{
+    bejTreeInitChildNode((struct RedfishPropertyLeaf*)child, name, bejBoolean);
+    child->value = value;
+    bejTreeLinkChildToParent(parent, child);
+}
+
 void bejTreeLinkChildToParent(struct RedfishPropertyParent* parent, void* child)
 {
     // A new node is added at the end of the list.
@@ -80,3 +119,12 @@
     parent->lastChild = child;
     parent->nChildren += 1;
 }
+
+void bejTreeUpdateNodeFlags(struct RedfishPropertyNode* node,
+                            bool deferredBinding, bool readOnlyProperty,
+                            bool nullableProperty)
+{
+    node->format.deferredBinding = deferredBinding;
+    node->format.readOnlyProperty = readOnlyProperty;
+    node->format.nullableProperty = nullableProperty;
+}
diff --git a/test/bej_tree_test.cpp b/test/bej_tree_test.cpp
index 82d763b..74ffb92 100644
--- a/test/bej_tree_test.cpp
+++ b/test/bej_tree_test.cpp
@@ -134,4 +134,90 @@
     EXPECT_THAT(child.value, enumValue);
 }
 
+TEST(BejTreeTest, AddString)
+{
+    const char* name = "SomeProperty";
+    const char* stringValue = "StringValue";
+    struct RedfishPropertyParent parent;
+    struct RedfishPropertyLeafString child;
+
+    bejTreeInitSet(&parent, nullptr);
+    bejTreeAddString(&parent, &child, name, stringValue);
+
+    EXPECT_THAT(child.leaf.nodeAttr.name, name);
+    EXPECT_THAT(child.leaf.nodeAttr.format.principalDataType, bejString);
+    EXPECT_THAT(child.leaf.nodeAttr.format.deferredBinding, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.readOnlyProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.nullableProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.sibling, nullptr);
+    EXPECT_THAT(child.value, stringValue);
+}
+
+TEST(BejTreeTest, AddReal)
+{
+    const char* name = "SomeProperty";
+    double value = 10.50;
+    struct RedfishPropertyParent parent;
+    struct RedfishPropertyLeafReal child;
+
+    bejTreeInitSet(&parent, nullptr);
+    bejTreeAddReal(&parent, &child, name, value);
+
+    EXPECT_THAT(child.leaf.nodeAttr.name, name);
+    EXPECT_THAT(child.leaf.nodeAttr.format.principalDataType, bejReal);
+    EXPECT_THAT(child.leaf.nodeAttr.format.deferredBinding, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.readOnlyProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.nullableProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.sibling, nullptr);
+    EXPECT_THAT(child.value, value);
+}
+
+TEST(BejTreeTest, AddBool)
+{
+    const char* name = "SomeProperty";
+    bool value = true;
+    struct RedfishPropertyParent parent;
+    struct RedfishPropertyLeafBool child;
+
+    bejTreeInitSet(&parent, nullptr);
+    bejTreeAddBool(&parent, &child, name, value);
+
+    EXPECT_THAT(child.leaf.nodeAttr.name, name);
+    EXPECT_THAT(child.leaf.nodeAttr.format.principalDataType, bejBoolean);
+    EXPECT_THAT(child.leaf.nodeAttr.format.deferredBinding, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.readOnlyProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.format.nullableProperty, 0);
+    EXPECT_THAT(child.leaf.nodeAttr.sibling, nullptr);
+    EXPECT_THAT(child.value, value);
+}
+
+TEST(BejTreeTest, NodeFlags)
+{
+    struct RedfishPropertyParent parent;
+    bejTreeInitSet(&parent, nullptr);
+    EXPECT_THAT(parent.nodeAttr.format.deferredBinding, 0);
+    EXPECT_THAT(parent.nodeAttr.format.readOnlyProperty, 0);
+    EXPECT_THAT(parent.nodeAttr.format.nullableProperty, 0);
+
+    bejTreeUpdateNodeFlags(&parent.nodeAttr, true, true, true);
+    EXPECT_THAT(parent.nodeAttr.format.deferredBinding, 1);
+    EXPECT_THAT(parent.nodeAttr.format.readOnlyProperty, 1);
+    EXPECT_THAT(parent.nodeAttr.format.nullableProperty, 1);
+}
+
+TEST(BejTreeTest, NodeType)
+{
+    struct RedfishPropertyParent parent;
+    struct RedfishPropertyLeafBool child1;
+    struct RedfishPropertyLeafReal child2;
+
+    bejTreeInitSet(&parent, nullptr);
+    bejTreeAddBool(&parent, &child1, nullptr, true);
+    bejTreeAddReal(&parent, &child2, nullptr, 10.5);
+
+    EXPECT_THAT(bejTreeIsParentType(&parent.nodeAttr), true);
+    EXPECT_THAT(bejTreeIsParentType(&child1.leaf.nodeAttr), false);
+    EXPECT_THAT(bejTreeIsParentType(&child2.leaf.nodeAttr), false);
+}
+
 } // namespace libbej