From b371cbc40fbac42844f2de5a5a745e97c495f572 Mon Sep 17 00:00:00 2001
From: Dmitri Pal <dpal@redhat.com>
Date: Tue, 4 Dec 2012 19:21:03 -0500
Subject: [PATCH 03/10] [INI] Merge and serialize comments

Patch adds ability to combine two different comments into one.
It includes changes to the comment API, header file and unit test.
It also fixes an invalid free in one of the error cases.
---
 ini/ini_comment.c    |  107 +++++++++++++++++++++++++++++++++++++++++-
 ini/ini_comment.h    |   13 +++++
 ini/ini_comment_ut.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 246 insertions(+), 2 deletions(-)

diff --git a/ini/ini_comment.c b/ini/ini_comment.c
index a767a659ee13e1c6342730fd78a5c356c86541c2..ecfdbc5270b46af72f1b23e40f57ae3660190a7b 100644
--- a/ini/ini_comment.c
+++ b/ini/ini_comment.c
@@ -28,6 +28,7 @@
 #include "ref_array.h"
 #include "simplebuffer.h"
 #include "ini_comment.h"
+#include "ini_defines.h"
 
 /* The lines will increment in this number */
 #define INI_COMMENT_BLOCK 10
@@ -339,7 +340,7 @@ static int ini_comment_modify(struct ini_comment *ic,
         error = ref_array_append(ic->ra, (void *)&elem);
         if (error) {
             TRACE_ERROR_NUMBER("Failed to append line to an array", error);
-            free(elem);
+            simplebuffer_free(elem);
             return error;
         }
 
@@ -654,6 +655,110 @@ int ini_comment_swap(struct ini_comment *ic,
     return error;
 }
 
+/* Add one comment to another */
+int ini_comment_add(struct ini_comment *ic_to_add,
+                    struct ini_comment *ic)
+{
+    int error = EOK;
+    struct simplebuffer *sb = NULL;
+    struct simplebuffer *sb_new = NULL;
+    void *res = NULL;
+    uint32_t len = 0;
+    int i;
+
+    TRACE_FLOW_ENTRY();
+
+    len = ref_array_len(ic_to_add->ra);
+
+    for (i = 0; i< len; i++) {
+
+        /* Get data element */
+        res = ref_array_get(ic_to_add->ra, i, (void *)(&sb));
+        if (!res) {
+            TRACE_ERROR_NUMBER("Failed to get comment element", error);
+            return error;
+        }
+
+        /* Create a storage a for a copy */
+        error = simplebuffer_alloc(&sb_new);
+        if (error) {
+            TRACE_ERROR_NUMBER("Allocate buffer for the comment", error);
+            return error;
+        }
+
+        /* Copy actual data */
+        error = simplebuffer_add_str(sb_new,
+                                     (const char *)simplebuffer_get_buf(sb),
+                                     simplebuffer_get_len(sb),
+                                     INI_COMMENT_LEN);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to append line to an array", error);
+            simplebuffer_free(sb_new);
+            return error;
+        }
+
+        /* Append it to the array */
+        error = ref_array_append(ic->ra, (void *)&sb_new);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to append element to an array", error);
+            simplebuffer_free(sb_new);
+            return error;
+        }
+    }
+
+    TRACE_FLOW_EXIT();
+    return error;
+}
+
+/* Serialize comment */
+int ini_comment_serialize (struct ini_comment *ic,
+                           struct simplebuffer *sbobj) 
+{
+    int error = EOK;
+    uint32_t num = 0;
+    uint32_t i = 0;
+    uint32_t len = 0;
+    char *commentline = NULL;
+
+    TRACE_FLOW_ENTRY();
+
+    /* Get number of lines in the comment */
+    error = ini_comment_get_numlines(ic, &num);
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to get number of lines", error);
+        return error;
+    }
+
+    for (i = 0; i < num; i++) {
+
+        len = 0;
+        commentline = NULL;
+
+        error = ini_comment_get_line(ic, i, &commentline, &len);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to get line", errno);
+            return error;
+        }
+
+        error = simplebuffer_add_raw(sbobj,
+                                     commentline,
+                                     len,
+                                     INI_VALUE_BLOCK);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to add comment", error);
+            return error;
+        }
+
+        error = simplebuffer_add_cr(sbobj);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to add CR", error);
+            return error;
+        }
+    }
+
+    TRACE_FLOW_EXIT();
+    return error;
+}
 
 /* Internal function to print comment */
 void ini_comment_print(struct ini_comment *ic, FILE *file)
diff --git a/ini/ini_comment.h b/ini/ini_comment.h
index 947209c179727455adedc30f01393cecfa18fdae..dfb26392bc1e0cb50a5f3d1a81a32ce5ed462c0a 100644
--- a/ini/ini_comment.h
+++ b/ini/ini_comment.h
@@ -24,6 +24,7 @@
 
 #include <stdint.h>
 #include <stdio.h>
+#include "simplebuffer.h"
 
 #ifndef EOK
 #define EOK 0
@@ -131,6 +132,18 @@ int ini_comment_copy(struct ini_comment *ic,
                      struct ini_comment **ic_copy);
 
 /**
+ * Add one comment to another
+ */
+int ini_comment_add(struct ini_comment *ic_to_add,
+                    struct ini_comment *ic);
+
+/**
+ * Serialize comment
+ */
+int ini_comment_serialize(struct ini_comment *ic,
+                          struct simplebuffer *sbobj);
+
+/**
  * Internal function to print comment
  */
 void ini_comment_print(struct ini_comment *ic, FILE *file);
