You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/08/22 16:18:48 UTC

svn commit: r806858 - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.in Makefile.msc.in include/acr_ini.h shared/ini.c test/sample.ini test/testsuite.c

Author: mturk
Date: Sat Aug 22 14:18:47 2009
New Revision: 806858

URL: http://svn.apache.org/viewvc?rev=806858&view=rev
Log:
Add basic ini parsing

Added:
    commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h   (with props)
    commons/sandbox/runtime/trunk/src/main/native/shared/ini.c   (with props)
    commons/sandbox/runtime/trunk/src/main/native/test/sample.ini   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/Makefile.in
    commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in
    commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c

Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=806858&r1=806857&r2=806858&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Sat Aug 22 14:18:47 2009
@@ -86,6 +86,7 @@
 	$(SRCDIR)/shared/error.$(OBJ) \
 	$(SRCDIR)/shared/fco.$(OBJ) \
 	$(SRCDIR)/shared/getopt.$(OBJ) \
+	$(SRCDIR)/shared/ini.$(OBJ) \
 	$(SRCDIR)/shared/mbstr.$(OBJ) \
 	$(SRCDIR)/shared/memory.$(OBJ) \
 	$(SRCDIR)/shared/modules.$(OBJ) \

Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in?rev=806858&r1=806857&r2=806858&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Sat Aug 22 14:18:47 2009
@@ -77,6 +77,7 @@
 	$(SRCDIR)/shared/error.$(OBJ) \
 	$(SRCDIR)/shared/fco.$(OBJ) \
 	$(SRCDIR)/shared/getopt.$(OBJ) \
+	$(SRCDIR)/shared/ini.$(OBJ) \
 	$(SRCDIR)/shared/mbstr.$(OBJ) \
 	$(SRCDIR)/shared/memory.$(OBJ) \
 	$(SRCDIR)/shared/modules.$(OBJ) \

