From 1d8d61d332ae27c5d5936c8f8a6ca6b1a2d2b51f Mon Sep 17 00:00:00 2001
From: Dmitri Pal <dpal@redhat.com>
Date: Wed, 21 Apr 2010 21:16:18 -0400
Subject: [PATCH] [INI] Introducing a comment object

Comment object will store
the comments found in the INI file.
It is based on the ref_array
interface.
---
 common/ini/Makefile.am      |   15 +-
 common/ini/ini_comment.c    |  506 +++++++++++++++++++++++++++++++++++++++++++
 common/ini/ini_comment.h    |  106 +++++++++
 common/ini/ini_comment_ut.c |  176 +++++++++++++++
 common/ini/ini_config_ut.c  |    4 +-
 5 files changed, 801 insertions(+), 6 deletions(-)
 create mode 100644 common/ini/ini_comment.c
 create mode 100644 common/ini/ini_comment.h
 create mode 100644 common/ini/ini_comment_ut.c

diff --git a/common/ini/Makefile.am b/common/ini/Makefile.am
index 1dc55d9d4fb39aa6da46d053eaba1dbaa0e008e7..ee6c6dee07104e8960f36b502ff0b74394375421 100644
--- a/common/ini/Makefile.am
+++ b/common/ini/Makefile.am
@@ -13,7 +13,8 @@ if HAVE_GCC
         -Wcast-align -Wwrite-strings
 endif
 
-AM_CPPFLAGS = -I$(topdir) -I$(topdir)/trace -I$(topdir)/collection -I$(topdir)/path_utils $(TRACE_LEVEL)
+AM_CPPFLAGS = -I$(topdir) -I$(topdir)/trace -I$(topdir)/collection \
+              -I$(topdir)/path_utils -I$(topdir)/refarray $(TRACE_LEVEL)
 
 ACLOCAL_AMFLAGS = -I m4
 
@@ -43,21 +44,27 @@ libini_config_la_SOURCES = \
     ini_parse.h \
     ini_metadata.c \
     ini_metadata.h \
-    ini_defines.h
+    ini_defines.h \
+    ini_comment.c \
+    ini_comment.h
 
 
 libini_config_la_LIBADD = \
     -L$(topbuilddir)/collection \
     -L$(topbuilddir)/path_utils \
+    -L$(topbuilddir)/refarray \
     -lcollection \
+    -lref_array \
     -lpath_utils
 libini_config_la_LDFLAGS = \
     -version-info 2:0:0
 
 # Build unit test
-check_PROGRAMS = ini_config_ut
+check_PROGRAMS = ini_config_ut ini_comment_ut
 ini_config_ut_SOURCES = ini_config_ut.c
 ini_config_ut_LDADD = libini_config.la -L$(topbuilddir)/collection -lcollection
+ini_comment_ut_SOURCES = ini_comment_ut.c
+ini_comment_ut_LDADD = libini_config.la
 
 if HAVE_DOXYGEN
 docs:
@@ -71,7 +78,7 @@ docs:
 	@exit 1
 endif
 
-TESTS = ini_config_ut
+TESTS = ini_config_ut ini_comment_ut
 
 tests: all $(check_PROGRAMS)
 