diff --git a/ini/ini_comment_ut.c b/ini/ini_comment_ut.c
index 56474f5a5dfaffb51996895024462e93cffff08e..3d017908aa0c785735889f58e816942192bf4727 100644
--- a/ini/ini_comment_ut.c
+++ b/ini/ini_comment_ut.c
@@ -223,7 +223,7 @@ int copy_test(void)
             printf("Copy: %s\n", line_copy);
             ini_comment_destroy(ic);
             ini_comment_destroy(ic_copy);
-            return error;
+            return -1;
         }
     }
 
@@ -233,12 +233,138 @@ int copy_test(void)
     return error;
 }
 
+int add_test(void)
+{
+    int error = EOK;
+    struct ini_comment *ic = NULL;
+    struct ini_comment *ic_to_add = NULL;
+    struct ini_comment *ic_cmp = NULL;
+    uint32_t i, num1 = 0, num2 = 0;
+    char *line1 = NULL;
+    char *line2 = NULL;
+
+
+    INIOUT(printf("\n\nAdd test\n\n"));
+
+    if ((error = ini_comment_create(&ic)) ||
+        (error = ini_comment_build(ic, ";Line 0")) ||
+        (error = ini_comment_build(ic, ";Line 1")) ||
+        (error = ini_comment_build(ic, ";Line 2"))) {
+        printf("Failed to create comment object %d\n",
+               error);
+        ini_comment_destroy(ic);
+        return error;
+    }
+
+    INIOUT(printf("<==== Comment ====>\n"));
+    INIOUT(ini_comment_print(ic, stdout));
+    INIOUT(printf("<=================>\n"));
+
+    if ((error = ini_comment_create(&ic_to_add)) ||
+        (error = ini_comment_build(ic_to_add, ";Line 3")) ||
+        (error = ini_comment_build(ic_to_add, ";Line 4")) ||
+        (error = ini_comment_build(ic_to_add, ";Line 5"))) {
+        printf("Failed to create comment object %d\n",
+               error);
+        ini_comment_destroy(ic);
+        return error;
+    }
+
+    INIOUT(printf("<==== Comment To Add ====>\n"));
+    INIOUT(ini_comment_print(ic_to_add, stdout));
+    INIOUT(printf("<=================>\n"));
+
+    error = ini_comment_add(ic_to_add, ic);
+    if (error) {
+        printf("Failed to add one comment to another.\n");
+        ini_comment_destroy(ic);
+        ini_comment_destroy(ic_to_add);
+        return error;
+    }
+
+    INIOUT(printf("<==== Merged Comment ====>\n"));
+    INIOUT(ini_comment_print(ic, stdout));
+    INIOUT(printf("<=================>\n"));
+
+    if ((error = ini_comment_create(&ic_cmp)) ||
+        (error = ini_comment_build(ic_cmp, ";Line 0")) ||
+        (error = ini_comment_build(ic_cmp, ";Line 1")) ||
+        (error = ini_comment_build(ic_cmp, ";Line 2")) ||
+        (error = ini_comment_build(ic_cmp, ";Line 3")) ||
+        (error = ini_comment_build(ic_cmp, ";Line 4")) ||
+        (error = ini_comment_build(ic_cmp, ";Line 5"))) {
+        printf("Failed to create comment object %d\n",
+               error);
+        ini_comment_destroy(ic_cmp);
+        return error;
+    }
+
+    ini_comment_destroy(ic_to_add);
+
+    error = ini_comment_get_numlines(ic, &num1);
+    if (error) {
+        printf("Failed to get number of lines.\n");
+        ini_comment_destroy(ic);
+        ini_comment_destroy(ic_cmp);
+        return error;
+    }
+
+    error = ini_comment_get_numlines(ic, &num2);
+    if (error) {
+        printf("Failed to get number of lines.\n");
+        ini_comment_destroy(ic);
+        ini_comment_destroy(ic_cmp);
+        return error;
+    }
+
+    if (num1 != num2) {
+        printf("Sizes are different.\n");
+        ini_comment_destroy(ic);
+        ini_comment_destroy(ic_cmp);
+        return -1;
+    }
+
+    for (i = 0; i < num1; i++) {
+        line1 = NULL;
+        error = ini_comment_get_line(ic, i, &line1, NULL);
+        if (error) {
+            printf("Failed to get line.\n");
+            ini_comment_destroy(ic);
+            ini_comment_destroy(ic_cmp);
+            return error;
+        }
+        line2 = NULL;
+        error = ini_comment_get_line(ic_cmp, i, &line2, NULL);
+        if (error) {
+            printf("Failed to get line.\n");
+            ini_comment_destroy(ic);
+            ini_comment_destroy(ic_cmp);
+            return error;
+        }
+        if (strcmp(line1, line2) != 0) {
+            printf("Lines do not match.\n");
+            printf("1st: %s\n", line1);
+            printf("2nd: %s\n", line2);
+            ini_comment_destroy(ic);
+            ini_comment_destroy(ic_cmp);
+            return -1;
+        }
+    }
+
+    ini_comment_destroy(ic);
+    ini_comment_destroy(ic_cmp);
+
+    return error;
+}
+
+
 int main(int argc, char *argv[])
 {
     int error = EOK;
     test_fn tests[] = { file_test,
                         alter_test,
                         copy_test,
+                        add_test,
                         NULL };
     test_fn t;
     int i = 0;
-- 
1.7.1