Added: commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h?rev=806858&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h (added)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h Sat Aug 22 14:18:47 2009
@@ -0,0 +1,73 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ACR_INI_H
+#define _ACR_INI_H
+
+#include "acr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file acr_ini.h
+ * @brief
+ *
+ * ACR configuration functions
+ *
+ */
+
+typedef struct ini_node_t ini_node_t;
+
+struct ini_node_t {
+    ini_node_t  *next;
+    ini_node_t **last;
+    char        *key;
+    char        *val;
+};
+
+typedef struct ini_section_t ini_section_t;
+
+struct ini_section_t {
+    ini_section_t  *next;
+    ini_section_t **last;
+    char           *name;
+    char           *attr;
+    ini_node_t     *nodes;
+    ini_section_t  *child;
+};
+
+/**
+ * Free the memory used by ini table.
+ * @param root Root ini section.
+ */
+ACR_DECLARE(void) ACR_IniTableFree(ini_section_t *root);
+
+/**
+ * Load the Microsoft ini style configuration file.
+ * @param env Current JNI environment.
+ * @param fname INI file to load.
+ */
+ACR_DECLARE(ini_section_t *) ACR_IniLoadIni(JNIEnv *env, const char *fname);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ACR_INI_H */
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/native/shared/ini.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/ini.c?rev=806858&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/ini.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/ini.c Sat Aug 22 14:18:47 2009
@@ -0,0 +1,267 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * @author Mladen Turk
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_arch.h"
+#include "acr_error.h"
+#include "acr_string.h"
+#include "acr_tables.h"
+#include "acr_ini.h"
+
+/**
+ * Configuration functions
+ */
+
+#if defined(WIN32)
+#define STD_FOPEN_RDFLAGS     "rt"
+#else
+#define STD_FOPEN_RDFLAGS     "r"
+#endif
+
+static void ini_section_free(ini_section_t *ini)
+{
+    ini_section_t *p;
+
+    while ((p = ini)) {
+        ini_node_t *n;
+        while ((n = ini->nodes)) {
+            ini->nodes = n->next;
+            x_free(n->key);
+            x_free(n->val);
+            x_free(n);
+        }
+        if (ini->child) {
+            /* Recursevly delete child sections
+             */
+            ini_section_free(ini->child);
+        }
+        ini = p->next;
+        x_free(p->name);
+        x_free(p->attr);
+        x_free(p);
+    }
+}
+
+static ini_section_t *ini_section_new(ini_section_t *top)
+{
+    ini_section_t *ini = x_calloc(sizeof(ini_section_t));
+    if (top) {
+        *top->last = ini;
+         top->last = &ini->next;
+    }
+    else
+        ini->last = &ini->next;
+
+    return ini;
+}
+
+static ini_section_t *ini_child_new(ini_section_t *parent)
+{
+    ini_section_t *top = parent->child;
+    ini_section_t *ini = x_calloc(sizeof(ini_section_t));
+    if (top) {
+        *top->last = ini;
+         top->last = &ini->next;
+    }
+    else {
+        ini->last     = &ini->next;
+        parent->child = ini;
+    }
+    return ini;
+}
+
+static ini_node_t *ini_node_new(ini_section_t *ini)
+{
+    ini_node_t *node = x_calloc(sizeof(ini_node_t));
+    if (ini->nodes) {
+        *ini->nodes->last = node;
+        ini->nodes->last  = &node->next;
+    }
+    else {
+        node->last = &node->next;
+        ini->nodes = node;
+    }
+    return node;
+}
+
+static ini_section_t *ini_section_get(ini_section_t *ini, const char *name)
+{
+    ini_section_t *p;
+    if (!ini)
+        return NULL;
+    for (p = ini; p; p = p->next) {
+        if (p->name && !strcasecmp(p->name, name))
+            return p;
+    }
+    return NULL;
+}
+
+static char *rtrim(char *s)
+{
+    size_t i;
+    /* check for empty strings */
+    if (!(i = strlen(s)))
+        return s;
+    for (i = i - 1; i >= 0 && acr_isspace(s[i]); i--)
+        ;
+    s[i + 1] = '\0';
+    return s;
+}
+
+static char *ltrim(char *s)
+{
+    size_t i;
+    for (i = 0; s[i] != '\0' && acr_isspace(s[i]); i++)
+        ;
+
+    return s + i;
+}
+
+static char *rltrim(char *s)
+{
+    size_t i;
+    /* check for empty strings */
+    if (!(i = strlen(s)))
+        return s;
+    for (i = i - 1; i >= 0 && acr_isspace(s[i]); i--)
+        ;
+    s[i + 1] = '\0';
+    for (i = 0; s[i] != '\0' && acr_isspace(s[i]); i++)
+        ;
+
+    return s + i;
+}
+
+static char *expand_envars(char *s)
+{
+    /* TODO: Implement
+     */
+    return s;
+}
+
+ACR_DECLARE(void) ACR_IniTableFree(ini_section_t *root)
+{
+    ini_section_free(root);
+}
+
+ACR_DECLARE(ini_section_t *) ACR_IniLoadIni(JNIEnv *_E, const char *fname)
+{
+    FILE *fp;
+    ini_section_t *top  = NULL;
+    ini_section_t *ini  = NULL;
+    ini_node_t    *node = NULL;
+    char buffer[ACR_PBUFF_SIZ];
+    int counter  = 0;
+    int nextline = 0;
+    int started  = 0;
+
+    if (!(fp = fopen(fname, STD_FOPEN_RDFLAGS))) {
+        ACR_THROW_IO_ERRNO();
+        return NULL;
+    }
+    ini = top = ini_section_new(NULL);
+    while (fgets(buffer, ACR_PBUFF_SIZ, fp)) {
+        char *section;
+        char *line;
+        /* Trim readed line */
+        counter++;
+        line = rtrim(buffer);
+        if (!started) {
+            line = ltrim(buffer);
+            /* Evrything up to first [ is comment
+             */
+            if (*line != '[')
+                continue;
+            else
+                started = 1;
+        }
+        if (nextline) {
+            nextline = 0;
+            if (!node || *line == '\0')
+                continue;
+            node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, line);
+            if (node->val[strlen(node->val) - 1] == '\\') {
+                node->val[strlen(node->val) - 1] = '\0';
+                nextline = 1;
+            }
+            if (!nextline) {
+                node->val = expand_envars(node->val);
+            }
+            continue;
+        }
+        line = ltrim(buffer);
+        /* Skip comments and empty lines*/
+        if (*line == '\0' || *line == '#' || *line == ';')
+            continue;
+        if (*line == '[') {
+            char *ends = strchr(++line, ']');
+            if (!ends) {
+                sprintf(buffer, "Unterminated section at line %d", counter);
+                ACR_ThrowExceptionA(_E, THROW_NMARK, ACR_EX_EINVAL, buffer);
+                goto cleanup;
+            }
+            *ends = '\0';
+            section = rltrim(line);
+            if (!(ini = ini_section_get(top, section))) {
+                ini = ini_section_new(top);
+                ini->name = ACR_StrdupA(_E, THROW_NMARK, section);
+            }
+            continue;
+        }
+        else {
+            char *val = NULL;
+            char *equ = line;
+            if (*equ == '=')
+                equ++;
+            if ((equ = strchr(equ, '='))) {
+                *equ++ = '\0';
+                val = rltrim(equ);
+                if (val[strlen(val) - 1] == '\\') {
+                    val[strlen(val) - 1] = '\0';
+                    nextline = 1;
+                }
+                if (!*val)
+                    val = NULL;
+            }
+            line = rltrim(line);
+            if (!*line) {
+                /* Skip entries without keys **/
+                nextline = 0;
+                continue;
+            }
+            node = ini_node_new(ini);
+            node->key = ACR_StrdupA(_E, THROW_NMARK, line);
+            node->val = ACR_StrdupA(_E, THROW_NMARK, val);
+            if (node->val && !nextline) {
+                node->val = expand_envars(node->val);
+            }
+        }
+    }
+    fclose(fp);
+    return top;
+
+cleanup:
+    fclose(fp);
+    ini_section_free(top);
+    return NULL;
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/shared/ini.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/native/test/sample.ini
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/sample.ini?rev=806858&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/sample.ini (added)
+++ commons/sandbox/runtime/trunk/src/main/native/test/sample.ini Sat Aug 22 14:18:47 2009
@@ -0,0 +1,49 @@
+Sample initialization file
+
+Everything up to the first '[' is considered as comment.
+After the first section is recognized, lines starting with first
+'#' or ';' characters are comments.
+Empty lines are ignored.
+
+
+  [first section]
+key without equal char delimiter
+this is key without value =
+values can be spanned on multiple lines = delimiter is '\'\
+  character \
+# comments are allowed in the line \      
+and '\' must be the last non whitespace char. Multiline is ended\
+by the first line without '\' char on the end
+however keys cannot be spanned on \
+multiple lines
+n.#ext = Names don't have to be ascii they can have any chars except =
+
+[second section]
+#sections don't need to have any nodes
+[]
+; this is comment
+# this is comment as well
+    ; comment is first non space character
+
+empty = section names are allowed
+=
+==
+===
+= single equal is considered as key (very dumb)
+multiple=keys
+multiple=are not
+multiple=overwitten.
+
+;[unterminated
+;section]
+; is considered as error.
+
+[duplicate]
+section=instances
+[duplicate]
+section=can be repeted multiple times
+[duplicate]
+# variable order is preserved
+
+
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/test/sample.ini
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c?rev=806858&r1=806857&r2=806858&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Sat Aug 22 14:18:47 2009
@@ -37,6 +37,7 @@
 #include "acr_env.h"
 #include "acr_io.h"
 #include "acr_dso.h"
