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/24 19:55:05 UTC
svn commit: r807319 - in /commons/sandbox/runtime/trunk/src/main/native:
include/acr_ini.h include/acr_ring.h shared/ini.c test/sample.ini
test/testsuite.c
Author: mturk
Date: Mon Aug 24 17:55:04 2009
New Revision: 807319
URL: http://svn.apache.org/viewvc?rev=807319&view=rev
Log:
Rewrite ini to use APR ring macros
Added:
commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h (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/sample.ini
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=807319&r1=807318&r2=807319&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 Mon Aug 24 17:55:04 2009
@@ -18,6 +18,7 @@
#define _ACR_INI_H
#include "acr.h"
+#include "acr_ring.h"
#ifdef __cplusplus
extern "C" {
@@ -31,68 +32,189 @@
*
*/
-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 acr_ini_attr_t acr_ini_attr_t;
+typedef struct acr_ini_node_t acr_ini_node_t;
+typedef struct acr_ini_t acr_ini_t;
+
+struct acr_ini_attr_t {
+ ACR_RING_ENTRY(acr_ini_attr_t) link;
+ const char *key;
+ char *val;
+ char buf[1]; /* Key storage */
};
-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;
- ini_section_t *parent;
+struct acr_ini_node_t {
+ ACR_RING_ENTRY(acr_ini_node_t) link;
+ ACR_RING_HEAD(ini_attrs_t, acr_ini_attr_t) attr_ring;
+ ACR_RING_HEAD(ini_child_t, acr_ini_node_t) node_ring;
+ acr_ini_node_t *parent; /* Is this a child node */
+ char *name; /* Name of this section */
+ char *attr; /* Node's attributes */
+ char data[1]; /* Key storage */
};
/**
- * Free the memory used by ini table.
- * @param root Root ini section.
+ * Create new ini table
+ * @param env Current JNI environment.
*/
-ACR_DECLARE(void) ACR_IniTableFree(ini_section_t *root);
+ACR_DECLARE(acr_ini_t *) ACR_IniNew(JNIEnv *env);
/**
- * Load the Microsoft ini style configuration file.
+ * Free the memory used by ini table.
* @param env Current JNI environment.
- * @param fname INI file to load.
+ * @param ini Ini table to free.
*/
-ACR_DECLARE(ini_section_t *) ACR_IniLoadIni(JNIEnv *env, const char *fname);
+ACR_DECLARE(void) ACR_IniFree(JNIEnv *env, acr_ini_t *ini);
/**
- * Load the Java properties style configuration file.
+ * Get root node from ini table.
+ * @param ini Ini table to use.
+ * @return Root node,
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeRoot(acr_ini_t *ini);
+
+/**
+ * Get node parent.
+ * @param node Node from which to return the parent.
+ * @return Parent node.
+ * @note If this is root node returned value is pointer to itself.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeParent(acr_ini_node_t *node);
+
+/**
+ * Set current node.
+ * @param ini Ini table for which to set the current node.
+ * @param node Node to use as new current node.
+ * @note If node is NULL, the table root node is used as current.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniSetCurrent(acr_ini_t *ini,
+ acr_ini_node_t *node);
+
+/**
+ * Set parent of the node as current node.
+ * @param ini Ini table for which to set the parent.
+ * @param node Node which parent is used as new current node.
+ * @note If node is NULL, the table root node is used as current.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniSetParentAsCurrent(acr_ini_t *ini,
+ acr_ini_node_t *node);
+
+/**
+ * Find the node from the current table node by name.
+ * @param ini Ini table for which to get the node.
+ * @param name Node name to find.
+ * @note Node is searched in table's current node.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeGet(JNIEnv *env, acr_ini_t *ini,
+ const char *name);
+/**
+ * Add the node to the current table node if not added alreay.
+ * @param ini Ini table for which to get the node.
+ * @param name Node name to add.
+ * @note Node is added to the table's current node.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeAdd(JNIEnv *env, acr_ini_t *ini,
+ const char *name,
+ const char *attr);
+/**
+ * Add the node to the current table node if not added alreay
+ * and set this node as table current node.
+ * @param ini Ini table for which to get the node.
+ * @param name Node name to add or set as current.
+ * @note Node is added to the table's current node.
+ */
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeSet(JNIEnv *env, acr_ini_t *ini,
+ const char *name,
+ const char *attr);
+
+/**
+ * Add attr to the existing node attribute.
+ * @param node Node for which to add addribute.
+ * @param attr String to add.
+ * @note New attribute is constructed using strcat to previous value.
+ * If the attr param is NULL, the previous attribute is deleted and
+ * its memory is freed.
+ */
+ACR_DECLARE(int) ACR_IniNodeAddAttr(JNIEnv *env, acr_ini_node_t *node,
+ const char *attr);
+
+/**
+ * Replace the existing node attribute.
+ * @param node Node for which to add addribute.
+ * @param attr New string attribute.
+ * @note If the attr param is NULL, the previous attribute is deleted and
+ * its memory is freed.
+ */
+ACR_DECLARE(int) ACR_IniNodeSetAttr(JNIEnv *env, acr_ini_node_t *node,
+ const char *attr);
+
+/**
+ * Add new key value attribute to the node.
+ * @param node Node for which to add addribute.
+ * @param key New attribute key.
+ * @param val New attribute value.
+ */
+ACR_DECLARE(acr_ini_attr_t *) ACR_IniNodeAttrAdd(JNIEnv *env,
+ acr_ini_node_t *node,
+ const char *key,
+ const char *val);
+/**
+ * Add new key value attribute to the node if not added already
+ * @param node Node for which to add addribute.
+ * @param key Attribute key.
+ * @param val New attribute value.
+ * @note if the attribute with the given key already exists for the
+ * node it's value is replaced with the val parameter.
+ */
+ACR_DECLARE(acr_ini_attr_t *) ACR_IniNodeAttrSet(JNIEnv *env,
+ acr_ini_node_t *node,
+ const char *key,
+ const char *val);
+
+/**
+ * Add value to the existing attribute value.
+ * @param attr Attribute for which to add value.
+ * @param val String to add.
+ * @note New attribute's value is constructed using strcat to previous value.
+ * If the val param is NULL, the previous attribute value is deleted and
+ * its memory is freed.
+ */
+ACR_DECLARE(int) ACR_IniAttrAddVal(JNIEnv *env, acr_ini_attr_t *attr,
+ const char *val);
+/**
+ * Replace the existing node attribute value.
+ * @param attr Attribute for which to set the value.
+ * @param val New attribute's value.
+ * @note If the val param is NULL, the previous attribute is deleted and
+ * its memory is freed.
+ */
+ACR_DECLARE(int) ACR_IniAttrSetVal(JNIEnv *env, acr_ini_attr_t *attr,
+ const char *val);
+
+
+/**
+ * Load the Microsoft ini style configuration file.
* @param env Current JNI environment.
- * @param fname Properties file to load.
- * @param allowdup If nonzero duplicate keys are allowed
+ * @param fname INI file to load.
*/
-ACR_DECLARE(ini_section_t *) ACR_IniLoadProperties(JNIEnv *env,
- const char *fname,
- int allowdups);
+ACR_DECLARE(acr_ini_t *) ACR_IniLoadIni(JNIEnv *env, const char *fname);
/**
* Load the Java properties style configuration file.
* @param env Current JNI environment.
* @param fname Properties file to load.
- * @param section separator character.
* @param allowdup If nonzero duplicate keys are allowed
*/
-ACR_DECLARE(ini_section_t *) ACR_IniLoadPropertiesTree(JNIEnv *env,
- const char *fname,
- int separator,
- int allowdups);
+ACR_DECLARE(acr_ini_t *) ACR_IniLoadProperties(JNIEnv *env,
+ const char *fname,
+ int allowdups);
/**
* Load the Apache Httpd style configuration file.
* @param env Current JNI environment.
* @param fname Conf file to load.
*/
-ACR_DECLARE(ini_section_t *) ACR_IniLoadConf(JNIEnv *env, const char *fname);
+ACR_DECLARE(acr_ini_t *) ACR_IniLoadConf(JNIEnv *env, const char *fname);
#ifdef __cplusplus
Added: commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h?rev=807319&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h (added)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h Mon Aug 24 17:55:04 2009
@@ -0,0 +1,403 @@
+/* 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.
+ */
+
+/*
+ * This code draws heavily from the 4.4BSD <sys/queue.h> macros
+ * and Dean Gaudet's "splim/ring.h".
+ * <http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h>
+ * <http://www.arctic.org/~dean/splim/>
+ *
+ * We'd use Dean's code directly if we could guarantee the
+ * availability of inline functions.
+ */
+
+#ifndef _ACR_RING_H
+#define _ACR_RING_H
+
+/**
+ * @file acr_ring.h
+ * @brief ACR Rings
+ */
+
+/**
+ * @defgroup acr_ring Ring Macro Implementations
+ * @ingroup ACR
+ * A ring is a kind of doubly-linked list that can be manipulated
+ * without knowing where its head is.
+ * @{
+ */
+
+/**
+ * The Ring Element
+ *
+ * A ring element struct is linked to the other elements in the ring
+ * through its ring entry field, e.g.
+ * <pre>
+ * struct my_element_t {
+ * ACR_RING_ENTRY(my_element_t) link;
+ * int foo;
+ * char *bar;
+ * };
+ * </pre>
+ *
+ * An element struct may be put on more than one ring if it has more
+ * than one ACR_RING_ENTRY field. Each ACR_RING_ENTRY has a corresponding
+ * ACR_RING_HEAD declaration.
+ *
+ * @warning For strict C standards compliance you should put the ACR_RING_ENTRY
+ * first in the element struct unless the head is always part of a larger
+ * object with enough earlier fields to accommodate the offsetof() used
+ * to compute the ring sentinel below. You can usually ignore this caveat.
+ */
+#define ACR_RING_ENTRY(elem) \
+ struct { \
+ struct elem * volatile next; \
+ struct elem * volatile prev; \
+ }
+
+/**
+ * The Ring Head
+ *
+ * Each ring is managed via its head, which is a struct declared like this:
+ * <pre>
+ * ACR_RING_HEAD(my_ring_t, my_element_t);
+ * struct my_ring_t ring, *ringp;
+ * </pre>
+ *
+ * This struct looks just like the element link struct so that we can
+ * be sure that the typecasting games will work as expected.
+ *
+ * The first element in the ring is next after the head, and the last
+ * element is just before the head.
+ */
+#define ACR_RING_HEAD(head, elem) \
+ struct head { \
+ struct elem *next; \
+ struct elem *prev; \
+ }
+
+/**
+ * The Ring Sentinel
+ *
+ * This is the magic pointer value that occurs before the first and
+ * after the last elements in the ring, computed from the address of
+ * the ring's head. The head itself isn't an element, but in order to
+ * get rid of all the special cases when dealing with the ends of the
+ * ring, we play typecasting games to make it look like one.
+ *
+ * Here is a diagram to illustrate the arrangements of the next and
+ * prev pointers of each element in a single ring. Note that they point
+ * to the start of each element, not to the ACR_RING_ENTRY structure.
+ *
+ * <pre>
+ * +->+------+<-+ +->+------+<-+ +->+------+<-+
+ * | |struct| | | |struct| | | |struct| |
+ * / | elem | \/ | elem | \/ | elem | \
+ * ... | | /\ | | /\ | | ...
+ * +------+ | | +------+ | | +------+
+ * ...--|prev | | +--|ring | | +--|prev |
+ * | next|--+ | entry|--+ | next|--...
+ * +------+ +------+ +------+
+ * | etc. | | etc. | | etc. |
+ * : : : : : :
+ * </pre>
+ *
+ * The ACR_RING_HEAD is nothing but a bare ACR_RING_ENTRY. The prev
+ * and next pointers in the first and last elements don't actually
+ * point to the head, they point to a phantom place called the
+ * sentinel. Its value is such that last->next->next == first because
+ * the offset from the sentinel to the head's next pointer is the same
+ * as the offset from the start of an element to its next pointer.
+ * This also works in the opposite direction.
+ *
+ * <pre>
+ * last first
+ * +->+------+<-+ +->sentinel<-+ +->+------+<-+
+ * | |struct| | | | | |struct| |
+ * / | elem | \/ \/ | elem | \
+ * ... | | /\ /\ | | ...
+ * +------+ | | +------+ | | +------+
+ * ...--|prev | | +--|ring | | +--|prev |
+ * | next|--+ | head|--+ | next|--...
+ * +------+ +------+ +------+
+ * | etc. | | etc. |
+ * : : : :
+ * </pre>
+ *
+ * Note that the offset mentioned above is different for each kind of
+ * ring that the element may be on, and each kind of ring has a unique
+ * name for its ACR_RING_ENTRY in each element, and has its own type
+ * for its ACR_RING_HEAD.
+ *
+ * Note also that if the offset is non-zero (which is required if an
+ * element has more than one ACR_RING_ENTRY), the unreality of the
+ * sentinel may have bad implications on very perverse implementations
+ * of C -- see the warning in ACR_RING_ENTRY.
+ *
+ * @param hp The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_SENTINEL(hp, elem, link) \
+ (struct elem *)((char *)(&(hp)->next) - ACR_OFFSETOF(struct elem, link))
+
+/**
+ * The first element of the ring
+ * @param hp The head of the ring
+ */
+#define ACR_RING_FIRST(hp) (hp)->next
+/**
+ * The last element of the ring
+ * @param hp The head of the ring
+ */
+#define ACR_RING_LAST(hp) (hp)->prev
+/**
+ * The next element in the ring
+ * @param ep The current element
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_NEXT(ep, link) (ep)->link.next
+/**
+ * The previous element in the ring
+ * @param ep The current element
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_PREV(ep, link) (ep)->link.prev
+
+
+/**
+ * Initialize a ring
+ * @param hp The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_INIT(hp, elem, link) do { \
+ ACR_RING_FIRST((hp)) = ACR_RING_SENTINEL((hp), elem, link); \
+ ACR_RING_LAST((hp)) = ACR_RING_SENTINEL((hp), elem, link); \
+ } while (0)
+
+/**
+ * Determine if a ring is empty
+ * @param hp The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ * @return true or false
+ */
+#define ACR_RING_EMPTY(hp, elem, link) \
+ (ACR_RING_FIRST((hp)) == ACR_RING_SENTINEL((hp), elem, link))
+
+/**
+ * Initialize a singleton element
+ * @param ep The element
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_ELEM_INIT(ep, link) do { \
+ ACR_RING_NEXT((ep), link) = (ep); \
+ ACR_RING_PREV((ep), link) = (ep); \
+ } while (0)
+
+
+/**
+ * Splice the sequence ep1..epN into the ring before element lep
+ * (..lep.. becomes ..ep1..epN..lep..)
+ * @warning This doesn't work for splicing before the first element or on
+ * empty rings... see ACR_RING_SPLICE_HEAD for one that does
+ * @param lep Element in the ring to splice before
+ * @param ep1 First element in the sequence to splice in
+ * @param epN Last element in the sequence to splice in
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_SPLICE_BEFORE(lep, ep1, epN, link) do { \
+ ACR_RING_NEXT((epN), link) = (lep); \
+ ACR_RING_PREV((ep1), link) = ACR_RING_PREV((lep), link); \
+ ACR_RING_NEXT(ACR_RING_PREV((lep), link), link) = (ep1); \
+ ACR_RING_PREV((lep), link) = (epN); \
+ } while (0)
+
+/**
+ * Splice the sequence ep1..epN into the ring after element lep
+ * (..lep.. becomes ..lep..ep1..epN..)
+ * @warning This doesn't work for splicing after the last element or on
+ * empty rings... see ACR_RING_SPLICE_TAIL for one that does
+ * @param lep Element in the ring to splice after
+ * @param ep1 First element in the sequence to splice in
+ * @param epN Last element in the sequence to splice in
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_SPLICE_AFTER(lep, ep1, epN, link) do { \
+ ACR_RING_PREV((ep1), link) = (lep); \
+ ACR_RING_NEXT((epN), link) = ACR_RING_NEXT((lep), link); \
+ ACR_RING_PREV(ACR_RING_NEXT((lep), link), link) = (epN); \
+ ACR_RING_NEXT((lep), link) = (ep1); \
+ } while (0)
+
+/**
+ * Insert the element nep into the ring before element lep
+ * (..lep.. becomes ..nep..lep..)
+ * @warning This doesn't work for inserting before the first element or on
+ * empty rings... see ACR_RING_INSERT_HEAD for one that does
+ * @param lep Element in the ring to insert before
+ * @param nep Element to insert
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_INSERT_BEFORE(lep, nep, link) \
+ ACR_RING_SPLICE_BEFORE((lep), (nep), (nep), link)
+
+/**
+ * Insert the element nep into the ring after element lep
+ * (..lep.. becomes ..lep..nep..)
+ * @warning This doesn't work for inserting after the last element or on
+ * empty rings... see ACR_RING_INSERT_TAIL for one that does
+ * @param lep Element in the ring to insert after
+ * @param nep Element to insert
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_INSERT_AFTER(lep, nep, link) \
+ ACR_RING_SPLICE_AFTER((lep), (nep), (nep), link)
+
+
+/**
+ * Splice the sequence ep1..epN into the ring before the first element
+ * (..hp.. becomes ..hp..ep1..epN..)
+ * @param hp Head of the ring
+ * @param ep1 First element in the sequence to splice in
+ * @param epN Last element in the sequence to splice in
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_SPLICE_HEAD(hp, ep1, epN, elem, link) \
+ ACR_RING_SPLICE_AFTER(ACR_RING_SENTINEL((hp), elem, link), \
+ (ep1), (epN), link)
+
+/**
+ * Splice the sequence ep1..epN into the ring after the last element
+ * (..hp.. becomes ..ep1..epN..hp..)
+ * @param hp Head of the ring
+ * @param ep1 First element in the sequence to splice in
+ * @param epN Last element in the sequence to splice in
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link) \
+ ACR_RING_SPLICE_BEFORE(ACR_RING_SENTINEL((hp), elem, link), \
+ (ep1), (epN), link)
+
+/**
+ * Insert the element nep into the ring before the first element
+ * (..hp.. becomes ..hp..nep..)
+ * @param hp Head of the ring
+ * @param nep Element to insert
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_INSERT_HEAD(hp, nep, elem, link) \
+ ACR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link)
+
+/**
+ * Insert the element nep into the ring after the last element
+ * (..hp.. becomes ..nep..hp..)
+ * @param hp Head of the ring
+ * @param nep Element to insert
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_INSERT_TAIL(hp, nep, elem, link) \
+ ACR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
+
+/**
+ * Concatenate ring h2 onto the end of ring h1, leaving h2 empty.
+ * @param h1 Head of the ring to concatenate onto
+ * @param h2 Head of the ring to concatenate
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_CONCAT(h1, h2, elem, link) do { \
+ if (!ACR_RING_EMPTY((h2), elem, link)) { \
+ ACR_RING_SPLICE_BEFORE(ACR_RING_SENTINEL((h1), elem, link), \
+ ACR_RING_FIRST((h2)), \
+ ACR_RING_LAST((h2)), link); \
+ ACR_RING_INIT((h2), elem, link); \
+ } \
+ } while (0)
+
+/**
+ * Prepend ring h2 onto the beginning of ring h1, leaving h2 empty.
+ * @param h1 Head of the ring to prepend onto
+ * @param h2 Head of the ring to prepend
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_PREPEND(h1, h2, elem, link) do { \
+ if (!ACR_RING_EMPTY((h2), elem, link)) { \
+ ACR_RING_SPLICE_AFTER(ACR_RING_SENTINEL((h1), elem, link), \
+ ACR_RING_FIRST((h2)), \
+ ACR_RING_LAST((h2)), link); \
+ ACR_RING_INIT((h2), elem, link); \
+ } \
+ } while (0)
+
+/**
+ * Unsplice a sequence of elements from a ring
+ * @warning The unspliced sequence is left with dangling pointers at either end
+ * @param ep1 First element in the sequence to unsplice
+ * @param epN Last element in the sequence to unsplice
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_UNSPLICE(ep1, epN, link) do { \
+ ACR_RING_NEXT(ACR_RING_PREV((ep1), link), link) = \
+ ACR_RING_NEXT((epN), link); \
+ ACR_RING_PREV(ACR_RING_NEXT((epN), link), link) = \
+ ACR_RING_PREV((ep1), link); \
+ } while (0)
+
+/**
+ * Remove a single element from a ring
+ * @warning The unspliced element is left with dangling pointers at either end
+ * @param ep Element to remove
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_REMOVE(ep, link) \
+ ACR_RING_UNSPLICE((ep), (ep), link)
+
+/**
+ * Iterate over a ring
+ * @param ep The current element
+ * @param head The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_FOREACH(ep, head, elem, link) \
+ for (ep = ACR_RING_FIRST(head); \
+ ep != ACR_RING_SENTINEL(head, elem, link); \
+ ep = ACR_RING_NEXT(ep, link))
+
+/**
+ * Iterate over a ring safe against removal of the current element
+ * @param ep1 The current element
+ * @param ep2 Iteration cursor
+ * @param head The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the ACR_RING_ENTRY in the element struct
+ */
+#define ACR_RING_FOREACH_SAFE(ep1, ep2, head, elem, link) \
+ for (ep1 = ACR_RING_FIRST(head), ep2 = ACR_RING_NEXT(ep1, link); \
+ ep1 != ACR_RING_SENTINEL(head, elem, link); \
+ ep1 = ep2, ep2 = ACR_RING_NEXT(ep1, link))
+
+/** @} */
+
+#endif /* !_ACR_RING_H */
+
Propchange: commons/sandbox/runtime/trunk/src/main/native/include/acr_ring.h
------------------------------------------------------------------------------
svn:eol-style = native
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=807319&r1=807318&r2=807319&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/ini.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/ini.c Mon Aug 24 17:55:04 2009
@@ -23,6 +23,7 @@
#include "acr_private.h"
#include "acr_arch.h"
#include "acr_error.h"
+#include "acr_memory.h"
#include "acr_string.h"
#include "acr_tables.h"
#include "acr_ini.h"
@@ -31,105 +32,287 @@
* Configuration functions
*/
+struct acr_ini_t {
+ acr_ini_node_t root;
+ acr_ini_node_t *cur;
+};
+
+
#if defined(WIN32)
#define STD_FOPEN_RDFLAGS "rt"
#else
#define STD_FOPEN_RDFLAGS "r"
#endif
-static void ini_section_free(ini_section_t *ini)
+static acr_ini_node_t *ini_node_create(JNIEnv *_E, size_t nlen)
+{
+ acr_ini_node_t *ini;
+
+ ini = ACR_Calloc(_E, THROW_NMARK, sizeof(acr_ini_node_t) + nlen);
+ if (!ini)
+ return NULL;
+
+ ACR_RING_ELEM_INIT(ini, link);
+ ACR_RING_INIT(&ini->attr_ring, acr_ini_attr_t, link);
+ ACR_RING_INIT(&ini->node_ring, acr_ini_node_t, link);
+ if (nlen)
+ ini->name = &ini->data[0];
+ return ini;
+}
+
+static void ini_node_free(acr_ini_node_t *node, int clear)
{
- ini_section_t *p;
+ acr_ini_attr_t *ap;
+ acr_ini_attr_t *ac;
+ acr_ini_node_t *np;
+ acr_ini_node_t *nc;
+
+ ACR_RING_FOREACH_SAFE(nc, np, &node->node_ring, acr_ini_node_t, link) {
+ ACR_RING_REMOVE(nc, link);
+ ini_node_free(nc, 0);
+ }
+
+ ACR_RING_FOREACH_SAFE(ac, ap, &node->attr_ring, acr_ini_attr_t, link) {
+ ACR_RING_REMOVE(ac, link);
+ x_free(ac->val);
+ x_free(ac);
+ }
+ x_free(node->attr);
+ node->attr = NULL;
+ if (!clear) {
+ x_free(node);
+ }
+}
+
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeGet(JNIEnv *_E, acr_ini_t *ini,
+ const char *name)
+{
+ acr_ini_node_t *np;
+
+ if (!name)
+ return &ini->root;
+ for (np = ACR_RING_FIRST(&(ini->cur->node_ring));
+ np != ACR_RING_SENTINEL(&(ini->cur->node_ring), acr_ini_node_t, link);
+ np = ACR_RING_NEXT(np, link)) {
+ if (name && np->name && !strcasecmp(name, np->name))
+ return np;
+ else if (name == NULL && np->name == NULL)
+ return np;
+
+ }
+ return NULL;
+}
- 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);
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeSet(JNIEnv *_E, acr_ini_t *ini,
+ const char *name,
+ const char *attr)
+{
+ acr_ini_node_t *np;
+
+ if (!name) {
+ return NULL;
+ }
+ for (np = ACR_RING_FIRST(&(ini->cur->node_ring));
+ np != ACR_RING_SENTINEL(&(ini->cur->node_ring), acr_ini_node_t, link);
+ np = ACR_RING_NEXT(np, link)) {
+ if (np->name && !strcasecmp(name, np->name)) {
+ ini->cur = np;
+ return np;
}
- if (ini->child) {
- /* Recursevly delete child sections
- */
- ini_section_free(ini->child);
+ }
+ np = ini_node_create(_E, strlen(name));
+ if (!np)
+ return NULL;
+ strcpy(np->data, name);
+ np->attr = ACR_StrdupA(_E, THROW_NMARK, attr);
+ np->parent = ini->cur;
+ ACR_RING_INSERT_TAIL(&(ini->cur->node_ring), np, acr_ini_node_t, link);
+ ini->cur = np;
+
+ return np;
+}
+
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeAdd(JNIEnv *_E, acr_ini_t *ini,
+ const char *name,
+ const char *attr)
+{
+ acr_ini_node_t *np;
+
+ if (!name) {
+ return NULL;
+ }
+ for (np = ACR_RING_FIRST(&(ini->cur->node_ring));
+ np != ACR_RING_SENTINEL(&(ini->cur->node_ring), acr_ini_node_t, link);
+ np = ACR_RING_NEXT(np, link)) {
+ if (np->name && !strcasecmp(name, np->name))
+ return np;
+ }
+ np = ini_node_create(_E, strlen(name));
+ if (!np)
+ return NULL;
+ strcpy(np->data, name);
+ np->attr = ACR_StrdupA(_E, THROW_NMARK, attr);
+ np->parent = ini->cur;
+ ACR_RING_INSERT_TAIL(&(ini->cur->node_ring), np, acr_ini_node_t, link);
+
+ return np;
+}
+
+ACR_DECLARE(acr_ini_attr_t *) ACR_IniNodeAttrSet(JNIEnv *_E, acr_ini_node_t *node,
+ const char *key, const char *val)
+{
+ acr_ini_attr_t *ap;
+
+ if (!key) {
+ return NULL;
+ }
+ for (ap = ACR_RING_FIRST(&(node->attr_ring));
+ ap != ACR_RING_SENTINEL(&(node->attr_ring), acr_ini_attr_t, link);
+ ap = ACR_RING_NEXT(ap, link)) {
+ if (!strcasecmp(key, ap->key)) {
+ x_free(ap->val);
+ ap->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ return ap;
}
- ini = p->next;
- x_free(p->name);
- x_free(p->attr);
- x_free(p);
}
+ ap = ACR_Calloc(_E, THROW_NMARK, sizeof(acr_ini_attr_t) + strlen(key));
+ if (!ap)
+ return NULL;
+ strcpy(ap->buf, key);
+ ap->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ ap->key = &ap->buf[0];
+ ACR_RING_ELEM_INIT(ap, link);
+ ACR_RING_INSERT_TAIL(&(node->attr_ring), ap, acr_ini_attr_t, link);
+
+ return ap;
}
-static ini_section_t *ini_section_new(ini_section_t *top)
+ACR_DECLARE(acr_ini_attr_t *) ACR_IniNodeAttrAdd(JNIEnv *_E, acr_ini_node_t *node,
+ const char *key, const char *val)
{
- ini_section_t *ini = x_calloc(sizeof(ini_section_t));
- if (top) {
- *top->last = ini;
- top->last = &ini->next;
+ acr_ini_attr_t *ap;
+
+ if (!key) {
+ return NULL;
}
- else
- ini->last = &ini->next;
- ini->parent = top;
- return ini;
+ ap = ACR_Calloc(_E, THROW_NMARK, sizeof(acr_ini_attr_t) + strlen(key));
+ if (!ap)
+ return NULL;
+ strcpy(ap->buf, key);
+ ap->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ ap->key = &ap->buf[0];
+ ACR_RING_ELEM_INIT(ap, link);
+ ACR_RING_INSERT_TAIL(&(node->attr_ring), ap, acr_ini_attr_t, link);
+
+ return ap;
}
-static ini_section_t *ini_child_new(ini_section_t *parent)
+ACR_DECLARE(int) ACR_IniAttrAddVal(JNIEnv *_E, acr_ini_attr_t *attr,
+ const char *val)
{
- 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;
+ if (!val) {
+ /* Nothing to add */
+ return 0;
}
- ini->parent = parent;
- return ini;
+ attr->val = ACR_StrcatA(_E, THROW_NMARK, attr->val, val);
+ if (!attr->val)
+ return ACR_GET_OS_ERROR();
+ else
+ return 0;
}
-static ini_node_t *ini_node_new(ini_section_t *ini)
+ACR_DECLARE(int) ACR_IniAttrSetVal(JNIEnv *_E, acr_ini_attr_t *attr,
+ const char *val)
{
- ini_node_t *node = x_calloc(sizeof(ini_node_t));
- if (ini->nodes) {
- *ini->nodes->last = node;
- ini->nodes->last = &node->next;
+ x_free(attr->val);
+ attr->val = NULL;
+ if (!val) {
+ /* Nothing to add */
+ return 0;
}
- else {
- node->last = &node->next;
- ini->nodes = node;
+ attr->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ if (!attr->val)
+ return ACR_GET_OS_ERROR();
+ else
+ return 0;
+}
+
+ACR_DECLARE(int) ACR_IniNodeAddAttr(JNIEnv *_E, acr_ini_node_t *node,
+ const char *attr)
+{
+ if (!attr) {
+ /* Nothing to add */
+ return 0;
}
- return node;
+ node->attr = ACR_StrcatA(_E, THROW_NMARK, node->attr, attr);
+ if (!node->attr)
+ return ACR_GET_OS_ERROR();
+ else
+ return 0;
+
}
-static ini_section_t *ini_section_get(ini_section_t *ini, const char *name)
+ACR_DECLARE(int) ACR_IniNodeSetAttr(JNIEnv *_E, acr_ini_node_t *node,
+ const char *attr)
{
- ini_section_t *p;
- if (!ini)
- return NULL;
- for (p = ini; p; p = p->next) {
- if (name && p->name && !strcasecmp(p->name, name))
- return p;
- else if (name == NULL && p->name == NULL)
- return p;
+ x_free(node->attr);
+ node->attr = NULL;
+ if (!attr) {
+ /* Nothing to set */
+ return 0;
}
- return NULL;
+ node->attr = ACR_StrdupA(_E, THROW_NMARK, attr);
+ if (!node->attr)
+ return ACR_GET_OS_ERROR();
+ else
+ return 0;
}
-static ini_node_t *ini_node_get(ini_section_t *ini, const char *key)
+ACR_DECLARE(acr_ini_t *) ACR_IniNew(JNIEnv *_E)
{
- ini_node_t *n;
+ acr_ini_t *ini;
+
+ ini = ACR_Calloc(_E, THROW_NMARK, sizeof(acr_ini_t));
if (!ini)
return NULL;
- for (n = ini->nodes; n; n = n->next) {
- if (key && n->key && !strcasecmp(n->key, key))
- return n;
- else if (key == NULL && n->key == NULL)
- return n;
- }
- return NULL;
+ ini->cur = &ini->root;
+ ini->cur->parent = ini->cur;
+ ACR_RING_ELEM_INIT(ini->cur, link);
+ ACR_RING_INIT(&ini->cur->attr_ring, acr_ini_attr_t, link);
+ ACR_RING_INIT(&ini->cur->node_ring, acr_ini_node_t, link);
+
+ return ini;
+}
+
+ACR_DECLARE(void) ACR_IniFree(JNIEnv *_E, acr_ini_t *ini)
+{
+ ini_node_free(&ini->root, 1);
+ ACR_Free(_E, THROW_NMARK, ini);
+}
+
+ACR_DECLARE(acr_ini_node_t *) ACR_IniNodeRoot(acr_ini_t *ini)
+{
+ return &ini->root;
+}
+
+ACR_DECLARE(acr_ini_node_t *) ACR_IniSetCurrent(acr_ini_t *ini,
+ acr_ini_node_t *node)
+{
+ if (node)
+ ini->cur = node;
+ else
+ ini->cur = &ini->root;
+ return ini->cur;
+}
+
+ACR_DECLARE(acr_ini_node_t *) ACR_IniSetParentAsCurrent(acr_ini_t *ini,
+ acr_ini_node_t *node)
+{
+ if (node->parent)
+ ini->cur = node->parent;
+ else
+ ini->cur = &ini->root;
+ return ini->cur;
}
static char *rtrim(char *s)
@@ -258,23 +441,18 @@
return s;
}
-ACR_DECLARE(void) ACR_IniTableFree(ini_section_t *root)
-{
- ini_section_free(root);
-}
-
/*
* TODO:
* Use replacement file stdio api once when finished
* so we can use ucs2 file names and portable fgets.
* fopen, fgets and fclose need ACR replacement functions.
*/
-ACR_DECLARE(ini_section_t *) ACR_IniLoadIni(JNIEnv *_E, const char *fname)
+ACR_DECLARE(acr_ini_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;
+ acr_ini_t *ini = NULL;
+ acr_ini_node_t *cur = NULL;
+ acr_ini_attr_t *attr = NULL;
char buffer[ACR_PBUFF_SIZ];
int counter = 0;
int nextline = 0;
@@ -284,7 +462,9 @@
ACR_THROW_IO_ERRNO();
return NULL;
}
- ini = top = ini_section_new(NULL);
+ ini = ACR_IniNew(_E);
+ cur = ACR_IniNodeRoot(ini);
+ ACR_IniNodeSetAttr(_E, cur, fname);
while (fgets(buffer, ACR_PBUFF_SIZ, fp)) {
char *section;
char *line;
@@ -302,15 +482,15 @@
}
if (nextline) {
nextline = 0;
- if (!node || *line == '\0')
+ if (!attr || *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';
+ if (line[strlen(line) - 1] == '\\') {
+ line[strlen(line) - 1] = '\0';
nextline = 1;
}
+ ACR_IniAttrAddVal(_E, attr, line);
if (!nextline) {
- node->val = expand_envars(node->val);
+ attr->val = expand_envars(attr->val);
}
continue;
}
@@ -327,10 +507,13 @@
}
*ends = '\0';
section = strtrim(line);
- if (!(ini = ini_section_get(top, section))) {
- ini = ini_section_new(top);
- ini->name = ACR_StrdupA(_E, THROW_NMARK, section);
+ if (!*section) {
+ /* Skip empty section names */
+ sprintf(buffer, "Empty section name at line %d", counter);
+ ACR_ThrowExceptionA(_E, THROW_NMARK, ACR_EX_EINVAL, buffer);
+ goto cleanup;
}
+ cur = ACR_IniNodeAdd(_E, ini, section, NULL);
continue;
}
else {
@@ -354,210 +537,41 @@
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);
+ attr = ACR_IniNodeAttrAdd(_E, cur, line, val);
+ if (attr->val && !nextline) {
+ attr->val = expand_envars(attr->val);
}
}
}
fclose(fp);
- return top;
+ return ini;
cleanup:
fclose(fp);
- ini_section_free(top);
+ ACR_IniFree(_E, ini);
return NULL;
}
-ACR_DECLARE(ini_section_t *) ACR_IniLoadPropertiesTree(JNIEnv *_E,
- const char *fname,
- int separator,
- int allowdups)
+ACR_DECLARE(acr_ini_t *) ACR_IniLoadProperties(JNIEnv *_E,
+ const char *fname,
+ int allowdups)
{
FILE *fp;
- ini_section_t *top = NULL;
- ini_section_t *ini = NULL;
- ini_node_t *node = NULL;
+ acr_ini_t *ini = NULL;
+ acr_ini_node_t *node = NULL;
+ acr_ini_attr_t *attr = NULL;
char buffer[ACR_PBUFF_SIZ];
int counter = 0;
int nextline = 0;
- char seps[5] = { '.', ' ', '=', ':', '\0'};
size_t slen;
if (!(fp = fopen(fname, STD_FOPEN_RDFLAGS))) {
ACR_THROW_IO_ERRNO();
return NULL;
}
- if (separator > 0)
- seps[0] = separator;
- ini = top = ini_section_new(NULL);
- while (fgets(buffer, ACR_PBUFF_SIZ, fp)) {
- char *section;
- char *line;
- char *ssep;
- char *equ;
- char *key;
- char *val = NULL;
- /* Always right trim the 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);
- slen = strlen(node->val);
- if (node->val[slen - 1] == '\\') {
- node->val[slen - 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;
- ssep = strpbrk_q(line, seps);
- if (ssep && *ssep == seps[0]) {
- char *sub;
- *(ssep++) = '\0';
- /* Get root subsection */
- section = strunesc(line);
- if (!(ini = ini_section_get(top, section))) {
- ini = ini_section_new(top);
- ini->name = ACR_StrdupA(_E, THROW_NMARK, section);
- }
- while ((sub = strpbrk_q(ssep, seps))) {
- ini_section_t *sec = ini;
- /* Check for '=' char */
- if (*sub != seps[0]) {
- /* We have found a '.' after '='
- * The dot is part of value. bail out
- */
- break;
- }
- *(sub++) = '\0';
- section = strunesc(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_q(ssep, " :="))) {
- *equ++ = '\0';
- val = strtrim_p(equ);
- slen = strlen(val);
- if (slen && val[slen - 1] == '\\') {
- val[slen - 1] = '\0';
- nextline = 1;
- }
- if (!*val)
- val = NULL;
- }
- key = strunesc(strtrim(ssep));
- if (!*key) {
- /* Skip entries without keys **/
- nextline = 0;
- continue;
- }
- if (allowdups) {
- node = ini_node_new(ini);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
- }
- else {
- if (!(node = ini_node_get(ini, key))) {
- node = ini_node_new(ini);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- }
- if (val && *val) {
- if (node->val) {
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, ", ");
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, val);
- }
- else
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
- }
- }
- if (node->val && !nextline) {
- node->val = expand_envars(node->val);
- }
- }
- else {
- if ((equ = strpbrk_q(line, " :="))) {
- *equ++ = '\0';
- val = strtrim_p(equ);
- slen = strlen(val);
- if (slen && val[slen - 1] == '\\') {
- val[slen - 1] = '\0';
- nextline = 1;
- }
- if (!*val)
- val = NULL;
- }
- key = strunesc(strtrim(line));
- if (!*key) {
- /* Skip entries without keys **/
- nextline = 0;
- continue;
- }
- if (allowdups) {
- node = ini_node_new(top);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
- }
- else {
- if (!(node = ini_node_get(top, key))) {
- node = ini_node_new(top);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- }
- if (val && *val) {
- if (node->val) {
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, ", ");
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, val);
- }
- else
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
- }
- }
- if (node->val && !nextline) {
- node->val = expand_envars(node->val);
- }
- }
- }
- fclose(fp);
- return top;
-
-}
-
-ACR_DECLARE(ini_section_t *) ACR_IniLoadProperties(JNIEnv *_E,
- const char *fname,
- int allowdups)
-{
- FILE *fp;
- ini_section_t *ini = NULL;
- ini_node_t *node = NULL;
- char buffer[ACR_PBUFF_SIZ];
- int counter = 0;
- int nextline = 0;
- size_t slen;
-
- if (!(fp = fopen(fname, STD_FOPEN_RDFLAGS))) {
- ACR_THROW_IO_ERRNO();
- return NULL;
- }
- ini = ini_section_new(NULL);
+ ini = ACR_IniNew(_E);
+ node = ACR_IniNodeRoot(ini);
+ ACR_IniNodeSetAttr(_E, node, fname);
while (fgets(buffer, ACR_PBUFF_SIZ, fp)) {
char *val = NULL;
char *key;
@@ -571,16 +585,16 @@
/* Java props are left trimmed
*/
line = ltrim(line);
- if (!node || *line == '\0')
+ if (!attr || *line == '\0')
continue;
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, line);
- slen = strlen(node->val);
- if (node->val[slen - 1] == '\\') {
- node->val[slen - 1] = '\0';
+ slen = strlen(line);
+ if (line[slen - 1] == '\\') {
+ line[slen - 1] = '\0';
nextline = 1;
}
+ ACR_IniAttrAddVal(_E, attr, line);
if (!nextline) {
- node->val = expand_envars(node->val);
+ attr->val = expand_envars(attr->val);
}
continue;
}
@@ -607,32 +621,25 @@
}
key = strunesc(line);
if (allowdups) {
- node = ini_node_new(ini);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ attr = ACR_IniNodeAttrAdd(_E, node, key, val);
}
else {
- if (!(node = ini_node_get(ini, key))) {
- node = ini_node_new(ini);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- }
- x_free(node->val);
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
+ attr = ACR_IniNodeAttrSet(_E, node, key, val);
}
- if (node->val && !nextline) {
- node->val = expand_envars(node->val);
+ if (attr->val && !nextline) {
+ attr->val = expand_envars(attr->val);
}
}
fclose(fp);
return ini;
}
-ACR_DECLARE(ini_section_t *) ACR_IniLoadConf(JNIEnv *_E, const char *fname)
+ACR_DECLARE(acr_ini_t *) ACR_IniLoadConf(JNIEnv *_E, const char *fname)
{
FILE *fp;
- ini_section_t *top = NULL;
- ini_section_t *ini = NULL;
- ini_node_t *node = NULL;
+ acr_ini_t *ini = NULL;
+ acr_ini_node_t *cur = NULL;
+ acr_ini_attr_t *attr = NULL;
char buffer[ACR_PBUFF_SIZ];
int counter = 0;
int nextline = 0;
@@ -642,7 +649,9 @@
ACR_THROW_IO_ERRNO();
return NULL;
}
- ini = top = ini_section_new(NULL);
+ ini = ACR_IniNew(NULL);
+ cur = ACR_IniNodeRoot(ini);
+ ACR_IniNodeSetAttr(_E, cur, fname);
while (fgets(buffer, ACR_PBUFF_SIZ, fp)) {
char *section;
char *line;
@@ -657,16 +666,16 @@
/* Java props are left trimmed
*/
line = ltrim(line);
- if (!node || *line == '\0')
+ if (!attr || *line == '\0')
continue;
- node->val = ACR_StrcatA(_E, THROW_NMARK, node->val, line);
- slen = strlen(node->val);
- if (node->val[slen - 1] == '\\') {
- node->val[slen - 1] = '\0';
+ slen = strlen(line);
+ if (line[slen - 1] == '\\') {
+ line[slen - 1] = '\0';
nextline = 1;
}
+ ACR_IniAttrAddVal(_E, attr, line);
if (!nextline) {
- node->val = expand_envars(node->val);
+ attr->val = expand_envars(attr->val);
}
continue;
}
@@ -685,25 +694,24 @@
}
*ends = '\0';
section = strunesc(strtrim(line + 2));
- if (!ini->name || strcasecmp(section, ini->name)) {
+ if (!cur->name || strcasecmp(section, cur->name)) {
sprintf(buffer, "Found </%s> while expecting </%s> at line %d",
- section, ini->name ? ini->name : "(null)",
+ section, cur->name ? cur->name : "(null)",
counter);
ACR_ThrowExceptionA(_E, THROW_NMARK, ACR_EX_EINVAL, buffer);
+ fprintf(stderr, "%s\n", buffer);
goto cleanup;
}
- ini = ini->parent;
- if (!ini)
- ini = top;
+ cur = ACR_IniSetParentAsCurrent(ini, cur);
}
else if (*line == '<') {
/* New section
*/
- ini_section_t *sec;
char *ends = strpbrk_q(++line, ">");
if (!ends) {
sprintf(buffer, "Unterminated section at line %d", counter);
ACR_ThrowExceptionA(_E, THROW_NMARK, ACR_EX_EINVAL, buffer);
+ fprintf(stderr, "%s\n", buffer);
goto cleanup;
}
*ends = '\0';
@@ -715,12 +723,7 @@
val = NULL;
}
section = strunesc(section);
- if (!(sec = ini_section_get(ini, section))) {
- sec = ini_child_new(ini);
- sec->name = ACR_StrdupA(_E, THROW_NMARK, section);
- sec->attr = ACR_StrdupA(_E, THROW_NMARK, val);
- }
- ini = sec;
+ cur = ACR_IniNodeSet(_E, ini, section, val);
}
else {
if ((equ = strpbrk_q(line, " ="))) {
@@ -740,20 +743,18 @@
nextline = 0;
continue;
}
- node = ini_node_new(ini);
- node->key = ACR_StrdupA(_E, THROW_NMARK, key);
- node->val = ACR_StrdupA(_E, THROW_NMARK, val);
- if (node->val && !nextline) {
- node->val = expand_envars(node->val);
+ attr = ACR_IniNodeAttrAdd(_E, cur, key, val);
+ if (attr->val && !nextline) {
+ attr->val = expand_envars(attr->val);
}
}
}
fclose(fp);
- return top;
+ return ini;
cleanup:
fclose(fp);
- ini_section_free(top);
+ ACR_IniFree(_E, ini);
return NULL;
}
Modified: 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=807319&r1=807318&r2=807319&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/sample.ini (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/sample.ini Mon Aug 24 17:55:04 2009
@@ -20,12 +20,12 @@
[second section]
#sections don't need to have any nodes
-[]
+[empty]
; this is comment
# this is comment as well
; comment is first non space character
-empty = section names are allowed
+empty = section names are not allowed
=
==
===
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=807319&r1=807318&r2=807319&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Mon Aug 24 17:55:04 2009
@@ -37,6 +37,7 @@
#include "acr_env.h"
#include "acr_io.h"
#include "acr_dso.h"
+#include "acr_ring.h"
#include "acr_ini.h"
#include "acr_version.h"
@@ -247,77 +248,47 @@
return 0;
}
-static int test_msini(int argc, const char *const argv[])
+static void dump_ini_attr(acr_ini_node_t *node, int level)
{
- 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_ini_attr_t *ap;
+ ACR_RING_FOREACH(ap, &node->attr_ring, acr_ini_attr_t, link) {
+ fprintf(stdout, "%*s%s -> %s\n", level, "", ap->key, ap->val);
}
- ACR_IniTableFree(top);
-
- return 0;
}
-static void dump_ini_section(ini_section_t *ini, int level)
+static void dump_ini_node(acr_ini_node_t *node, int level)
{
- while (ini) {
- ini_node_t *node = ini->nodes;
- fprintf(stdout, "%*sSection [%s]%s\n", level, "", ini->name,
- ini->attr ? ini->attr : "");
- 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;
+ acr_ini_node_t *np;
+
+ fprintf(stdout, "%*sSection [%s] %s\n", level, "", node->name,
+ node->attr ? node->attr : "");
+ dump_ini_attr(node, level + 2);
+ ACR_RING_FOREACH(np, &node->node_ring, acr_ini_node_t, link) {
+ dump_ini_node(np, level + 2);
}
}
-static int test_props(int argc, const char *const argv[])
+static int test_msini(int argc, const char *const argv[])
{
- ini_section_t *ini;
- ini_section_t *top;
- int allowdups = 0;
-
- if (argv[0][0] == '+') {
- allowdups = 1;
- --argc;
- ++argv;
- }
+ acr_ini_t *top;
if (argc < 1)
return 1;
- ini = ACR_IniLoadProperties(NULL, argv[0], allowdups);
- fprintf(stdout, "Using Property `%s\'\n", argv[0]);
- top = ini;
- dump_ini_section(ini, 0);
- ACR_IniTableFree(top);
+ top = ACR_IniLoadIni(NULL, argv[0]);
+
+ if (top) {
+ dump_ini_node(ACR_IniNodeRoot(top), 0);
+ ACR_IniFree(NULL, top);
+ }
+ printf("Ms INI OK\n");
return 0;
}
-static int test_ptree(int argc, const char *const argv[])
+
+static int test_props(int argc, const char *const argv[])
{
- ini_section_t *ini;
- ini_section_t *top;
+ acr_ini_t *ini;
int allowdups = 0;
if (argv[0][0] == '+') {
@@ -327,29 +298,65 @@
}
if (argc < 1)
return 1;
-
- ini = ACR_IniLoadPropertiesTree(NULL, argv[0], '.', allowdups);
+ ini = ACR_IniLoadProperties(NULL, argv[0], allowdups);
fprintf(stdout, "Using Property `%s\'\n", argv[0]);
- top = ini;
- dump_ini_section(ini, 0);
- ACR_IniTableFree(top);
+
+ dump_ini_node(ACR_IniNodeRoot(ini), 0);
+ ACR_IniFree(NULL, ini);
return 0;
}
static int test_conf(int argc, const char *const argv[])
{
- ini_section_t *ini;
- ini_section_t *top;
+ acr_ini_t *top;
if (argc < 1)
return 1;
- ini = ACR_IniLoadConf(NULL, argv[0]);
- fprintf(stdout, "Using Conf `%s\'\n", argv[0]);
- top = ini;
- dump_ini_section(ini, 0);
- ACR_IniTableFree(top);
+ top = ACR_IniLoadConf(NULL, argv[0]);
+ printf("Loaded OK %p\n", top);
+ if (top) {
+ dump_ini_node(ACR_IniNodeRoot(top), 0);
+ ACR_IniFree(NULL, top);
+ }
+ printf("Conf OK\n");
+ return 0;
+}
+
+static int test_ring(int argc, const char *const argv[])
+{
+ acr_ini_t *top;
+
+ acr_ini_node_t *ini;
+ acr_ini_node_t *is1;
+ acr_ini_node_t *is2;
+ acr_ini_node_t *p;
+
+ top = ACR_IniNew(NULL);
+
+ ini = ACR_IniNodeSet(NULL, top, "node1", NULL);
+ ACR_IniSetCurrent(top, ini);
+ is1 = ACR_IniNodeSet(NULL, top, "node2", NULL);
+ is2 = ACR_IniNodeSet(NULL, top, "node3", NULL);
+
+ for (p = ACR_RING_FIRST(&(ini->node_ring));
+ p != ACR_RING_SENTINEL(&(ini->node_ring), acr_ini_node_t, link);
+ p = ACR_RING_NEXT(p, link)) {
+ printf("INI %s\n", p->name);
+ }
+ for (p = ACR_RING_FIRST(&(is1->node_ring));
+ p != ACR_RING_SENTINEL(&(is1->node_ring), acr_ini_node_t, link);
+ p = ACR_RING_NEXT(p, link)) {
+ printf("IS1 %s\n", p->name);
+ }
+ for (p = ACR_RING_FIRST(&(is2->node_ring));
+ p != ACR_RING_SENTINEL(&(is2->node_ring), acr_ini_node_t, link);
+ p = ACR_RING_NEXT(p, link)) {
+ printf("IS2 %s\n", p->name);
+ }
+ ACR_IniFree(NULL, top);
+ fprintf(stdout, "ring test: OK\n");
return 0;
}
@@ -418,12 +425,12 @@
else if (!strcasecmp(run_test, "props")) {
rv = test_props(argc, argv);
}
- else if (!strcasecmp(run_test, "ptree")) {
- rv = test_ptree(argc, argv);
- }
else if (!strcasecmp(run_test, "conf")) {
rv = test_conf(argc, argv);
}
+ else if (!strcasecmp(run_test, "ring")) {
+ rv = test_ring(argc, argv);
+ }
}
cleanup: