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 19:45:08 UTC

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

Author: mturk
Date: Sat Aug 22 17:45:08 2009
New Revision: 806872

URL: http://svn.apache.org/viewvc?rev=806872&view=rev
Log:
Java Properties file parser

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

Modified: 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=806872&r1=806871&r2=806872&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_ini.h Sat Aug 22 17:45:08 2009
@@ -64,6 +64,13 @@
  */
 ACR_DECLARE(ini_section_t *) ACR_IniLoadIni(JNIEnv *env, const char *fname);
 
+/**
+ * Load the Java properties style configuration file.
+ * @param env Current JNI environment.
+ * @param fname INI file to load.
+ */
+ACR_DECLARE(ini_section_t *) ACR_IniLoadProps(JNIEnv *_E, const char *fname);
+
 
 #ifdef __cplusplus
 }

Modified: 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=806872&r1=806871&r2=806872&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/ini.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/ini.c Sat Aug 22 17:45:08 2009
@@ -151,6 +151,22 @@
     return s + i;
 }
 
+static char *rltrim_p(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]) || s[i] == ':' || s[i] == '='); i++)
+        ;
+
+    return s + i;
+}
+
 static char *expand_envars(char *s)
 {
     /* TODO: Implement ${ENV} expansion.
@@ -216,7 +232,7 @@
             continue;
         }
         line = ltrim(buffer);
-        /* Skip comments and empty lines*/
+        /* Skip comments and empty lines */
         if (*line == '\0' || *line == '#' || *line == ';')
             continue;
         if (*line == '[') {
@@ -272,3 +288,136 @@
     return NULL;
 }
 
+ACR_DECLARE(ini_section_t *) ACR_IniLoadProps(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;
+
+    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;
+        char *ssep;
+        /* Trim readed line */
+        counter++;
+        line = rtrim(buffer);
+        if (nextline) {
+            nextline = 0;
+            /* Java props are left trimmed
+             */
+            line = ltrim(line);
+            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;
+        /* TODO: Use strpbrk that understands quoted char's
+         */
+        ssep = strpbrk(line, ". :=");
+        if (ssep && *ssep == '.') {
+            char *val = NULL;
+            char *equ;
+            char *sub;
+            *(ssep++) = '\0';
+            /* Get root subsection */
+            section   = line;            
+            if (!(ini = ini_section_get(top, section))) {
+                ini = ini_section_new(top);
+                ini->name = ACR_StrdupA(_E, THROW_NMARK, section);
+            }
+            while ((sub = strpbrk(ssep, ". :="))) {
+                ini_section_t *sec  = ini;
+                /* Check for '=' char */
+                if (*sub != '.') {
+                    /* We have found a '.' after '='
+                     * The dot is part of value. bail out
+                     */
+                    break;
+                }
+                *(sub++) = '\0';
+                section = ssep;
+                if (!(ini = ini_section_get(sec, section))) {
+                    ini = ini_child_new(sec);
+                    ini->name = ACR_StrdupA(_E, THROW_NMARK, section);
+                }
+                ssep = sub;
+            }
+            if (*ssep == '=' || *ssep == ':')
+                ssep++;
+            if ((equ = strpbrk(ssep, " =:"))) {
+                *equ++ = '\0';
+                val = rltrim_p(equ);
+                if (val[strlen(val) - 1] == '\\') {
+                    val[strlen(val) - 1] = '\0';
+                    nextline = 1;
+                }
+                if (!*val)
+                    val = NULL;
+            }
+            ssep = rltrim(ssep);
+            if (!*ssep) {
+                /* Skip entries without keys **/
+                nextline = 0;
+                continue;
+            }
+            node = ini_node_new(ini);
+            node->key = ACR_StrdupA(_E, THROW_NMARK, ssep);
+            node->val = ACR_StrdupA(_E, THROW_NMARK, val);
+            if (node->val && !nextline) {
+                node->val = expand_envars(node->val);
+            }
+        }
+        else {
+            char *val = NULL;
+            char *equ;
+            if (*line == '=' || *line == ':')
+                line++;
+            if ((equ = strpbrk(line, " =:"))) {
+                *equ++ = '\0';
+                val = rltrim_p(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(top);
+            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;
+
+}
+

Added: commons/sandbox/runtime/trunk/src/main/native/test/sample.properties
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/sample.properties?rev=806872&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/sample.properties (added)
+++ commons/sandbox/runtime/trunk/src/main/native/test/sample.properties Sat Aug 22 17:45:08 2009
@@ -0,0 +1,42 @@
+# Example properties file
+! It behaves like java properties
+
+foo=level0
+section.name =:level1
+section.subsection.name = level2a
+section.subsection.name
+section.subsection.name     is:level2b
+value
+second.
+third.multiline : value \
+                  over multiple \
+                  lines
+third.next level
+
+! Some examples from the Java 2 Documentation
+!
+Truth = Beauty
+            Truth:Beauty
+Truth                   :Beauty
+! As another example the following lines are
+! specify a single property
+
+fruits      apple, bannana, pear, \
+            kiwi, mango
+
+invalid. remaining is ignored
+.missing
+.missing section has empty name (different then NULL)
+
+key\ with\ quoted\ chars\=: value
+
+some wired sequences
+=a
+:b
+=:
+=::what to do with that ?
+: :Double separators behave like comment
+=c=d
+:e:f
+
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/test/sample.properties
------------------------------------------------------------------------------
    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=806872&r1=806871&r2=806872&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 17:45:08 2009
@@ -274,6 +274,39 @@
     return 0;
 }
 
+static void dump_ini_section(ini_section_t *ini, int level)
+{
+    while (ini) {
+        ini_node_t *node = ini->nodes;
+        fprintf(stdout, "%*sSection [%s]\n", level, "", ini->name);
+        while (node) {
+            fprintf(stdout, "%*s%s -> %s\n", level + 2, "", node->key, node->val);
+            node = node->next;
+        }
+        if (ini->child) {
+            dump_ini_section(ini->child, level + 2);
+        }
+        ini = ini->next;
+    }
+
+}
+
+static int test_props(int argc, const char *const argv[])
+{
+    ini_section_t *ini;
+    ini_section_t *top;
+    if (argc < 1)
+        return 1;
+
+    ini = ACR_IniLoadProps(NULL, argv[0]);
+    fprintf(stdout, "Using Property `%s\'\n", argv[0]);
+    top = ini;
+    dump_ini_section(ini, 0);
+    ACR_IniTableFree(top);
+
+    return 0;
+}
+
 int main(int argc, const char *const argv[])
 {
     int rv = 0;
@@ -336,6 +369,9 @@
         else if (!strcasecmp(run_test, "msini")) {
             rv = test_msini(argc, argv);
         }
+        else if (!strcasecmp(run_test, "props")) {
+            rv = test_props(argc, argv);
+        }
     }
 
 cleanup: