diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-20 15:52:18 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-20 15:52:18 +0300 |
commit | 7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (patch) | |
tree | 422bda7fdce2709ea0b4c67c42e6f9a7cecc4918 | |
parent | 205d53a8e930d3fd126075ab083d316cc344ebaf (diff) | |
download | eclat-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.am | 3 | ||||
-rw-r--r-- | lib/libeclat.h | 16 | ||||
-rw-r--r-- | lib/xmltree.c | 188 | ||||
-rw-r--r-- | src/eclat.c | 73 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 8 | ||||
-rw-r--r-- | tests/testsuite.at | 4 | ||||
-rw-r--r-- | tests/txml.c | 88 | ||||
-rw-r--r-- | tests/xml01.at | 63 |
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 | ||
33 | AM_LDFLAGS = $(CURL_LIBS) | 34 | AM_LDFLAGS = $(CURL_LIBS) |
34 | INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS) | 35 | 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 @@ | |||
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 | ||
19 | void hmac_sha1(const void *text, size_t textlen, | 21 | void 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); | |||
56 | char *eclat_query_to_url(struct ec2_query *req, char **post_params); | 58 | char *eclat_query_to_url(struct ec2_query *req, char **post_params); |
57 | 59 | ||
58 | void eclat_query_encode(struct ec2_query *q); | 60 | void eclat_query_encode(struct ec2_query *q); |
59 | 61 | ||
62 | typedef struct eclat_partial_tree *eclat_partial_tree_t; | ||
63 | |||
64 | eclat_partial_tree_t eclat_partial_tree_create(void); | ||
65 | void eclat_partial_tree_destroy(eclat_partial_tree_t); | ||
66 | struct grecs_node *eclat_partial_tree_finish(eclat_partial_tree_t); | ||
67 | void eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len); | ||
68 | void eclat_partial_tree_start_handler(void *data, const XML_Char *name, | ||
69 | const XML_Char **atts); | ||
70 | void 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 | |||
22 | struct 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 | |||
29 | static void | ||
30 | pt_free_node(void *ptr) | ||
31 | { | ||
32 | struct grecs_node *node = ptr; | ||
33 | grecs_node_free(node); | ||
34 | } | ||
35 | |||
36 | struct eclat_partial_tree * | ||
37 | eclat_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 | |||
46 | void | ||
47 | eclat_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 | |||
56 | struct grecs_node * | ||
57 | eclat_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 | |||
68 | static char * | ||
69 | install_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 | |||
89 | static struct grecs_node * | ||
90 | gettos(struct eclat_partial_tree *nref) | ||
91 | { | ||
92 | if (nref->stack->head) | ||
93 | return nref->stack->head->data; | ||
94 | return NULL; | ||
95 | } | ||
96 | |||
97 | void | ||
98 | eclat_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 */ | ||
107 | void | ||
108 | eclat_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 | |||
126 | void | ||
127 | eclat_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); | ||