+#include "acr_ini.h"
 #include "acr_version.h"
 
 #if defined (WIN32)
@@ -246,6 +247,33 @@
     return 0;
 }
 
+static int test_msini(int argc, const char *const argv[])
+{
+    ini_section_t *ini;
+    ini_section_t *top;
+    if (argc < 1)
+        return 1;
+
+    ini = ACR_IniLoadIni(NULL, argv[0]);
+    fprintf(stdout, "Using INI `%s\'\n", argv[0]);
+    top = ini;
+    while (ini) {
+        ini_node_t *node = ini->nodes;
+        if (!ini->name)
+            fprintf(stdout, "Root Section has NULL 'name' member\n");
+        else
+            fprintf(stdout, "Section [%s]\n", ini->name);
+        while (node) {
+            fprintf(stdout, "  %s -> %s\n", node->key, node->val);
+            node = node->next;
+        }
+        ini = ini->next;
+    }
+    ACR_IniTableFree(top);
+
+    return 0;
+}
+
 int main(int argc, const char *const argv[])
 {
     int rv = 0;
@@ -305,6 +333,9 @@
         else if (!strcasecmp(run_test, "error")) {
             rv = test_errno(argc, argv);
         }
+        else if (!strcasecmp(run_test, "msini")) {
+            rv = test_msini(argc, argv);
+        }
     }
 
 cleanup: