]> git.mxchange.org Git - flightgear.git/blob - utils/xmlgrep/xml_cache.c
Merge branch 'ehofman/version'
[flightgear.git] / utils / xmlgrep / xml_cache.c
1 /* Copyright (c) 2007-2009 by Adalin B.V.
2  * Copyright (c) 2007-2009 by Erik Hofman
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *      * Redistributions of source code must retain the above copyright
8  *         notice, this list of conditions and the following disclaimer.
9  *      * Redistributions in binary form must reproduce the above copyright
10  *         notice, this list of conditions and the following disclaimer in the
11  *         documentation and/or other materials provided with the distribution.
12  *      * Neither the name of (any of) the copyrightholder(s) nor the
13  *         names of its contributors may be used to endorse or promote products
14  *         derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <assert.h>
32
33 #include "xml.h"
34
35 #ifndef NDEBUG
36 # define PRINT(a, b, c) { \
37    size_t l1 = (b), l2 = (c); \
38    char *s = (a); \
39    if (s) { \
40       size_t q, len = l2; \
41       if (l1 < l2) len = l1; \
42       if (len < 50000) { \
43          printf("(%i) '", len); \
44          for (q=0; q<len; q++) printf("%c", s[q]); \
45          printf("'\n"); \
46       } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
47    } else printf("NULL pointer at line %i\n", __LINE__); \
48 }
49 #endif
50
51 #if !defined(XML_USE_NODECACHE)
52 void *
53 cacheNodeGet(void *id, const char *node)
54 {
55     return 0;
56 }
57
58 #else
59
60 #define NODE_BLOCKSIZE          16
61
62 struct _xml_node
63 {
64     void *parent;
65     char *name;
66     size_t name_len;
67     char *data;
68     size_t data_len;
69     void **node;
70     size_t no_nodes;
71     size_t first_free;
72 };
73
74 char *
75 __xmlNodeGetFromCache(void **nc, const char *start, size_t *len,
76                       char **element, size_t *elementlen , size_t *nodenum)
77 {
78     struct _xml_node *cache;
79     size_t num = *nodenum;
80     char *name = *element;
81     void *rv = 0;
82
83     assert(nc != 0);
84  
85     cache = (struct _xml_node *)*nc;
86     assert(cache != 0);
87
88     assert((cache->first_free > num) || (cache->first_free == 0));
89
90     if (cache->first_free == 0) /* leaf node */
91     {
92         rv = cache->data;
93         *len = cache->data_len;
94         *element = cache->name;
95         *elementlen = cache->name_len;
96         *nodenum = 0;
97     }
98     else if (*name == '*')
99     {
100         struct _xml_node *node = cache->node[num];
101         *nc = node;
102         rv = node->data;
103         *len = node->data_len;
104         *element = node->name;
105         *elementlen = node->name_len;
106         *nodenum = cache->first_free;
107     }
108     else
109     {
110         size_t namelen = *elementlen;
111         size_t i, pos = 0;
112
113         for (i=0; i<cache->first_free; i++)
114         {
115             struct _xml_node *node = cache->node[i];
116
117             assert(node);
118
119             if ((node->name_len == namelen) &&
120                 (!strncasecmp(node->name, name, namelen)))
121             {
122                  if (pos == num)
123                  {
124                      *nc = node;
125                      rv = node->data;
126                      *element = node->name;
127                      *elementlen = node->name_len;
128                      *len = node->data_len;
129                      *nodenum = cache->first_free;
130                      break;
131                  }
132                  pos++;
133             }
134         }
135     }
136
137     return rv;
138 }
139
140
141 void *
142 cacheInit()
143 {
144    return calloc(1, sizeof(struct _xml_node));
145 }
146
147 void
148 cacheInitLevel(void *nc)
149 {
150     struct _xml_node *cache = (struct _xml_node *)nc;
151
152     assert(cache != 0);
153
154     cache->node = calloc(NODE_BLOCKSIZE, sizeof(struct _xml_node *));
155     cache->no_nodes = NODE_BLOCKSIZE;
156 }
157
158 void
159 cacheFree(void *nc)
160 {
161     struct _xml_node *cache = (struct _xml_node *)nc;
162
163     assert(nc != 0);
164
165     if (cache->first_free)
166     {
167         struct _xml_node **node = (struct _xml_node **)cache->node;
168         size_t i = 0;
169
170         while(i < cache->first_free)
171         {
172             cacheFree(node[i++]);
173         }
174
175         free(node);
176     }
177     free(cache);
178 }
179
180 void *
181 cacheNodeGet(void *id)
182 {
183     struct _xml_id *xid = (struct _xml_id *)id;
184     struct _xml_node *cache = 0;
185
186     assert(xid != 0);
187
188     if (xid->name)
189     {
190         cache = xid->node;
191     }
192     else
193     {
194         struct _root_id *rid = (struct _root_id *)xid;
195         cache = rid->node;
196     }
197
198     return cache;
199 }
200
201 void *
202 cacheNodeNew(void *nc)
203 {
204     struct _xml_node *cache = (struct _xml_node *)nc;
205     struct _xml_node *rv = 0;
206     size_t i = 0;
207
208     assert(nc != 0);
209
210     i = cache->first_free;
211     if (i == cache->no_nodes)
212     {
213         size_t size, no_nodes;
214         void *p;
215
216         no_nodes = cache->no_nodes + NODE_BLOCKSIZE;
217         size = no_nodes * sizeof(struct _xml_node *);
218         p = realloc(cache->node, size);
219         if (!p) return 0;
220
221         cache->node = p;
222         cache->no_nodes = no_nodes;
223     }
224
225     rv = calloc(1, sizeof(struct _xml_node));
226     if (rv) rv->parent = cache;
227     cache->node[i] = rv;
228     cache->first_free++;
229
230     return rv;
231 }
232
233 void
234 cacheDataSet(void *n, char *name, size_t namelen, char *data, size_t datalen)
235 {
236    struct _xml_node *node = (struct _xml_node *)n;
237
238    assert(node != 0);
239    assert(name != 0);
240    assert(namelen != 0);
241    assert(data != 0);
242
243    node->name = name;
244    node->name_len = namelen;
245    node->data = data;
246    node->data_len = datalen;
247 }
248
249 #endif
250