* replaced __thread with pthread_key_t/pthread_setspecific
[strongswan.git] / src / manager / lib / xml.c
1 /**
2 * @file xml.c
3 *
4 * @brief Implementation of xml_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "xml.h"
24
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27
28
29 typedef struct private_xml_t private_xml_t;
30
31 /**
32 * private data of xml
33 */
34 struct private_xml_t {
35
36 /**
37 * public functions
38 */
39 xml_t public;
40
41 /**
42 * root node of this xml (part)
43 */
44 xmlNode *node;
45
46 /**
47 * document, only for root xml_t
48 */
49 xmlDoc *doc;
50
51 /**
52 * Root xml_t*
53 */
54 private_xml_t *root;
55
56 /**
57 * number of enumerator instances
58 */
59 int enums;
60 };
61
62 /**
63 * child element enumerator
64 */
65 typedef struct {
66 /** enumerator interface */
67 enumerator_t e;
68 /** current child context (returned to enumerate() caller) */
69 private_xml_t child;
70 /** currently processing node */
71 xmlNode *node;
72 } child_enum_t;
73
74 /**
75 * Implementation of xml_t.children().enumerate().
76 */
77 static bool child_enumerate(child_enum_t *e, private_xml_t **child,
78 char **name, char **value)
79 {
80 while (e->node && e->node->type != XML_ELEMENT_NODE)
81 {
82 e->node = e->node->next;
83 }
84 if (e->node)
85 {
86 xmlNode *text;
87
88 text = e->node->children;
89 *value = NULL;
90
91 while (text && text->type != XML_TEXT_NODE)
92 {
93 text = text->next;
94 }
95 if (text)
96 {
97 *value = text->content;
98 }
99 *name = (char*)e->node->name;
100 *child = &e->child;
101 e->child.node = e->node->children;
102 e->node = e->node->next;
103 return TRUE;
104 }
105 return FALSE;
106 }
107
108 /**
109 * Implementation of xml_t.get_attribute.
110 */
111 static char* get_attribute(private_xml_t *this, char *name)
112 {
113 return NULL;
114 }
115
116 /**
117 * destroy enumerator, and complete tree if this was the last enumerator
118 */
119 static void child_destroy(child_enum_t *this)
120 {
121 if (--this->child.root->enums == 0)
122 {
123 xmlFreeDoc(this->child.root->doc);
124 free(this->child.root);
125 }
126 free(this);
127 }
128
129 /**
130 * Implementation of xml_t.children.
131 */
132 static enumerator_t* children(private_xml_t *this)
133 {
134 child_enum_t *ce = malloc_thing(child_enum_t);
135 ce->e.enumerate = (void*)child_enumerate;
136 ce->e.destroy = (void*)child_destroy;
137 ce->node = this->node;
138 ce->child.public.children = (void*)children;
139 ce->child.public.get_attribute = (void*)get_attribute;
140 ce->child.node = NULL;
141 ce->child.doc = this->doc;
142 ce->child.root = this->root;
143 this->root->enums++;
144 return &ce->e;
145 }
146
147 /*
148 * see header file
149 */
150 xml_t *xml_create(char *xml)
151 {
152 private_xml_t *this = malloc_thing(private_xml_t);
153
154 this->public.get_attribute = (char*(*)(xml_t*,char*))get_attribute;
155 this->public.children = (enumerator_t*(*)(xml_t*))children;
156
157 this->doc = xmlReadMemory(xml, strlen(xml), NULL, NULL, 0);
158 if (this->doc == NULL)
159 {
160 free(this);
161 return NULL;
162 }
163 this->node = xmlDocGetRootElement(this->doc);
164 this->root = this;
165 this->enums = 0;
166
167 return &this->public;
168 }
169