aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-20 15:52:18 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-09-20 15:52:18 +0300
commit7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (patch)
tree422bda7fdce2709ea0b4c67c42e6f9a7cecc4918
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.
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/libeclat.h16
-rw-r--r--lib/xmltree.c188
-rw-r--r--src/eclat.c73
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/testsuite.at4
-rw-r--r--tests/txml.c88
-rw-r--r--tests/xml01.at63
9 files changed, 438 insertions, 6 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=\
28 reqsign.c\ 28 reqsign.c\
29 sha1.c\ 29 sha1.c\
30 sha1.h\ 30 sha1.h\
31 urlencode.c 31 urlencode.c\
32 xmltree.c
32 33
33AM_LDFLAGS = $(CURL_LIBS) 34AM_LDFLAGS = $(CURL_LIBS)
34INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS) 35INCLUDES = -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 @@
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */ 15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16 16
17#include <stddef.h> 17#include <stddef.h>
18#include <expat.h>
19#include "grecs.h"
18 20
19void hmac_sha1(const void *text, size_t textlen, 21void hmac_sha1(const void *text, size_t textlen,
20 const void *key, size_t keylen, 22 const void *key, size_t keylen,
@@ -56,4 +58,16 @@ int eclat_query_signature(struct ec2_query *req, char *secret);
56char *eclat_query_to_url(struct ec2_query *req, char **post_params); 58char *eclat_query_to_url(struct ec2_query *req, char **post_params);
57 59
58void eclat_query_encode(struct ec2_query *q); 60void eclat_query_encode(struct ec2_query *q);
59 61
62typedef struct eclat_partial_tree *eclat_partial_tree_t;
63
64eclat_partial_tree_t eclat_partial_tree_create(void);
65void eclat_partial_tree_destroy(eclat_partial_tree_t);
66struct grecs_node *eclat_partial_tree_finish(eclat_partial_tree_t);
67void eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len);
68void eclat_partial_tree_start_handler(void *data, const XML_Char *name,
69 const XML_Char **atts);
70void eclat_partial_tree_end_handler(void *data, const XML_Char *name);
71
72
73
diff --git a/lib/xmltree.c b/lib/xmltree.c
new file mode 100644
index 0000000..e5d4772
--- /dev/null
+++ b/lib/xmltree.c
@@ -0,0 +1,188 @@
1/* This file is part of Eclat
2 Copyright (C) 2012 Sergey Poznyakoff
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <config.h>
18#include "libeclat.h"
19
20#define NODEREF_TEXT 0x01 /* Text is being constructed */
21
22struct eclat_partial_tree {
23 int flags;
24 struct grecs_txtacc *acc;
25 struct grecs_symtab *texttab;
26 struct grecs_list *stack; /* Node stack */
27};
28
29static void
30pt_free_node(void *ptr)
31{
32 struct grecs_node *node = ptr;
33 grecs_node_free(node);
34}
35
36struct eclat_partial_tree *
37eclat_partial_tree_create()
38{
39 struct eclat_partial_tree *pt = grecs_zalloc(sizeof(*pt));
40 pt->acc = grecs_txtacc_create();
41 pt->stack = grecs_list_create();
42 pt->stack->free_entry = pt_free_node;
43 return pt;
44}
45
46void
47eclat_partial_tree_destroy(struct eclat_partial_tree *pt)
48{
49 grecs_txtacc_free(pt->acc);
50 if (pt->texttab)
51 grecs_symtab_free(pt->texttab);
52 grecs_list_free(pt->stack);
53 free(pt);
54}
55
56struct grecs_node *
57eclat_partial_tree_finish(struct eclat_partial_tree *pt)
58{
59 struct grecs_node *root = grecs_node_create(grecs_node_root, NULL);
60 root->v.texttab = pt->texttab;
61 pt->texttab = NULL;
62 grecs_node_bind(root, grecs_list_pop(pt->stack), 1);
63 eclat_partial_tree_destroy(pt);
64 return root;
65}
66
67
68static char *
69install_text(struct eclat_partial_tree *nref, const char *str)
70{
71 struct grecs_syment key;
72 struct grecs_syment *ent;
73 int install = 1;
74
75 if (!nref->texttab) {
76 nref->texttab = grecs_symtab_create_default(
77 sizeof(struct grecs_syment));
78 if (!nref->texttab)
79 grecs_alloc_die();
80 }
81
82 key.name = (char*) str;
83 ent = grecs_symtab_lookup_or_install(nref->texttab, &key, &install);
84 if (!ent)
85 grecs_alloc_die();
86 return ent->name;
87}
88
89static struct grecs_node *
90gettos(struct eclat_partial_tree *nref)
91{
92 if (nref->stack->head)
93 return nref->stack->head->data;
94 return NULL;
95}
96
97void
98eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len)
99{
100 struct eclat_partial_tree *noderef = data;
101
102 grecs_txtacc_grow(noderef->acc, s, len);
103 noderef->flags |= NODEREF_TEXT;
104}
105
106/* Start handler: create a node and push it on stack */
107void
108eclat_partial_tree_start_handler(void *data, const XML_Char *name,
109 const XML_Char **atts)
110{
111 struct eclat_partial_tree *noderef = data;
112 struct grecs_node *node;
113
114 if (noderef->flags & NODEREF_TEXT) {
115 grecs_txtacc_free_string(noderef->acc,
116 grecs_txtacc_finish(noderef->acc, 0));
117 noderef->flags &= ~NODEREF_TEXT;
118 }
119
120 node = grecs_node_create((enum grecs_node_type)-1, NULL);
121 node->ident = grecs_strdup(name);
122 grecs_list_push(noderef->stack, node);
123 noderef->flags &= ~NODEREF_TEXT;
124}
125
126void
127eclat_partial_tree_end_handler(void *data, const XML_Char *name)
128{
129 struct eclat_partial_tree *noderef = data;
130 struct grecs_node *node = grecs_list_pop(noderef->stack);
131 struct grecs_node *tos = gettos(noderef);
132
133 if (noderef->flags & NODEREF_TEXT) {
134 char *s, *p;
135 grecs_value_t *ptr;
136
137 grecs_txtacc_grow_char(noderef->acc, 0);
138 s = grecs_txtacc_finish(noderef->acc, 1);
139
140 for (p = s; *p && isspace(*p); p++)
141 ;
142 if (!*p) {
143 free(s);
144 if (node->type == -1)
145 node->type = grecs_node_block;
146 } else {
147 switch (node->type) {
148 default:
149 node->type = grecs_node_stmt;
150 ptr = grecs_malloc(sizeof(*ptr));
151 ptr->type = GRECS_TYPE_STRING;
152 ptr->v.string = s;
153 node->v.value = ptr;
154 break;
155
156 case grecs_node_root:
157 abort(); /* should not happen */
158
159 case grecs_node_stmt:
160 case grecs_node_block:
161 /* FIXME: error message */
162 /* ignoring additional textual data */
163 free(s);
164 }
165 }
166 noderef->flags &= ~NODEREF_TEXT;
167 }
168
169 if (!tos)
170 grecs_list_push(noderef->stack, node);
171 else {
172 switch (tos->type) {
173 default:
174 tos->type = grecs_node_block;
175 break;
176 case grecs_node_root:
177 abort(); /* should not happen */
178 case grecs_node_stmt:
179 /* FIXME: error message */
180 /* ignoring additional textual data */
181 grecs_value_free(tos->v.value);