1*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
2*6777b538SAndroid Build Coastguard Worker #include <string.h>
3*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
4*6777b538SAndroid Build Coastguard Worker #include <libxml/dict.h>
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker /**** dictionary tests ****/
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #ifdef __clang__
10*6777b538SAndroid Build Coastguard Worker #if __clang_major__ >= 12
11*6777b538SAndroid Build Coastguard Worker #define ATTRIBUTE_NO_SANITIZE_INTEGER \
12*6777b538SAndroid Build Coastguard Worker __attribute__ ((no_sanitize("unsigned-integer-overflow"))) \
13*6777b538SAndroid Build Coastguard Worker __attribute__ ((no_sanitize("unsigned-shift-base")))
14*6777b538SAndroid Build Coastguard Worker #else
15*6777b538SAndroid Build Coastguard Worker #define ATTRIBUTE_NO_SANITIZE_INTEGER \
16*6777b538SAndroid Build Coastguard Worker __attribute__ ((no_sanitize("unsigned-integer-overflow")))
17*6777b538SAndroid Build Coastguard Worker #endif
18*6777b538SAndroid Build Coastguard Worker #else
19*6777b538SAndroid Build Coastguard Worker #define ATTRIBUTE_NO_SANITIZE_INTEGER
20*6777b538SAndroid Build Coastguard Worker #endif
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker /* #define WITH_PRINT */
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker static const char *seeds1[] = {
25*6777b538SAndroid Build Coastguard Worker "a", "b", "c",
26*6777b538SAndroid Build Coastguard Worker "d", "e", "f",
27*6777b538SAndroid Build Coastguard Worker "g", "h", "i",
28*6777b538SAndroid Build Coastguard Worker "j", "k", "l",
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker NULL
31*6777b538SAndroid Build Coastguard Worker };
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker static const char *seeds2[] = {
34*6777b538SAndroid Build Coastguard Worker "m", "n", "o",
35*6777b538SAndroid Build Coastguard Worker "p", "q", "r",
36*6777b538SAndroid Build Coastguard Worker "s", "t", "u",
37*6777b538SAndroid Build Coastguard Worker "v", "w", "x",
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker NULL
40*6777b538SAndroid Build Coastguard Worker };
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker #define NB_STRINGS_MAX 100000
43*6777b538SAndroid Build Coastguard Worker #define NB_STRINGS_NS 10000
44*6777b538SAndroid Build Coastguard Worker #define NB_STRINGS_PREFIX (NB_STRINGS_NS / 20)
45*6777b538SAndroid Build Coastguard Worker #define NB_STRINGS_MIN 10
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker static xmlChar **strings1;
48*6777b538SAndroid Build Coastguard Worker static xmlChar **strings2;
49*6777b538SAndroid Build Coastguard Worker static const xmlChar **test1;
50*6777b538SAndroid Build Coastguard Worker static const xmlChar **test2;
51*6777b538SAndroid Build Coastguard Worker static int nbErrors = 0;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker static void
fill_string_pool(xmlChar ** strings,const char ** seeds)54*6777b538SAndroid Build Coastguard Worker fill_string_pool(xmlChar **strings, const char **seeds) {
55*6777b538SAndroid Build Coastguard Worker int i, j, k;
56*6777b538SAndroid Build Coastguard Worker int start_ns = NB_STRINGS_MAX - NB_STRINGS_NS;
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker /*
59*6777b538SAndroid Build Coastguard Worker * That's a bit nasty but the output is fine and it doesn't take hours
60*6777b538SAndroid Build Coastguard Worker * there is a small but sufficient number of duplicates, and we have
61*6777b538SAndroid Build Coastguard Worker * ":xxx" and full QNames in the last NB_STRINGS_NS values
62*6777b538SAndroid Build Coastguard Worker */
63*6777b538SAndroid Build Coastguard Worker for (i = 0; seeds[i] != NULL; i++) {
64*6777b538SAndroid Build Coastguard Worker strings[i] = xmlStrdup((const xmlChar *) seeds[i]);
65*6777b538SAndroid Build Coastguard Worker if (strings[i] == NULL) {
66*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while generating strings\n");
67*6777b538SAndroid Build Coastguard Worker exit(1);
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker for (j = 0, k = 0; i < start_ns; i++) {
71*6777b538SAndroid Build Coastguard Worker strings[i] = xmlStrncatNew(strings[j], strings[k], -1);
72*6777b538SAndroid Build Coastguard Worker if (strings[i] == NULL) {
73*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while generating strings\n");
74*6777b538SAndroid Build Coastguard Worker exit(1);
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker if (xmlStrlen(strings[i]) > 30) {
77*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "### %s %s\n", strings[start_ns+j], strings[k]);
78*6777b538SAndroid Build Coastguard Worker abort();
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker j++;
81*6777b538SAndroid Build Coastguard Worker if (j >= 50) {
82*6777b538SAndroid Build Coastguard Worker j = 0;
83*6777b538SAndroid Build Coastguard Worker k++;
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker for (j = 0, k = 0; (j < NB_STRINGS_PREFIX) && (i < NB_STRINGS_MAX);
87*6777b538SAndroid Build Coastguard Worker i++, j++) {
88*6777b538SAndroid Build Coastguard Worker strings[i] = xmlStrncatNew(strings[k], (const xmlChar *) ":", -1);
89*6777b538SAndroid Build Coastguard Worker if (strings[i] == NULL) {
90*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while generating strings\n");
91*6777b538SAndroid Build Coastguard Worker exit(1);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker k += 1;
94*6777b538SAndroid Build Coastguard Worker if (k >= start_ns) k = 0;
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker for (j = 0, k = 0; i < NB_STRINGS_MAX; i++) {
97*6777b538SAndroid Build Coastguard Worker strings[i] = xmlStrncatNew(strings[start_ns+j], strings[k], -1);
98*6777b538SAndroid Build Coastguard Worker if (strings[i] == NULL) {
99*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while generating strings\n");
100*6777b538SAndroid Build Coastguard Worker exit(1);
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker j++;
103*6777b538SAndroid Build Coastguard Worker if (j >= NB_STRINGS_PREFIX) j = 0;
104*6777b538SAndroid Build Coastguard Worker k += 5;
105*6777b538SAndroid Build Coastguard Worker if (k >= start_ns) k = 0;
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker #ifdef WITH_PRINT
print_strings(void)110*6777b538SAndroid Build Coastguard Worker static void print_strings(void) {
111*6777b538SAndroid Build Coastguard Worker int i;
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker for (i = 0; i < NB_STRINGS_MAX;i++) {
114*6777b538SAndroid Build Coastguard Worker printf("%s\n", strings1[i]);
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker for (i = 0; i < NB_STRINGS_MAX;i++) {
117*6777b538SAndroid Build Coastguard Worker printf("%s\n", strings2[i]);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker #endif
121*6777b538SAndroid Build Coastguard Worker
clean_strings(void)122*6777b538SAndroid Build Coastguard Worker static void clean_strings(void) {
123*6777b538SAndroid Build Coastguard Worker int i;
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker for (i = 0; i < NB_STRINGS_MAX; i++) {
126*6777b538SAndroid Build Coastguard Worker if (strings1[i] != NULL) /* really should not happen */
127*6777b538SAndroid Build Coastguard Worker xmlFree(strings1[i]);
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker for (i = 0; i < NB_STRINGS_MAX; i++) {
130*6777b538SAndroid Build Coastguard Worker if (strings2[i] != NULL) /* really should not happen */
131*6777b538SAndroid Build Coastguard Worker xmlFree(strings2[i]);
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker /*
136*6777b538SAndroid Build Coastguard Worker * This tests the sub-dictionary support
137*6777b538SAndroid Build Coastguard Worker */
138*6777b538SAndroid Build Coastguard Worker static int
test_subdict(xmlDictPtr parent)139*6777b538SAndroid Build Coastguard Worker test_subdict(xmlDictPtr parent) {
140*6777b538SAndroid Build Coastguard Worker int i, j;
141*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict;
142*6777b538SAndroid Build Coastguard Worker int ret = 0;
143*6777b538SAndroid Build Coastguard Worker xmlChar prefix[40];
144*6777b538SAndroid Build Coastguard Worker xmlChar *cur, *pref;
145*6777b538SAndroid Build Coastguard Worker const xmlChar *tmp;
146*6777b538SAndroid Build Coastguard Worker
147*6777b538SAndroid Build Coastguard Worker dict = xmlDictCreateSub(parent);
148*6777b538SAndroid Build Coastguard Worker if (dict == NULL) {
149*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while creating sub-dictionary\n");
150*6777b538SAndroid Build Coastguard Worker exit(1);
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker /* Cast to avoid buggy warning on MSVC. */
153*6777b538SAndroid Build Coastguard Worker memset((void *) test2, 0, sizeof(test2));
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker /*
156*6777b538SAndroid Build Coastguard Worker * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
157*6777b538SAndroid Build Coastguard Worker * and we allocate all those doing the fast key computations
158*6777b538SAndroid Build Coastguard Worker * All the strings are based on a different seeds subset so we know
159*6777b538SAndroid Build Coastguard Worker * they are allocated in the main dictionary, not coming from the parent
160*6777b538SAndroid Build Coastguard Worker */
161*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++) {
162*6777b538SAndroid Build Coastguard Worker test2[i] = xmlDictLookup(dict, strings2[i], -1);
163*6777b538SAndroid Build Coastguard Worker if (test2[i] == NULL) {
164*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
165*6777b538SAndroid Build Coastguard Worker ret = 1;
166*6777b538SAndroid Build Coastguard Worker nbErrors++;
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker }
169*6777b538SAndroid Build Coastguard Worker j = NB_STRINGS_MAX - NB_STRINGS_NS;
170*6777b538SAndroid Build Coastguard Worker /* ":foo" like strings2 */
171*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
172*6777b538SAndroid Build Coastguard Worker test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
173*6777b538SAndroid Build Coastguard Worker if (test2[j] == NULL) {
174*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
175*6777b538SAndroid Build Coastguard Worker ret = 1;
176*6777b538SAndroid Build Coastguard Worker nbErrors++;
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker /* "a:foo" like strings2 */
180*6777b538SAndroid Build Coastguard Worker j = NB_STRINGS_MAX - NB_STRINGS_MIN;
181*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
182*6777b538SAndroid Build Coastguard Worker test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
183*6777b538SAndroid Build Coastguard Worker if (test2[j] == NULL) {
184*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
185*6777b538SAndroid Build Coastguard Worker ret = 1;
186*6777b538SAndroid Build Coastguard Worker nbErrors++;
187*6777b538SAndroid Build Coastguard Worker }
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Worker /*
191*6777b538SAndroid Build Coastguard Worker * At this point allocate all the strings
192*6777b538SAndroid Build Coastguard Worker * the dictionary will grow in the process, reallocate more string tables
193*6777b538SAndroid Build Coastguard Worker * and switch to the better key generator
194*6777b538SAndroid Build Coastguard Worker */
195*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
196*6777b538SAndroid Build Coastguard Worker if (test2[i] != NULL)
197*6777b538SAndroid Build Coastguard Worker continue;
198*6777b538SAndroid Build Coastguard Worker test2[i] = xmlDictLookup(dict, strings2[i], -1);
199*6777b538SAndroid Build Coastguard Worker if (test2[i] == NULL) {
200*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
201*6777b538SAndroid Build Coastguard Worker ret = 1;
202*6777b538SAndroid Build Coastguard Worker nbErrors++;
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker /*
207*6777b538SAndroid Build Coastguard Worker * Now we can start to test things, first that all strings2 belongs to
208*6777b538SAndroid Build Coastguard Worker * the dict, and that none of them was actually allocated in the parent
209*6777b538SAndroid Build Coastguard Worker */
210*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
211*6777b538SAndroid Build Coastguard Worker if (!xmlDictOwns(dict, test2[i])) {
212*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed ownership failure for '%s'\n",
213*6777b538SAndroid Build Coastguard Worker strings2[i]);
214*6777b538SAndroid Build Coastguard Worker ret = 1;
215*6777b538SAndroid Build Coastguard Worker nbErrors++;
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker if (xmlDictOwns(parent, test2[i])) {
218*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed parent ownership failure for '%s'\n",
219*6777b538SAndroid Build Coastguard Worker strings2[i]);
220*6777b538SAndroid Build Coastguard Worker ret = 1;
221*6777b538SAndroid Build Coastguard Worker nbErrors++;
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker /*
226*6777b538SAndroid Build Coastguard Worker * Also verify that all strings from the parent are seen from the subdict
227*6777b538SAndroid Build Coastguard Worker */
228*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
229*6777b538SAndroid Build Coastguard Worker if (!xmlDictOwns(dict, test1[i])) {
230*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed sub-ownership failure for '%s'\n",
231*6777b538SAndroid Build Coastguard Worker strings1[i]);
232*6777b538SAndroid Build Coastguard Worker ret = 1;
233*6777b538SAndroid Build Coastguard Worker nbErrors++;
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker /*
238*6777b538SAndroid Build Coastguard Worker * Then that another lookup to the string in sub will return the same
239*6777b538SAndroid Build Coastguard Worker */
240*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
241*6777b538SAndroid Build Coastguard Worker if (xmlDictLookup(dict, strings2[i], -1) != test2[i]) {
242*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
243*6777b538SAndroid Build Coastguard Worker i, strings2[i]);
244*6777b538SAndroid Build Coastguard Worker ret = 1;
245*6777b538SAndroid Build Coastguard Worker nbErrors++;
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker /*
249*6777b538SAndroid Build Coastguard Worker * But also that any lookup for a string in the parent will be provided
250*6777b538SAndroid Build Coastguard Worker * as in the parent
251*6777b538SAndroid Build Coastguard Worker */
252*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
253*6777b538SAndroid Build Coastguard Worker if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
254*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed parent string lookup check for %d, '%s'\n",
255*6777b538SAndroid Build Coastguard Worker i, strings1[i]);
256*6777b538SAndroid Build Coastguard Worker ret = 1;
257*6777b538SAndroid Build Coastguard Worker nbErrors++;
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker /*
262*6777b538SAndroid Build Coastguard Worker * check the QName lookups
263*6777b538SAndroid Build Coastguard Worker */
264*6777b538SAndroid Build Coastguard Worker for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
265*6777b538SAndroid Build Coastguard Worker cur = strings2[i];
266*6777b538SAndroid Build Coastguard Worker pref = &prefix[0];
267*6777b538SAndroid Build Coastguard Worker while (*cur != ':') *pref++ = *cur++;
268*6777b538SAndroid Build Coastguard Worker cur++;
269*6777b538SAndroid Build Coastguard Worker *pref = 0;
270*6777b538SAndroid Build Coastguard Worker tmp = xmlDictQLookup(dict, &prefix[0], cur);
271*6777b538SAndroid Build Coastguard Worker if (tmp != test2[i]) {
272*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
273*6777b538SAndroid Build Coastguard Worker &prefix[0], cur);
274*6777b538SAndroid Build Coastguard Worker ret = 1;
275*6777b538SAndroid Build Coastguard Worker nbErrors++;
276*6777b538SAndroid Build Coastguard Worker }
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker /*
279*6777b538SAndroid Build Coastguard Worker * check the QName lookups for strings from the parent
280*6777b538SAndroid Build Coastguard Worker */
281*6777b538SAndroid Build Coastguard Worker for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
282*6777b538SAndroid Build Coastguard Worker cur = strings1[i];
283*6777b538SAndroid Build Coastguard Worker pref = &prefix[0];
284*6777b538SAndroid Build Coastguard Worker while (*cur != ':') *pref++ = *cur++;
285*6777b538SAndroid Build Coastguard Worker cur++;
286*6777b538SAndroid Build Coastguard Worker *pref = 0;
287*6777b538SAndroid Build Coastguard Worker tmp = xmlDictQLookup(dict, &prefix[0], cur);
288*6777b538SAndroid Build Coastguard Worker if (xmlDictQLookup(dict, &prefix[0], cur) != test1[i]) {
289*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed parent lookup check for '%s':'%s'\n",
290*6777b538SAndroid Build Coastguard Worker &prefix[0], cur);
291*6777b538SAndroid Build Coastguard Worker ret = 1;
292*6777b538SAndroid Build Coastguard Worker nbErrors++;
293*6777b538SAndroid Build Coastguard Worker }
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker
296*6777b538SAndroid Build Coastguard Worker xmlDictFree(dict);
297*6777b538SAndroid Build Coastguard Worker return(ret);
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker /*
301*6777b538SAndroid Build Coastguard Worker * Test a single dictionary
302*6777b538SAndroid Build Coastguard Worker */
303*6777b538SAndroid Build Coastguard Worker static int
test_dict(xmlDict * dict)304*6777b538SAndroid Build Coastguard Worker test_dict(xmlDict *dict) {
305*6777b538SAndroid Build Coastguard Worker int i, j;
306*6777b538SAndroid Build Coastguard Worker int ret = 0;
307*6777b538SAndroid Build Coastguard Worker xmlChar prefix[40];
308*6777b538SAndroid Build Coastguard Worker xmlChar *cur, *pref;
309*6777b538SAndroid Build Coastguard Worker const xmlChar *tmp;
310*6777b538SAndroid Build Coastguard Worker
311*6777b538SAndroid Build Coastguard Worker /* Cast to avoid buggy warning on MSVC. */
312*6777b538SAndroid Build Coastguard Worker memset((void *) test1, 0, sizeof(test1));
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker /*
315*6777b538SAndroid Build Coastguard Worker * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
316*6777b538SAndroid Build Coastguard Worker * and we allocate all those doing the fast key computations
317*6777b538SAndroid Build Coastguard Worker */
318*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++) {
319*6777b538SAndroid Build Coastguard Worker test1[i] = xmlDictLookup(dict, strings1[i], -1);
320*6777b538SAndroid Build Coastguard Worker if (test1[i] == NULL) {
321*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
322*6777b538SAndroid Build Coastguard Worker ret = 1;
323*6777b538SAndroid Build Coastguard Worker nbErrors++;
324*6777b538SAndroid Build Coastguard Worker }
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker j = NB_STRINGS_MAX - NB_STRINGS_NS;
327*6777b538SAndroid Build Coastguard Worker /* ":foo" like strings1 */
328*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
329*6777b538SAndroid Build Coastguard Worker test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
330*6777b538SAndroid Build Coastguard Worker if (test1[j] == NULL) {
331*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
332*6777b538SAndroid Build Coastguard Worker ret = 1;
333*6777b538SAndroid Build Coastguard Worker nbErrors++;
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker /* "a:foo" like strings1 */
337*6777b538SAndroid Build Coastguard Worker j = NB_STRINGS_MAX - NB_STRINGS_MIN;
338*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
339*6777b538SAndroid Build Coastguard Worker test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
340*6777b538SAndroid Build Coastguard Worker if (test1[j] == NULL) {
341*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
342*6777b538SAndroid Build Coastguard Worker ret = 1;
343*6777b538SAndroid Build Coastguard Worker nbErrors++;
344*6777b538SAndroid Build Coastguard Worker }
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker /*
348*6777b538SAndroid Build Coastguard Worker * At this point allocate all the strings
349*6777b538SAndroid Build Coastguard Worker * the dictionary will grow in the process, reallocate more string tables
350*6777b538SAndroid Build Coastguard Worker * and switch to the better key generator
351*6777b538SAndroid Build Coastguard Worker */
352*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
353*6777b538SAndroid Build Coastguard Worker if (test1[i] != NULL)
354*6777b538SAndroid Build Coastguard Worker continue;
355*6777b538SAndroid Build Coastguard Worker test1[i] = xmlDictLookup(dict, strings1[i], -1);
356*6777b538SAndroid Build Coastguard Worker if (test1[i] == NULL) {
357*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
358*6777b538SAndroid Build Coastguard Worker ret = 1;
359*6777b538SAndroid Build Coastguard Worker nbErrors++;
360*6777b538SAndroid Build Coastguard Worker }
361*6777b538SAndroid Build Coastguard Worker }
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Worker /*
364*6777b538SAndroid Build Coastguard Worker * Now we can start to test things, first that all strings1 belongs to
365*6777b538SAndroid Build Coastguard Worker * the dict
366*6777b538SAndroid Build Coastguard Worker */
367*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
368*6777b538SAndroid Build Coastguard Worker if (!xmlDictOwns(dict, test1[i])) {
369*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed ownership failure for '%s'\n",
370*6777b538SAndroid Build Coastguard Worker strings1[i]);
371*6777b538SAndroid Build Coastguard Worker ret = 1;
372*6777b538SAndroid Build Coastguard Worker nbErrors++;
373*6777b538SAndroid Build Coastguard Worker }
374*6777b538SAndroid Build Coastguard Worker }
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker /*
377*6777b538SAndroid Build Coastguard Worker * Then that another lookup to the string will return the same
378*6777b538SAndroid Build Coastguard Worker */
379*6777b538SAndroid Build Coastguard Worker for (i = 0;i < NB_STRINGS_MAX;i++) {
380*6777b538SAndroid Build Coastguard Worker if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
381*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
382*6777b538SAndroid Build Coastguard Worker i, strings1[i]);
383*6777b538SAndroid Build Coastguard Worker ret = 1;
384*6777b538SAndroid Build Coastguard Worker nbErrors++;
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker }
387*6777b538SAndroid Build Coastguard Worker
388*6777b538SAndroid Build Coastguard Worker /*
389*6777b538SAndroid Build Coastguard Worker * More complex, check the QName lookups
390*6777b538SAndroid Build Coastguard Worker */
391*6777b538SAndroid Build Coastguard Worker for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
392*6777b538SAndroid Build Coastguard Worker cur = strings1[i];
393*6777b538SAndroid Build Coastguard Worker pref = &prefix[0];
394*6777b538SAndroid Build Coastguard Worker while (*cur != ':') *pref++ = *cur++;
395*6777b538SAndroid Build Coastguard Worker cur++;
396*6777b538SAndroid Build Coastguard Worker *pref = 0;
397*6777b538SAndroid Build Coastguard Worker tmp = xmlDictQLookup(dict, &prefix[0], cur);
398*6777b538SAndroid Build Coastguard Worker if (tmp != test1[i]) {
399*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
400*6777b538SAndroid Build Coastguard Worker &prefix[0], cur);
401*6777b538SAndroid Build Coastguard Worker ret = 1;
402*6777b538SAndroid Build Coastguard Worker nbErrors++;
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker }
405*6777b538SAndroid Build Coastguard Worker
406*6777b538SAndroid Build Coastguard Worker return(ret);
407*6777b538SAndroid Build Coastguard Worker }
408*6777b538SAndroid Build Coastguard Worker
409*6777b538SAndroid Build Coastguard Worker static int
testall_dict(void)410*6777b538SAndroid Build Coastguard Worker testall_dict(void) {
411*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict;
412*6777b538SAndroid Build Coastguard Worker int ret = 0;
413*6777b538SAndroid Build Coastguard Worker
414*6777b538SAndroid Build Coastguard Worker strings1 = xmlMalloc(NB_STRINGS_MAX * sizeof(strings1[0]));
415*6777b538SAndroid Build Coastguard Worker memset(strings1, 0, NB_STRINGS_MAX * sizeof(strings1[0]));
416*6777b538SAndroid Build Coastguard Worker strings2 = xmlMalloc(NB_STRINGS_MAX * sizeof(strings2[0]));
417*6777b538SAndroid Build Coastguard Worker memset(strings2, 0, NB_STRINGS_MAX * sizeof(strings2[0]));
418*6777b538SAndroid Build Coastguard Worker test1 = xmlMalloc(NB_STRINGS_MAX * sizeof(test1[0]));
419*6777b538SAndroid Build Coastguard Worker memset(test1, 0, NB_STRINGS_MAX * sizeof(test1[0]));
420*6777b538SAndroid Build Coastguard Worker test2 = xmlMalloc(NB_STRINGS_MAX * sizeof(test2[0]));
421*6777b538SAndroid Build Coastguard Worker memset(test2, 0, NB_STRINGS_MAX * sizeof(test2[0]));
422*6777b538SAndroid Build Coastguard Worker
423*6777b538SAndroid Build Coastguard Worker fill_string_pool(strings1, seeds1);
424*6777b538SAndroid Build Coastguard Worker fill_string_pool(strings2, seeds2);
425*6777b538SAndroid Build Coastguard Worker #ifdef WITH_PRINT
426*6777b538SAndroid Build Coastguard Worker print_strings();
427*6777b538SAndroid Build Coastguard Worker #endif
428*6777b538SAndroid Build Coastguard Worker
429*6777b538SAndroid Build Coastguard Worker dict = xmlDictCreate();
430*6777b538SAndroid Build Coastguard Worker if (dict == NULL) {
431*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "Out of memory while creating dictionary\n");
432*6777b538SAndroid Build Coastguard Worker exit(1);
433*6777b538SAndroid Build Coastguard Worker }
434*6777b538SAndroid Build Coastguard Worker if (test_dict(dict) != 0) {
435*6777b538SAndroid Build Coastguard Worker ret = 1;
436*6777b538SAndroid Build Coastguard Worker }
437*6777b538SAndroid Build Coastguard Worker if (test_subdict(dict) != 0) {
438*6777b538SAndroid Build Coastguard Worker ret = 1;
439*6777b538SAndroid Build Coastguard Worker }
440*6777b538SAndroid Build Coastguard Worker xmlDictFree(dict);
441*6777b538SAndroid Build Coastguard Worker
442*6777b538SAndroid Build Coastguard Worker clean_strings();
443*6777b538SAndroid Build Coastguard Worker xmlFree(strings1);
444*6777b538SAndroid Build Coastguard Worker xmlFree(strings2);
445*6777b538SAndroid Build Coastguard Worker xmlFree(test1);
446*6777b538SAndroid Build Coastguard Worker xmlFree(test2);
447*6777b538SAndroid Build Coastguard Worker
448*6777b538SAndroid Build Coastguard Worker return ret;
449*6777b538SAndroid Build Coastguard Worker }
450*6777b538SAndroid Build Coastguard Worker
451*6777b538SAndroid Build Coastguard Worker
452*6777b538SAndroid Build Coastguard Worker /**** Hash table tests ****/
453*6777b538SAndroid Build Coastguard Worker
454*6777b538SAndroid Build Coastguard Worker static unsigned
455*6777b538SAndroid Build Coastguard Worker rng_state[2] = { 123, 456 };
456*6777b538SAndroid Build Coastguard Worker
457*6777b538SAndroid Build Coastguard Worker #define HASH_ROL(x,n) ((x) << (n) | ((x) & 0xFFFFFFFF) >> (32 - (n)))
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
460*6777b538SAndroid Build Coastguard Worker static unsigned
my_rand(unsigned max)461*6777b538SAndroid Build Coastguard Worker my_rand(unsigned max) {
462*6777b538SAndroid Build Coastguard Worker unsigned s0 = rng_state[0];
463*6777b538SAndroid Build Coastguard Worker unsigned s1 = rng_state[1];
464*6777b538SAndroid Build Coastguard Worker unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5;
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker s1 ^= s0;
467*6777b538SAndroid Build Coastguard Worker rng_state[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9);
468*6777b538SAndroid Build Coastguard Worker rng_state[1] = HASH_ROL(s1, 13);
469*6777b538SAndroid Build Coastguard Worker
470*6777b538SAndroid Build Coastguard Worker return((result & 0xFFFFFFFF) % max);
471*6777b538SAndroid Build Coastguard Worker }
472*6777b538SAndroid Build Coastguard Worker
473*6777b538SAndroid Build Coastguard Worker static xmlChar *
gen_random_string(xmlChar id)474*6777b538SAndroid Build Coastguard Worker gen_random_string(xmlChar id) {
475*6777b538SAndroid Build Coastguard Worker unsigned size = my_rand(64) + 1;
476*6777b538SAndroid Build Coastguard Worker unsigned id_pos = my_rand(size);
477*6777b538SAndroid Build Coastguard Worker size_t j;
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker xmlChar *str = xmlMalloc(size + 1);
480*6777b538SAndroid Build Coastguard Worker for (j = 0; j < size; j++) {
481*6777b538SAndroid Build Coastguard Worker str[j] = 'a' + my_rand(26);
482*6777b538SAndroid Build Coastguard Worker }
483*6777b538SAndroid Build Coastguard Worker str[id_pos] = id;
484*6777b538SAndroid Build Coastguard Worker str[size] = 0;
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker /* Generate QName in 75% of cases */
487*6777b538SAndroid Build Coastguard Worker if (size > 3 && my_rand(4) > 0) {
488*6777b538SAndroid Build Coastguard Worker unsigned colon_pos = my_rand(size - 3) + 1;
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker if (colon_pos >= id_pos)
491*6777b538SAndroid Build Coastguard Worker colon_pos++;
492*6777b538SAndroid Build Coastguard Worker str[colon_pos] = ':';
493*6777b538SAndroid Build Coastguard Worker }
494*6777b538SAndroid Build Coastguard Worker
495*6777b538SAndroid Build Coastguard Worker return str;
496*6777b538SAndroid Build Coastguard Worker }
497*6777b538SAndroid Build Coastguard Worker
498*6777b538SAndroid Build Coastguard Worker typedef struct {
499*6777b538SAndroid Build Coastguard Worker xmlChar **strings;
500*6777b538SAndroid Build Coastguard Worker size_t num_entries;
501*6777b538SAndroid Build Coastguard Worker size_t num_keys;
502*6777b538SAndroid Build Coastguard Worker size_t num_strings;
503*6777b538SAndroid Build Coastguard Worker size_t index;
504*6777b538SAndroid Build Coastguard Worker xmlChar id;
505*6777b538SAndroid Build Coastguard Worker } StringPool;
506*6777b538SAndroid Build Coastguard Worker
507*6777b538SAndroid Build Coastguard Worker static StringPool *
pool_new(size_t num_entries,size_t num_keys,xmlChar id)508*6777b538SAndroid Build Coastguard Worker pool_new(size_t num_entries, size_t num_keys, xmlChar id) {
509*6777b538SAndroid Build Coastguard Worker StringPool *ret;
510*6777b538SAndroid Build Coastguard Worker size_t num_strings;
511*6777b538SAndroid Build Coastguard Worker
512*6777b538SAndroid Build Coastguard Worker ret = xmlMalloc(sizeof(*ret));
513*6777b538SAndroid Build Coastguard Worker ret->num_entries = num_entries;
514*6777b538SAndroid Build Coastguard Worker ret->num_keys = num_keys;
515*6777b538SAndroid Build Coastguard Worker num_strings = num_entries * num_keys;
516*6777b538SAndroid Build Coastguard Worker ret->strings = xmlMalloc(num_strings * sizeof(ret->strings[0]));
517*6777b538SAndroid Build Coastguard Worker memset(ret->strings, 0, num_strings * sizeof(ret->strings[0]));
518*6777b538SAndroid Build Coastguard Worker ret->num_strings = num_strings;
519*6777b538SAndroid Build Coastguard Worker ret->index = 0;
520*6777b538SAndroid Build Coastguard Worker ret->id = id;
521*6777b538SAndroid Build Coastguard Worker
522*6777b538SAndroid Build Coastguard Worker return ret;
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker
525*6777b538SAndroid Build Coastguard Worker static void
pool_free(StringPool * pool)526*6777b538SAndroid Build Coastguard Worker pool_free(StringPool *pool) {
527*6777b538SAndroid Build Coastguard Worker size_t i;
528*6777b538SAndroid Build Coastguard Worker
529*6777b538SAndroid Build Coastguard Worker for (i = 0; i < pool->num_strings; i++) {
530*6777b538SAndroid Build Coastguard Worker xmlFree(pool->strings[i]);
531*6777b538SAndroid Build Coastguard Worker }
532*6777b538SAndroid Build Coastguard Worker xmlFree(pool->strings);
533*6777b538SAndroid Build Coastguard Worker xmlFree(pool);
534*6777b538SAndroid Build Coastguard Worker }
535*6777b538SAndroid Build Coastguard Worker
536*6777b538SAndroid Build Coastguard Worker static int
pool_done(StringPool * pool)537*6777b538SAndroid Build Coastguard Worker pool_done(StringPool *pool) {
538*6777b538SAndroid Build Coastguard Worker return pool->index >= pool->num_strings;
539*6777b538SAndroid Build Coastguard Worker }
540*6777b538SAndroid Build Coastguard Worker
541*6777b538SAndroid Build Coastguard Worker static void
pool_reset(StringPool * pool)542*6777b538SAndroid Build Coastguard Worker pool_reset(StringPool *pool) {
543*6777b538SAndroid Build Coastguard Worker pool->index = 0;
544*6777b538SAndroid Build Coastguard Worker }
545*6777b538SAndroid Build Coastguard Worker
546*6777b538SAndroid Build Coastguard Worker static int
pool_bulk_insert(StringPool * pool,xmlHashTablePtr hash,size_t num)547*6777b538SAndroid Build Coastguard Worker pool_bulk_insert(StringPool *pool, xmlHashTablePtr hash, size_t num) {
548*6777b538SAndroid Build Coastguard Worker size_t i, j;
549*6777b538SAndroid Build Coastguard Worker int ret = 0;
550*6777b538SAndroid Build Coastguard Worker
551*6777b538SAndroid Build Coastguard Worker for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
552*6777b538SAndroid Build Coastguard Worker xmlChar *str[3];
553*6777b538SAndroid Build Coastguard Worker size_t k;
554*6777b538SAndroid Build Coastguard Worker
555*6777b538SAndroid Build Coastguard Worker while (1) {
556*6777b538SAndroid Build Coastguard Worker xmlChar tmp_key[1];
557*6777b538SAndroid Build Coastguard Worker int res;
558*6777b538SAndroid Build Coastguard Worker
559*6777b538SAndroid Build Coastguard Worker for (k = 0; k < pool->num_keys; k++)
560*6777b538SAndroid Build Coastguard Worker str[k] = gen_random_string(pool->id);
561*6777b538SAndroid Build Coastguard Worker
562*6777b538SAndroid Build Coastguard Worker switch (pool->num_keys) {
563*6777b538SAndroid Build Coastguard Worker case 1:
564*6777b538SAndroid Build Coastguard Worker res = xmlHashAddEntry(hash, str[0], tmp_key);
565*6777b538SAndroid Build Coastguard Worker if (res == 0 &&
566*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry(hash, str[0], str[0], NULL) != 0)
567*6777b538SAndroid Build Coastguard Worker ret = -1;
568*6777b538SAndroid Build Coastguard Worker break;
569*6777b538SAndroid Build Coastguard Worker case 2:
570*6777b538SAndroid Build Coastguard Worker res = xmlHashAddEntry2(hash, str[0], str[1], tmp_key);
571*6777b538SAndroid Build Coastguard Worker if (res == 0 &&
572*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry2(hash, str[0], str[1], str[0],
573*6777b538SAndroid Build Coastguard Worker NULL) != 0)
574*6777b538SAndroid Build Coastguard Worker ret = -1;
575*6777b538SAndroid Build Coastguard Worker break;
576*6777b538SAndroid Build Coastguard Worker case 3:
577*6777b538SAndroid Build Coastguard Worker res = xmlHashAddEntry3(hash, str[0], str[1], str[2],
578*6777b538SAndroid Build Coastguard Worker tmp_key);
579*6777b538SAndroid Build Coastguard Worker if (res == 0 &&
580*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry3(hash, str[0], str[1], str[2],
581*6777b538SAndroid Build Coastguard Worker str[0], NULL) != 0)
582*6777b538SAndroid Build Coastguard Worker ret = -1;
583*6777b538SAndroid Build Coastguard Worker break;
584*6777b538SAndroid Build Coastguard Worker }
585*6777b538SAndroid Build Coastguard Worker
586*6777b538SAndroid Build Coastguard Worker if (res == 0)
587*6777b538SAndroid Build Coastguard Worker break;
588*6777b538SAndroid Build Coastguard Worker for (k = 0; k < pool->num_keys; k++)
589*6777b538SAndroid Build Coastguard Worker xmlFree(str[k]);
590*6777b538SAndroid Build Coastguard Worker }
591*6777b538SAndroid Build Coastguard Worker
592*6777b538SAndroid Build Coastguard Worker for (k = 0; k < pool->num_keys; k++)
593*6777b538SAndroid Build Coastguard Worker pool->strings[i++] = str[k];
594*6777b538SAndroid Build Coastguard Worker }
595*6777b538SAndroid Build Coastguard Worker
596*6777b538SAndroid Build Coastguard Worker pool->index = i;
597*6777b538SAndroid Build Coastguard Worker return ret;
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker
600*6777b538SAndroid Build Coastguard Worker static xmlChar *
hash_qlookup(xmlHashTable * hash,xmlChar ** names,size_t num_keys)601*6777b538SAndroid Build Coastguard Worker hash_qlookup(xmlHashTable *hash, xmlChar **names, size_t num_keys) {
602*6777b538SAndroid Build Coastguard Worker xmlChar *prefix[3];
603*6777b538SAndroid Build Coastguard Worker const xmlChar *local[3];
604*6777b538SAndroid Build Coastguard Worker xmlChar *res;
605*6777b538SAndroid Build Coastguard Worker size_t i;
606*6777b538SAndroid Build Coastguard Worker
607*6777b538SAndroid Build Coastguard Worker for (i = 0; i < 3; ++i) {
608*6777b538SAndroid Build Coastguard Worker if (i >= num_keys) {
609*6777b538SAndroid Build Coastguard Worker prefix[i] = NULL;
610*6777b538SAndroid Build Coastguard Worker local[i] = NULL;
611*6777b538SAndroid Build Coastguard Worker } else {
612*6777b538SAndroid Build Coastguard Worker const xmlChar *name = names[i];
613*6777b538SAndroid Build Coastguard Worker const xmlChar *colon = BAD_CAST strchr((const char *) name, ':');
614*6777b538SAndroid Build Coastguard Worker
615*6777b538SAndroid Build Coastguard Worker if (colon == NULL) {
616*6777b538SAndroid Build Coastguard Worker prefix[i] = NULL;
617*6777b538SAndroid Build Coastguard Worker local[i] = name;
618*6777b538SAndroid Build Coastguard Worker } else {
619*6777b538SAndroid Build Coastguard Worker prefix[i] = xmlStrndup(name, colon - name);
620*6777b538SAndroid Build Coastguard Worker local[i] = &colon[1];
621*6777b538SAndroid Build Coastguard Worker }
622*6777b538SAndroid Build Coastguard Worker }
623*6777b538SAndroid Build Coastguard Worker }
624*6777b538SAndroid Build Coastguard Worker
625*6777b538SAndroid Build Coastguard Worker res = xmlHashQLookup3(hash, prefix[0], local[0], prefix[1], local[1],
626*6777b538SAndroid Build Coastguard Worker prefix[2], local[2]);
627*6777b538SAndroid Build Coastguard Worker
628*6777b538SAndroid Build Coastguard Worker for (i = 0; i < 3; ++i)
629*6777b538SAndroid Build Coastguard Worker xmlFree(prefix[i]);
630*6777b538SAndroid Build Coastguard Worker
631*6777b538SAndroid Build Coastguard Worker return res;
632*6777b538SAndroid Build Coastguard Worker }
633*6777b538SAndroid Build Coastguard Worker
634*6777b538SAndroid Build Coastguard Worker static int
pool_bulk_lookup(StringPool * pool,xmlHashTablePtr hash,size_t num,int existing)635*6777b538SAndroid Build Coastguard Worker pool_bulk_lookup(StringPool *pool, xmlHashTablePtr hash, size_t num,
636*6777b538SAndroid Build Coastguard Worker int existing) {
637*6777b538SAndroid Build Coastguard Worker size_t i, j;
638*6777b538SAndroid Build Coastguard Worker int ret = 0;
639*6777b538SAndroid Build Coastguard Worker
640*6777b538SAndroid Build Coastguard Worker for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
641*6777b538SAndroid Build Coastguard Worker xmlChar **str = &pool->strings[i];
642*6777b538SAndroid Build Coastguard Worker int q;
643*6777b538SAndroid Build Coastguard Worker
644*6777b538SAndroid Build Coastguard Worker for (q = 0; q < 2; q++) {
645*6777b538SAndroid Build Coastguard Worker xmlChar *res = NULL;
646*6777b538SAndroid Build Coastguard Worker
647*6777b538SAndroid Build Coastguard Worker if (q) {
648*6777b538SAndroid Build Coastguard Worker res = hash_qlookup(hash, str, pool->num_keys);
649*6777b538SAndroid Build Coastguard Worker } else {
650*6777b538SAndroid Build Coastguard Worker switch (pool->num_keys) {
651*6777b538SAndroid Build Coastguard Worker case 1:
652*6777b538SAndroid Build Coastguard Worker res = xmlHashLookup(hash, str[0]);
653*6777b538SAndroid Build Coastguard Worker break;
654*6777b538SAndroid Build Coastguard Worker case 2:
655*6777b538SAndroid Build Coastguard Worker res = xmlHashLookup2(hash, str[0], str[1]);
656*6777b538SAndroid Build Coastguard Worker break;
657*6777b538SAndroid Build Coastguard Worker case 3:
658*6777b538SAndroid Build Coastguard Worker res = xmlHashLookup3(hash, str[0], str[1], str[2]);
659*6777b538SAndroid Build Coastguard Worker break;
660*6777b538SAndroid Build Coastguard Worker }
661*6777b538SAndroid Build Coastguard Worker }
662*6777b538SAndroid Build Coastguard Worker
663*6777b538SAndroid Build Coastguard Worker if (existing) {
664*6777b538SAndroid Build Coastguard Worker if (res != str[0])
665*6777b538SAndroid Build Coastguard Worker ret = -1;
666*6777b538SAndroid Build Coastguard Worker } else {
667*6777b538SAndroid Build Coastguard Worker if (res != NULL)
668*6777b538SAndroid Build Coastguard Worker ret = -1;
669*6777b538SAndroid Build Coastguard Worker }
670*6777b538SAndroid Build Coastguard Worker }
671*6777b538SAndroid Build Coastguard Worker
672*6777b538SAndroid Build Coastguard Worker i += pool->num_keys;
673*6777b538SAndroid Build Coastguard Worker }
674*6777b538SAndroid Build Coastguard Worker
675*6777b538SAndroid Build Coastguard Worker pool->index = i;
676*6777b538SAndroid Build Coastguard Worker return ret;
677*6777b538SAndroid Build Coastguard Worker }
678*6777b538SAndroid Build Coastguard Worker
679*6777b538SAndroid Build Coastguard Worker static int
pool_bulk_remove(StringPool * pool,xmlHashTablePtr hash,size_t num)680*6777b538SAndroid Build Coastguard Worker pool_bulk_remove(StringPool *pool, xmlHashTablePtr hash, size_t num) {
681*6777b538SAndroid Build Coastguard Worker size_t i, j;
682*6777b538SAndroid Build Coastguard Worker int ret = 0;
683*6777b538SAndroid Build Coastguard Worker
684*6777b538SAndroid Build Coastguard Worker for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
685*6777b538SAndroid Build Coastguard Worker xmlChar **str = &pool->strings[i];
686*6777b538SAndroid Build Coastguard Worker int res = -1;
687*6777b538SAndroid Build Coastguard Worker
688*6777b538SAndroid Build Coastguard Worker switch (pool->num_keys) {
689*6777b538SAndroid Build Coastguard Worker case 1:
690*6777b538SAndroid Build Coastguard Worker res = xmlHashRemoveEntry(hash, str[0], NULL);
691*6777b538SAndroid Build Coastguard Worker break;
692*6777b538SAndroid Build Coastguard Worker case 2:
693*6777b538SAndroid Build Coastguard Worker res = xmlHashRemoveEntry2(hash, str[0], str[1], NULL);
694*6777b538SAndroid Build Coastguard Worker break;
695*6777b538SAndroid Build Coastguard Worker case 3:
696*6777b538SAndroid Build Coastguard Worker res = xmlHashRemoveEntry3(hash, str[0], str[1], str[2], NULL);
697*6777b538SAndroid Build Coastguard Worker break;
698*6777b538SAndroid Build Coastguard Worker }
699*6777b538SAndroid Build Coastguard Worker
700*6777b538SAndroid Build Coastguard Worker if (res != 0)
701*6777b538SAndroid Build Coastguard Worker ret = -1;
702*6777b538SAndroid Build Coastguard Worker
703*6777b538SAndroid Build Coastguard Worker i += pool->num_keys;
704*6777b538SAndroid Build Coastguard Worker }
705*6777b538SAndroid Build Coastguard Worker
706*6777b538SAndroid Build Coastguard Worker pool->index = i;
707*6777b538SAndroid Build Coastguard Worker return ret;
708*6777b538SAndroid Build Coastguard Worker }
709*6777b538SAndroid Build Coastguard Worker
710*6777b538SAndroid Build Coastguard Worker static int
test_hash(size_t num_entries,size_t num_keys,int use_dict)711*6777b538SAndroid Build Coastguard Worker test_hash(size_t num_entries, size_t num_keys, int use_dict) {
712*6777b538SAndroid Build Coastguard Worker xmlDict *dict = NULL;
713*6777b538SAndroid Build Coastguard Worker xmlHashTable *hash;
714*6777b538SAndroid Build Coastguard Worker StringPool *pool1, *pool2;
715*6777b538SAndroid Build Coastguard Worker int ret = 0;
716*6777b538SAndroid Build Coastguard Worker
717*6777b538SAndroid Build Coastguard Worker if (use_dict) {
718*6777b538SAndroid Build Coastguard Worker dict = xmlDictCreate();
719*6777b538SAndroid Build Coastguard Worker hash = xmlHashCreateDict(0, dict);
720*6777b538SAndroid Build Coastguard Worker } else {
721*6777b538SAndroid Build Coastguard Worker hash = xmlHashCreate(0);
722*6777b538SAndroid Build Coastguard Worker }
723*6777b538SAndroid Build Coastguard Worker pool1 = pool_new(num_entries, num_keys, '1');
724*6777b538SAndroid Build Coastguard Worker pool2 = pool_new(num_entries, num_keys, '2');
725*6777b538SAndroid Build Coastguard Worker
726*6777b538SAndroid Build Coastguard Worker /* Insert all strings from pool2 and about half of pool1. */
727*6777b538SAndroid Build Coastguard Worker while (!pool_done(pool2)) {
728*6777b538SAndroid Build Coastguard Worker if (pool_bulk_insert(pool1, hash, my_rand(50)) != 0) {
729*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool1: hash insert failed\n");
730*6777b538SAndroid Build Coastguard Worker ret = 1;
731*6777b538SAndroid Build Coastguard Worker }
732*6777b538SAndroid Build Coastguard Worker if (pool_bulk_insert(pool2, hash, my_rand(100)) != 0) {
733*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool1: hash insert failed\n");
734*6777b538SAndroid Build Coastguard Worker ret = 1;
735*6777b538SAndroid Build Coastguard Worker }
736*6777b538SAndroid Build Coastguard Worker }
737*6777b538SAndroid Build Coastguard Worker
738*6777b538SAndroid Build Coastguard Worker /* Check existing entries */
739*6777b538SAndroid Build Coastguard Worker pool_reset(pool2);
740*6777b538SAndroid Build Coastguard Worker if (pool_bulk_lookup(pool2, hash, pool2->num_entries, 1) != 0) {
741*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool2: hash lookup failed\n");
742*6777b538SAndroid Build Coastguard Worker ret = 1;
743*6777b538SAndroid Build Coastguard Worker }
744*6777b538SAndroid Build Coastguard Worker
745*6777b538SAndroid Build Coastguard Worker /* Remove all strings from pool2 and insert the rest of pool1. */
746*6777b538SAndroid Build Coastguard Worker pool_reset(pool2);
747*6777b538SAndroid Build Coastguard Worker while (!pool_done(pool1) || !pool_done(pool2)) {
748*6777b538SAndroid Build Coastguard Worker if (pool_bulk_insert(pool1, hash, my_rand(50)) != 0) {
749*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool1: hash insert failed\n");
750*6777b538SAndroid Build Coastguard Worker ret = 1;
751*6777b538SAndroid Build Coastguard Worker }
752*6777b538SAndroid Build Coastguard Worker if (pool_bulk_remove(pool2, hash, my_rand(100)) != 0) {
753*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool2: hash remove failed\n");
754*6777b538SAndroid Build Coastguard Worker ret = 1;
755*6777b538SAndroid Build Coastguard Worker }
756*6777b538SAndroid Build Coastguard Worker }
757*6777b538SAndroid Build Coastguard Worker
758*6777b538SAndroid Build Coastguard Worker /* Check existing entries */
759*6777b538SAndroid Build Coastguard Worker pool_reset(pool1);
760*6777b538SAndroid Build Coastguard Worker if (pool_bulk_lookup(pool1, hash, pool1->num_entries, 1) != 0) {
761*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool1: hash lookup failed\n");
762*6777b538SAndroid Build Coastguard Worker ret = 1;
763*6777b538SAndroid Build Coastguard Worker }
764*6777b538SAndroid Build Coastguard Worker
765*6777b538SAndroid Build Coastguard Worker /* Check removed entries */
766*6777b538SAndroid Build Coastguard Worker pool_reset(pool2);
767*6777b538SAndroid Build Coastguard Worker if (pool_bulk_lookup(pool2, hash, pool2->num_entries, 0) != 0) {
768*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "pool2: hash lookup succeeded unexpectedly\n");
769*6777b538SAndroid Build Coastguard Worker ret = 1;
770*6777b538SAndroid Build Coastguard Worker }
771*6777b538SAndroid Build Coastguard Worker
772*6777b538SAndroid Build Coastguard Worker pool_free(pool1);
773*6777b538SAndroid Build Coastguard Worker pool_free(pool2);
774*6777b538SAndroid Build Coastguard Worker xmlHashFree(hash, NULL);
775*6777b538SAndroid Build Coastguard Worker xmlDictFree(dict);
776*6777b538SAndroid Build Coastguard Worker
777*6777b538SAndroid Build Coastguard Worker return ret;
778*6777b538SAndroid Build Coastguard Worker }
779*6777b538SAndroid Build Coastguard Worker
780*6777b538SAndroid Build Coastguard Worker static int
testall_hash(void)781*6777b538SAndroid Build Coastguard Worker testall_hash(void) {
782*6777b538SAndroid Build Coastguard Worker size_t num_keys;
783*6777b538SAndroid Build Coastguard Worker
784*6777b538SAndroid Build Coastguard Worker for (num_keys = 1; num_keys <= 3; num_keys++) {
785*6777b538SAndroid Build Coastguard Worker size_t num_strings;
786*6777b538SAndroid Build Coastguard Worker size_t max_strings = num_keys == 1 ? 100000 : 1000;
787*6777b538SAndroid Build Coastguard Worker
788*6777b538SAndroid Build Coastguard Worker for (num_strings = 10; num_strings <= max_strings; num_strings *= 10) {
789*6777b538SAndroid Build Coastguard Worker size_t reps, i;
790*6777b538SAndroid Build Coastguard Worker
791*6777b538SAndroid Build Coastguard Worker reps = 1000 / num_strings;
792*6777b538SAndroid Build Coastguard Worker if (reps == 0)
793*6777b538SAndroid Build Coastguard Worker reps = 1;
794*6777b538SAndroid Build Coastguard Worker
795*6777b538SAndroid Build Coastguard Worker for (i = 0; i < reps; i++) {
796*6777b538SAndroid Build Coastguard Worker if (test_hash(num_strings, num_keys, /* use_dict */ 0) != 0)
797*6777b538SAndroid Build Coastguard Worker return(1);
798*6777b538SAndroid Build Coastguard Worker }
799*6777b538SAndroid Build Coastguard Worker
800*6777b538SAndroid Build Coastguard Worker if (test_hash(num_strings, num_keys, /* use_dict */ 1) != 0)
801*6777b538SAndroid Build Coastguard Worker return(1);
802*6777b538SAndroid Build Coastguard Worker }
803*6777b538SAndroid Build Coastguard Worker }
804*6777b538SAndroid Build Coastguard Worker
805*6777b538SAndroid Build Coastguard Worker return(0);
806*6777b538SAndroid Build Coastguard Worker }
807*6777b538SAndroid Build Coastguard Worker
808*6777b538SAndroid Build Coastguard Worker
809*6777b538SAndroid Build Coastguard Worker /**** main ****/
810*6777b538SAndroid Build Coastguard Worker
811*6777b538SAndroid Build Coastguard Worker int
main(void)812*6777b538SAndroid Build Coastguard Worker main(void) {
813*6777b538SAndroid Build Coastguard Worker int ret = 0;
814*6777b538SAndroid Build Coastguard Worker
815*6777b538SAndroid Build Coastguard Worker LIBXML_TEST_VERSION
816*6777b538SAndroid Build Coastguard Worker
817*6777b538SAndroid Build Coastguard Worker if (testall_dict() != 0) {
818*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "dictionary tests failed\n");
819*6777b538SAndroid Build Coastguard Worker ret = 1;
820*6777b538SAndroid Build Coastguard Worker }
821*6777b538SAndroid Build Coastguard Worker if (testall_hash() != 0) {
822*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "hash tests failed\n");
823*6777b538SAndroid Build Coastguard Worker ret = 1;
824*6777b538SAndroid Build Coastguard Worker }
825*6777b538SAndroid Build Coastguard Worker
826*6777b538SAndroid Build Coastguard Worker xmlCleanupParser();
827*6777b538SAndroid Build Coastguard Worker return(ret);
828*6777b538SAndroid Build Coastguard Worker }
829