summaryrefslogtreecommitdiffabout
path: root/lib
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-20 12:52:18 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2012-09-20 12:52:18 (GMT)
commit7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (patch) (side-by-side diff)
tree422bda7fdce2709ea0b4c67c42e6f9a7cecc4918 /lib
parent205d53a8e930d3fd126075ab083d316cc344ebaf (diff)
downloadeclat-7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee.tar.gz
eclat-7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee.tar.bz2
Parse returned XML into a grecs tree structure.
* lib/xmltree.c: New file. * lib/Makefile.am: Add new file. * lib/libeclat.h: Include expat.h and grecs.h (eclat_partial_tree_t): New typedef. (eclat_partial_tree_create,eclat_partial_tree_destroy) (eclat_partial_tree_finish,eclat_partial_tree_data_handler) (eclat_partial_tree_start_handler) (eclat_partial_tree_end_handler): New protos. * src/eclat.c (main): Initialize XML parser with eclat_partial_tree handlers and bind it to the CURL output handler. * tests/.gitignore: Add txml * tests/Makefile.am (TESTSUITE_AT): Add xml01.at Build txml * tests/testsuite.at: Include xml01.at * tests/txml.c: New file. * tests/xml01.at: New file.
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/libeclat.h16
-rw-r--r--lib/xmltree.c188
3 files changed, 205 insertions, 2 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 7843433..2c1d3a8 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -28,7 +28,8 @@ libeclat_a_SOURCES=\
reqsign.c\
sha1.c\
sha1.h\
- urlencode.c
+ urlencode.c\
+ xmltree.c
AM_LDFLAGS = $(CURL_LIBS)
INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS)
diff --git a/lib/libeclat.h b/lib/libeclat.h
index 59ff0f6..670c51b 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -15,6 +15,8 @@
along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
#include <stddef.h>
+#include <expat.h>
+#include "grecs.h"
void hmac_sha1(const void *text, size_t textlen,
const void *key, size_t keylen,
@@ -56,4 +58,16 @@ int eclat_query_signature(struct ec2_query *req, char *secret);
char *eclat_query_to_url(struct ec2_query *req, char **post_params);
void eclat_query_encode(struct ec2_query *q);
-
+
+typedef struct eclat_partial_tree *eclat_partial_tree_t;
+
+eclat_partial_tree_t eclat_partial_tree_create(void);
+void eclat_partial_tree_destroy(eclat_partial_tree_t);
+struct grecs_node *eclat_partial_tree_finish(eclat_partial_tree_t);
+void eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len);
+void eclat_partial_tree_start_handler(void *data, const XML_Char *name,
+ const XML_Char **atts);
+void eclat_partial_tree_end_handler(void *data, const XML_Char *name);
+
+
+
diff --git a/lib/xmltree.c b/lib/xmltree.c
new file mode 100644
index 0000000..e5d4772
--- a/dev/null
+++ b/lib/xmltree.c
@@ -0,0 +1,188 @@
+/* This file is part of Eclat
+ Copyright (C) 2012 Sergey Poznyakoff
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include "libeclat.h"
+
+#define NODEREF_TEXT 0x01 /* Text is being constructed */
+
+struct eclat_partial_tree {
+ int flags;
+ struct grecs_txtacc *acc;
+ struct grecs_symtab *texttab;
+ struct grecs_list *stack; /* Node stack */
+};
+
+static void
+pt_free_node(void *ptr)
+{
+ struct grecs_node *node = ptr;
+ grecs_node_free(node);
+}
+
+struct eclat_partial_tree *
+eclat_partial_tree_create()
+{
+ struct eclat_partial_tree *pt = grecs_zalloc(sizeof(*pt));
+ pt->acc = grecs_txtacc_create();
+ pt->stack = grecs_list_create();
+ pt->stack->free_entry = pt_free_node;
+ return pt;
+}
+
+void
+eclat_partial_tree_destroy(struct eclat_partial_tree *pt)
+{
+ grecs_txtacc_free(pt->acc);
+ if (pt->texttab)
+ grecs_symtab_free(pt->texttab);
+ grecs_list_free(pt->stack);
+ free(pt);
+}
+
+struct grecs_node *
+eclat_partial_tree_finish(struct eclat_partial_tree *pt)
+{
+ struct grecs_node *root = grecs_node_create(grecs_node_root, NULL);
+ root->v.texttab = pt->texttab;
+ pt->texttab = NULL;
+ grecs_node_bind(root, grecs_list_pop(pt->stack), 1);
+ eclat_partial_tree_destroy(pt);
+ return root;
+}
+
+
+static char *
+install_text(struct eclat_partial_tree *nref, const char *str)
+{
+ struct grecs_syment key;
+ struct grecs_syment *ent;
+ int install = 1;
+
+ if (!nref->texttab) {
+ nref->texttab = grecs_symtab_create_default(
+ sizeof(struct grecs_syment));
+ if (!nref->texttab)
+ grecs_alloc_die();
+ }
+
+ key.name = (char*) str;
+ ent = grecs_symtab_lookup_or_install(nref->texttab, &key, &install);
+ if (!ent)
+ grecs_alloc_die();
+ return ent->name;
+}
+
+static struct grecs_node *
+gettos(struct eclat_partial_tree *nref)
+{
+ if (nref->stack->head)
+ return nref->stack->head->data;
+ return NULL;
+}
+
+void
+eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len)
+{
+ struct eclat_partial_tree *noderef = data;
+
+ grecs_txtacc_grow(noderef->acc, s, len);
+ noderef->flags |= NODEREF_TEXT;
+}
+
+/* Start handler: create a node and push it on stack */
+void
+eclat_partial_tree_start_handler(void *data, const XML_Char *name,
+ const XML_Char **atts)
+{
+ struct eclat_partial_tree *noderef = data;
+ struct grecs_node *node;
+
+ if (noderef->flags & NODEREF_TEXT) {
+ grecs_txtacc_free_string(noderef->acc,
+ grecs_txtacc_finish(noderef->acc, 0));
+ noderef->flags &= ~NODEREF_TEXT;
+ }
+
+ node = grecs_node_create((enum grecs_node_type)-1, NULL);
+ node->ident = grecs_strdup(name);
+ grecs_list_push(noderef->stack, node);
+ noderef->flags &= ~NODEREF_TEXT;
+}
+
+void
+eclat_partial_tree_end_handler(void *data, const XML_Char *name)
+{
+ struct eclat_partial_tree *noderef = data;
+ struct grecs_node *node = grecs_list_pop(noderef->stack);
+ struct grecs_node *tos = gettos(noderef);
+
+ if (noderef->flags & NODEREF_TEXT) {
+ char *s, *p;
+ grecs_value_t *ptr;
+
+ grecs_txtacc_grow_char(noderef->acc, 0);
+ s = grecs_txtacc_finish(noderef->acc, 1);
+
+ for (p = s; *p && isspace(*p); p++)
+ ;
+ if (!*p) {
+ free(s);
+ if (node->type == -1)
+ node->type = grecs_node_block;
+ } else {
+ switch (node->type) {
+ default:
+ node->type = grecs_node_stmt;
+ ptr = grecs_malloc(sizeof(*ptr));
+ ptr->type = GRECS_TYPE_STRING;
+ ptr->v.string = s;
+ node->v.value = ptr;
+ break;
+
+ case grecs_node_root:
+ abort(); /* should not happen */
+
+ case grecs_node_stmt:
+ case grecs_node_block:
+ /* FIXME: error message */
+ /* ignoring additional textual data */
+ free(s);
+ }
+ }
+ noderef->flags &= ~NODEREF_TEXT;
+ }
+
+ if (!tos)
+ grecs_list_push(noderef->stack, node);
+ else {
+ switch (tos->type) {
+ default:
+ tos->type = grecs_node_block;
+ break;
+ case grecs_node_root:
+ abort(); /* should not happen */
+ case grecs_node_stmt:
+ /* FIXME: error message */
+ /* ignoring additional textual data */
+ grecs_value_free(tos->v.value);
+ tos->type = grecs_node_block;
+ break;
+ }
+
+ grecs_node_bind(tos, node, 1);
+ }
+}

Return to:

Send suggestions and report system problems to the System administrator.