diff --git a/common/ini/ini_comment.c b/common/ini/ini_comment.c
new file mode 100644
index 0000000000000000000000000000000000000000..85b3ad02b9d8c680fac9ddaaaa365dc8b7e1af6c
--- /dev/null
+++ b/common/ini/ini_comment.c
@@ -0,0 +1,506 @@
+/*
+    INI LIBRARY
+
+    Object to handle comments
+
+    Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
+
+    INI Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    INI Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with INI Library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include "config.h"
+#include "trace.h"
+#include "ref_array.h"
+#include "ini_comment.h"
+
+/* The lines will increment in this number */
+#define INI_COMMENT_BLOCK 10
+
+/***************************/
+/* Internal comment states */
+/***************************/
+/* Empty - initial */
+#define INI_COMMENT_EMPTY   0
+/* Read - read from file */
+#define INI_COMMENT_READ    1
+/* Comment was altered */
+#define INI_COMMENT_CHANGED 2
+
+
+/*********************************/
+/* Modes to wrap ref array calls */
+/*********************************/
+#define INI_COMMENT_MODE_BUILD      1
+#define INI_COMMENT_MODE_APPEND     2
+#define INI_COMMENT_MODE_INSERT     3
+#define INI_COMMENT_MODE_REPLACE    4
+#define INI_COMMENT_MODE_REMOVE     5
+#define INI_COMMENT_MODE_CLEAR      6
+
+/****************************************/
+/* Internal structure to hold a comment */
+/****************************************/
+struct ini_comment {
+    struct ref_array *ra;
+    uint32_t state;
+};
+
+
+/****************************************/
+
+/* Destroy the comment object */
+void ini_comment_destroy(struct ini_comment *ic)
+{
+
+    TRACE_FLOW_STRING("ini_comment_destroy", "Entry");
+    if (ic) {
+        /* Function will check for NULL */
+        ref_array_destroy(ic->ra);
+        free(ic);
+    }
+    TRACE_FLOW_STRING("ini_comment_destroy", "Exit");
+}
+
+
+/* Cleanup callback */
+void ini_comment_cb(void *elem,
+                    ref_array_del_enum type,
+                    void *data)
+{
+
+    TRACE_FLOW_STRING("ini_comment_cb", "Entry");
+    free(*((char **)elem));
+    TRACE_FLOW_STRING("ini_comment_cb", "Exit");
+}
+
+
+/* Create a comment object */
+int ini_comment_create(struct ini_comment **ic)
+{
+    int error = EOK;
+    struct ref_array *ra = NULL;
+    struct ini_comment *ic_new = NULL;
+
+    TRACE_FLOW_STRING("ini_comment_create", "Entry");
+
+    error = ref_array_create(&ra,
+                             sizeof(char *),
+                             INI_COMMENT_BLOCK,
+                             ini_comment_cb,
+                             NULL);
+    if (error) {
+        TRACE_ERROR_NUMBER("Error creating ref array", error);
+        return error;
+    }
+
+    ic_new = malloc(sizeof(struct ini_comment));
+    if (!ic_new) {
+        TRACE_ERROR_NUMBER("Memory allocation error", ENOMEM);
+        ref_array_destroy(ic_new->ra);
+        return ENOMEM;
+    }
+
+    /* Initialize members here */
+    ic_new->ra = ra;
+    ic_new->state = INI_COMMENT_EMPTY;
+
+    *ic = ic_new;
+
+    TRACE_FLOW_STRING("ini_comment_create", "Exit");
+    return error;
+}
+
+
+/* Is the comment valid? */
+static int ini_comment_is_val(const char *line)
+{
+    int i;
+
+    TRACE_FLOW_STRING("ini_comment_is_val", "Entry");
+
+    /* Null is ok */
+    if (!line) {
+        TRACE_FLOW_STRING("ini_comment_is_val", "Exit - NULL str");
+        return 1;
+    }
+
+    /* Empty is Ok or starts with a special symbol */
+    if ((line[0] == '\0') ||
+        (line[0] == ';') ||
+        (line[0] == '#')) {
+        TRACE_FLOW_STRING("ini_comment_is_val", "Exit - empty or comment");
+        return 1;
+    }
+
+    /* All spaces is Ok too */
+    TRACE_INFO_STRING("Line to eval", line);
+
+    i = 0;
+    while (line[i] != '\0') {
+        if (!isspace(line[i])) {
+            TRACE_ERROR_STRING("ini_comment_is_val", "Invalid comment");
+            return 0;
+        }
+        i++;
+    }
+
+    TRACE_FLOW_STRING("ini_comment_is_val", "Exit - empty str");
+    return 1;
+
+}
+
+
+/*
+ * Modify the comment object
+ */
+static int ini_comment_modify(struct ini_comment *ic,
+                              int mode,
+                              uint32_t idx,
+                              const char *line)
+{
+    int error = EOK;
+    char *elem = NULL;
+    char *input = NULL;
+    char *empty = NULL;
+    uint32_t i, len = 0;
+
+    TRACE_FLOW_STRING("ini_comment_modify", "Entry");
+
+    if (!ic) {
+        TRACE_ERROR_NUMBER("Invalid comment object", EINVAL);
+        return EINVAL;
+    }
+
+
+    if (mode == INI_COMMENT_MODE_BUILD) {
+        /*
+         * Can use this function only if object is empty or
+         * reading from the file.
+         */
+        if ((ic->state != INI_COMMENT_EMPTY) &&
+            (ic->state != INI_COMMENT_READ)) {
+            TRACE_ERROR_NUMBER("Invalid use of the function", EINVAL);
+            return EINVAL;
+        }
+    }
+
+    /* Make sure that we ignore "line" in reset case */
+    if (mode != INI_COMMENT_MODE_CLEAR)
+        memcpy(&input, &line, sizeof(char *));
+
+    if (mode != INI_COMMENT_MODE_REMOVE) {
+        /*
+         * Check that provided line is a comment or an empty line.
+         * Can be NULL too.
+         */
+        if (!ini_comment_is_val(input)) {
+            TRACE_ERROR_NUMBER("Invalid comment", EINVAL);
+            return EINVAL;
+        }
+
+        /* Dup it */
+        if (input) elem = strdup(input);
+        else elem = strdup("");
+
+        if (!elem) {
+            TRACE_ERROR_NUMBER("Memory allocation error", ENOMEM);
+            return ENOMEM;
+        }
+    }
+
+    /* Do action depending on mode */
+    switch (mode) {
+    case INI_COMMENT_MODE_BUILD:
+
+                     TRACE_INFO_STRING("BUILD mode", "");
+                     error = ref_array_append(ic->ra, &elem);
+                     break;
+
+    case INI_COMMENT_MODE_APPEND:
+
+                     TRACE_INFO_STRING("Append mode", "");
+                     error = ref_array_append(ic->ra, &elem);
+                     break;
+
+    case INI_COMMENT_MODE_INSERT:
+
+                     TRACE_INFO_STRING("Insert mode", "");
+                     len = ref_array_len(ic->ra);
+                     if (idx > len) {
+                        /* Fill in empty lines */
+                        for (i = 0; i < (idx-len); i++) {
+                            empty = strdup("");
+                            if (empty) {
+                                TRACE_ERROR_NUMBER("Memory problem", ENOMEM);
+                                return ENOMEM;
+                            }
+                            error = ref_array_append(ic->ra, &empty);
+                            if (error) {
+                                TRACE_ERROR_NUMBER("Append problem", error);
+                                free(empty);
+                                return error;
+                            }
+                        }
+                        /* Append last line */
+                        error = ref_array_append(ic->ra, &elem);
+                     }
+                     else {
+                        /* Insert inside the array */
+                        error = ref_array_insert(ic->ra, idx, &elem);
+                     }
+                     break;
+
+
+    case INI_COMMENT_MODE_REPLACE:
+
+                     TRACE_INFO_STRING("Replace mode", "");
+                     error = ref_array_replace(ic->ra, idx, &elem);
+                     break;
+
+    case INI_COMMENT_MODE_REMOVE:
+
+                     TRACE_INFO_STRING("Remove mode", "");
+                     error = ref_array_remove(ic->ra, idx);
+                     break;
+
+    case INI_COMMENT_MODE_CLEAR:
+
+                     TRACE_INFO_STRING("Clear mode", "");
+                     error = ref_array_replace(ic->ra, idx, &elem);
+                     break;
+    default :
+                     TRACE_ERROR_STRING("Coding error", "");
+                     error = EINVAL;
+    }
+
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to append line to an array", error);
+        free(elem);
+        return error;
+    }
+
+    /* Change state */
+    if (INI_COMMENT_MODE_BUILD) ic->state = INI_COMMENT_READ;
+    else ic->state = INI_COMMENT_CHANGED;
+
+
+    TRACE_FLOW_STRING("ini_comment_modify", "Exit");
+    return error;
+}
+
+/*
+ * Build up a comment object - use this when reading
+ * comments from a file.
+ */
+int ini_comment_build(struct ini_comment *ic, const char *line)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_build", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_BUILD, 0, line);
+
+    TRACE_FLOW_NUMBER("ini_comment_build - Returning", error);
+    return error;
+}
+
+/*
+ * Modify comment by instering a line.
+ */
+int ini_comment_insert(struct ini_comment *ic,
+                       uint32_t idx,
+                       const char *line)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_insert", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_INSERT, idx, line);
+
+    TRACE_FLOW_NUMBER("ini_comment_insert - Returning", error);
+    return error;
+}
+
+/* Modify comment by appending a line. */
+int ini_comment_append(struct ini_comment *ic, const char *line)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_append", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_APPEND, 0, line);
+
+    TRACE_FLOW_NUMBER("ini_comment_append - Returning", error);
+    return error;
+}
+
+/* Remove line from the comment.*/
+int ini_comment_remove(struct ini_comment *ic, uint32_t idx)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_remove", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_REMOVE, idx, NULL);
+
+    TRACE_FLOW_NUMBER("ini_comment_remove - Returning", error);
+    return error;
+}
+
+/* Clear line in the comment. Line is replaced with an empty line */
+int ini_comment_clear(struct ini_comment *ic, uint32_t idx)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_clear", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_CLEAR, idx, NULL);
+
+    TRACE_FLOW_NUMBER("ini_comment_clear - Returning", error);
+    return error;
+
+}
+
+/* Replace a line in the comment */
+int ini_comment_replace(struct ini_comment *ic,
+                        uint32_t idx,
+                        const char *line)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_replace", "Entry");
+
+    error = ini_comment_modify(ic, INI_COMMENT_MODE_REPLACE, idx, line);
+
+    TRACE_FLOW_NUMBER("ini_comment_replace - Returning", error);
+    return error;
+}
+
+
+/* Reset the comment - clean all lines.*/
+int ini_comment_reset(struct ini_comment *ic)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_reset", "Entry");
+
+    if (!ic) {
+        TRACE_ERROR_NUMBER("Invalid comment object", EINVAL);
+        return EINVAL;
+    }
+
+    /* Reset comment if it is not empty */
+    if (ic->state != INI_COMMENT_EMPTY) {
+        ref_array_reset(ic->ra);
+        ic->state = INI_COMMENT_CHANGED;
+    }
+
+    TRACE_FLOW_STRING("ini_comment_reset", "Exit");
+    return error;
+}
+
+/* Get number of lines */
+int ini_comment_get_numlines(struct ini_comment *ic, uint32_t *num)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_get_numlines", "Entry");
+
+    if ((!ic) || (!num)) {
+        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
+        return EINVAL;
+    }
+
+    error = ref_array_getlen(ic->ra, num);
+
+    TRACE_FLOW_NUMBER("ini_comment_get_numlines - Returning", error);
+    return error;
+
+}
+
+/* Get line */
+int ini_comment_get_line(struct ini_comment *ic, uint32_t idx, char **line)
+{
+    int error = EOK;
+    void *res = NULL;
+
+    TRACE_FLOW_STRING("ini_comment_get_line", "Entry");
+
+    if ((!ic) || (!line)) {
+        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
+        return EINVAL;
+    }
+
+    res = ref_array_get(ic->ra, idx, (void *)line);
+    if (!res) {
+        error = EINVAL;
+        *line = NULL;
+    }
+    TRACE_FLOW_NUMBER("ini_comment_get_line - Returning", error);
+    return error;
+}
+
+/* Swap lines */
+int ini_comment_swap(struct ini_comment *ic,
+                     uint32_t idx1,
+                     uint32_t idx2)
+{
+    int error = EOK;
+
+    TRACE_FLOW_STRING("ini_comment_swap", "Entry");
+
+    if (!ic) {
+        TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
+        return EINVAL;
+    }
+
+    error = ref_array_swap(ic->ra, idx1, idx2);
+    if ((!error) && (idx1 != idx2)) {
+        ic->state = INI_COMMENT_CHANGED;
+    }
+
+    TRACE_FLOW_NUMBER("ini_comment_swap - Returning", error);
+    return error;
+}
+
+
+/* Internal function to print comment */
+void ini_comment_print(struct ini_comment *ic, FILE *file)
+{
+    int len;
+    int i;
+    char *ret = NULL;
+
+    TRACE_FLOW_STRING("ini_comment_print", "Entry");
+
+    if (!file) {
+        TRACE_ERROR_NUMBER("Invalid file argument", EINVAL);
+        return;
+    }
+
+    if (ic) {
+        len = ref_array_len(ic->ra);
+        for (i = 0; i < len; i++) {
+            ref_array_get(ic->ra, i, &ret);
+            fprintf(file, "%s\n", ret);
+        }
+    }
+
+    TRACE_FLOW_STRING("ini_comment_print", "Exit");
+
+}
diff --git a/common/ini/ini_comment.h b/common/ini/ini_comment.h
new file mode 100644
index 0000000000000000000000000000000000000000..05c6a7284e2b496bea316c503d754bba95b9ad10
--- /dev/null
+++ b/common/ini/ini_comment.h
@@ -0,0 +1,106 @@
+/*
+    INI LIBRARY
+
+    Header file for comment object.
+
+    Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
+
+    INI Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    INI Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with INI Library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INI_COMMENT_H
+#define INI_COMMENT_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#ifndef EOK
+#define EOK 0
+#endif
+
+struct ini_comment;
+
+/**
+ * Create a comment object
+ */
+int ini_comment_create(struct ini_comment **ic);
+
+/**
+ * Destroy the comment object
+ */
+void ini_comment_destroy(struct ini_comment *ic);
+
+/**
+ * Build up a comment object - use this when reading
+ * comments from a file.
+ */
+int ini_comment_build(struct ini_comment *ic,
+                      const char *line);
+
+/**
+ * Modify comment by instering a line.
+ *
+ * idx can be:
+ * 0 - as first
+ * 1 - after first
+ * 2 - after second
+ * ...
+ * If greater than number of lines
+ * missing lines are added automatically
+ * as empty lines
+ */
+int ini_comment_insert(struct ini_comment *ic,
+                       uint32_t idx,
+                       const char *line);
+
+/* Modify comment by appending a line. */
+int ini_comment_append(struct ini_comment *ic,
+                       const char *line);
+
+/* Remove line from the comment.*/
+int ini_comment_remove(struct ini_comment *ic,
+                       uint32_t idx);
+
+/* Clear line in the comment. Line is replaced with an empty line */
+int ini_comment_clear(struct ini_comment *ic,
+                      uint32_t idx);
+
+/* Replace a line in the comment */
+int ini_comment_replace(struct ini_comment *ic,
+                        uint32_t idx,
+                        const char *line);
+
+/* Reset the comment - clean all lines.*/
+int ini_comment_reset(struct ini_comment *ic);
+
+/* Get number of lines */
+int ini_comment_get_numlines(struct ini_comment *ic,
+                             uint32_t *num);
+
+/* Get line */
+int ini_comment_get_line(struct ini_comment *ic,
+                         uint32_t idx,
+                         char **line);
+
+/* Swap lines */
+int ini_comment_swap(struct ini_comment *ic,
+                     uint32_t idx1,
+                     uint32_t idx2);
+
+
+/* Internal function to print comment */
+void ini_comment_print(struct ini_comment *ic, FILE *file);
+
+
+#endif
diff --git a/common/ini/ini_comment_ut.c b/common/ini/ini_comment_ut.c
new file mode 100644
index 0000000000000000000000000000000000000000..40c15b839b0d3222b2dde7944afab42ca535d2b8
--- /dev/null
+++ b/common/ini/ini_comment_ut.c
@@ -0,0 +1,176 @@
+/*
+    INI LIBRARY
+
+    Unit test for the comment object.
+
+    Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
+
+    INI Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    INI Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with INI Library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#define TRACE_HOME
+#include "trace.h"
+#include "ini_comment.h"
+
+int verbose = 0;
+
+#define INIOUT(foo) \
+    do { \
+        if (verbose) foo; \
+    } while(0)
+
+
+int file_test(void)
+{
+    int error = EOK;
+    struct ini_comment *ic = NULL;
+
+    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 -1;
+    }
+
+    INIOUT(printf("<==== Comment ====>\n"));
+    INIOUT(ini_comment_print(ic, stdout));
+    INIOUT(printf("<=================>\n"));
+    ini_comment_destroy(ic);
+
+    return error;
+}
+
+
+int alter_test(void)
+{
+    int error = EOK;
+    struct ini_comment *ic = NULL;
+    uint32_t i, num = 0;
+    char *line = NULL;
+    const char *expected[] = { ";Line 0 inserted",
+                               ";Line 1 inserted",
+                               "",
+                               "",
+                               ";Line 3 replaced",
+                               "",
+                               ";Line 4" };
+
+
+    if ((error = ini_comment_create(&ic)) ||
+        (error = ini_comment_build(ic, ";Line 0")) ||
+        (error = ini_comment_build(ic, NULL)) ||
+        (error = ini_comment_build(ic, ";Line 2")) ||
+        (error = ini_comment_build(ic, ";Line 3")) ||
+        (error = ini_comment_build(ic, ""))) {
+        printf("Failed to create comment object\n");
+        ini_comment_destroy(ic);
+        return -1;
+    }
+
+    INIOUT(printf("<==== Comment ====>\n"));
+    INIOUT(ini_comment_print(ic, stdout));
+    INIOUT(printf("<=================>\n"));
+
+    if ((error = ini_comment_append(ic, ";Line 4")) ||
+        (error = ini_comment_clear(ic, 2)) ||
+        (error = ini_comment_replace(ic, 3, ";Line 3 replaced")) ||
+        (error = ini_comment_remove(ic, 0)) ||
+        (error = ini_comment_insert(ic, 0, ";Line 0 inserted")) ||
+        (error = ini_comment_insert(ic, 1, ";Line 1 inserted"))) {
+        printf("Failed to create comment object\n");
+        ini_comment_destroy(ic);
+        return -1;
+    }
+
+    INIOUT(printf("<==== Comment ====>\n"));
+    INIOUT(ini_comment_print(ic, stdout));
+    INIOUT(printf("<=================>\n"));
+
+    error = ini_comment_get_numlines(ic, &num);
+    if (error) {
+        printf("Failed to get number of lines.\n");
+        ini_comment_destroy(ic);
+        return -1;
+    }
+
+    for (i = 0; i < num; i++) {
+        error = ini_comment_get_line(ic, i, &line);
+        if (error) {
+            printf("Failed to get line.\n");
+            ini_comment_destroy(ic);
+            return -1;
+        }
+        if (strcmp(line, expected[i]) != 0) {
+            printf("Lines do not match.\n");
+            printf("GOT: %s\n", line);
+            printf("EXP: %s\n", expected[i]);
+            ini_comment_destroy(ic);
+            return -1;
+        }
+    }
+
+    INIOUT(printf("\n\nSwap test\n\n"));
+
+    if ((error = ini_comment_swap(ic, 0 , 6)) ||
+        (error = ini_comment_swap(ic, 1 , 5)) ||
+        (error = ini_comment_swap(ic, 2 , 4))) {
+        printf("Failed to swap lines.\n");
+        ini_comment_destroy(ic);
+        return -1;
+    }
+
+    for (i = 0; i < num; i++) {
+        error = ini_comment_get_line(ic, i, &line);
+        if (error) {
+            printf("Failed to get line.\n");
+            ini_comment_destroy(ic);
+            return -1;
+        }
+        if (strcmp(line, expected[6 - i]) != 0) {
+            printf("Lines do not match.\n");
+            printf("GOT: %s\n", line);
+            printf("EXP: %s\n", expected[6 - i]);
+            ini_comment_destroy(ic);
+            return -1;
+        }
+    }
+
+    ini_comment_destroy(ic);
+    return error;
+}
+
+
+int main(int argc, char *argv[])
+{
+    int error = EOK;
+
+    if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
+
+    INIOUT(printf("Start\n"));
+
+    if ((error = file_test()) ||
+        (error = alter_test())) {
+        printf("Test failed! Error %d.\n", error);
+        return -1;
+    }
+
+    INIOUT(printf("Success!\n"));
+    return 0;
+}
diff --git a/common/ini/ini_config_ut.c b/common/ini/ini_config_ut.c
index 55a8b3348e0a8092873fc1b8ddafbd3f2464ed3c..c9b13fd574cac752911a9046efb2d18c533830ba 100644
--- a/common/ini/ini_config_ut.c
+++ b/common/ini/ini_config_ut.c
@@ -1319,7 +1319,7 @@ int main(int argc, char *argv[])
 
     if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
 
-    printf("Start\n");
+    COLOUT(printf("Start\n"));
 
     srcdir = getenv("srcdir");
     if(srcdir) {
@@ -1343,6 +1343,6 @@ int main(int argc, char *argv[])
         return -1;
     }
 
-    printf("Success!\n");
+    COLOUT(printf("Success!\n"));
     return 0;
 }
-- 
1.5.5.6

