1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker * dict.c: dictionary of reusable strings, just used to avoid allocation
3*6777b538SAndroid Build Coastguard Worker * and freeing operations.
4*6777b538SAndroid Build Coastguard Worker *
5*6777b538SAndroid Build Coastguard Worker * Copyright (C) 2003-2012 Daniel Veillard.
6*6777b538SAndroid Build Coastguard Worker *
7*6777b538SAndroid Build Coastguard Worker * Permission to use, copy, modify, and distribute this software for any
8*6777b538SAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
9*6777b538SAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
10*6777b538SAndroid Build Coastguard Worker *
11*6777b538SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12*6777b538SAndroid Build Coastguard Worker * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13*6777b538SAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14*6777b538SAndroid Build Coastguard Worker * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15*6777b538SAndroid Build Coastguard Worker *
16*6777b538SAndroid Build Coastguard Worker * Author: [email protected]
17*6777b538SAndroid Build Coastguard Worker */
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
20*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker #include <errno.h>
23*6777b538SAndroid Build Coastguard Worker #include <limits.h>
24*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
25*6777b538SAndroid Build Coastguard Worker #include <string.h>
26*6777b538SAndroid Build Coastguard Worker #include <time.h>
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker #ifdef _WIN32
29*6777b538SAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
30*6777b538SAndroid Build Coastguard Worker #include <windows.h>
31*6777b538SAndroid Build Coastguard Worker #endif
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker #include "private/dict.h"
34*6777b538SAndroid Build Coastguard Worker #include "private/globals.h"
35*6777b538SAndroid Build Coastguard Worker #include "private/threads.h"
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
38*6777b538SAndroid Build Coastguard Worker #include <libxml/dict.h>
39*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
40*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlstring.h>
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker #ifndef SIZE_MAX
43*6777b538SAndroid Build Coastguard Worker #define SIZE_MAX ((size_t) -1)
44*6777b538SAndroid Build Coastguard Worker #endif
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker #define MAX_FILL_NUM 7
47*6777b538SAndroid Build Coastguard Worker #define MAX_FILL_DENOM 8
48*6777b538SAndroid Build Coastguard Worker #define MIN_HASH_SIZE 8
49*6777b538SAndroid Build Coastguard Worker #define MAX_HASH_SIZE (1u << 31)
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker typedef struct _xmlDictStrings xmlDictStrings;
52*6777b538SAndroid Build Coastguard Worker typedef xmlDictStrings *xmlDictStringsPtr;
53*6777b538SAndroid Build Coastguard Worker struct _xmlDictStrings {
54*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr next;
55*6777b538SAndroid Build Coastguard Worker xmlChar *free;
56*6777b538SAndroid Build Coastguard Worker xmlChar *end;
57*6777b538SAndroid Build Coastguard Worker size_t size;
58*6777b538SAndroid Build Coastguard Worker size_t nbStrings;
59*6777b538SAndroid Build Coastguard Worker xmlChar array[1];
60*6777b538SAndroid Build Coastguard Worker };
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker typedef xmlHashedString xmlDictEntry;
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker /*
65*6777b538SAndroid Build Coastguard Worker * The entire dictionary
66*6777b538SAndroid Build Coastguard Worker */
67*6777b538SAndroid Build Coastguard Worker struct _xmlDict {
68*6777b538SAndroid Build Coastguard Worker int ref_counter;
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker xmlDictEntry *table;
71*6777b538SAndroid Build Coastguard Worker size_t size;
72*6777b538SAndroid Build Coastguard Worker unsigned int nbElems;
73*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr strings;
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Worker struct _xmlDict *subdict;
76*6777b538SAndroid Build Coastguard Worker /* used for randomization */
77*6777b538SAndroid Build Coastguard Worker unsigned seed;
78*6777b538SAndroid Build Coastguard Worker /* used to impose a limit on size */
79*6777b538SAndroid Build Coastguard Worker size_t limit;
80*6777b538SAndroid Build Coastguard Worker };
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker /*
83*6777b538SAndroid Build Coastguard Worker * A mutex for modifying the reference counter for shared
84*6777b538SAndroid Build Coastguard Worker * dictionaries.
85*6777b538SAndroid Build Coastguard Worker */
86*6777b538SAndroid Build Coastguard Worker static xmlMutex xmlDictMutex;
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker /**
89*6777b538SAndroid Build Coastguard Worker * xmlInitializeDict:
90*6777b538SAndroid Build Coastguard Worker *
91*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Alias for xmlInitParser.
92*6777b538SAndroid Build Coastguard Worker *
93*6777b538SAndroid Build Coastguard Worker * Returns 0.
94*6777b538SAndroid Build Coastguard Worker */
95*6777b538SAndroid Build Coastguard Worker int
xmlInitializeDict(void)96*6777b538SAndroid Build Coastguard Worker xmlInitializeDict(void) {
97*6777b538SAndroid Build Coastguard Worker xmlInitParser();
98*6777b538SAndroid Build Coastguard Worker return(0);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker /**
102*6777b538SAndroid Build Coastguard Worker * xmlInitDictInternal:
103*6777b538SAndroid Build Coastguard Worker *
104*6777b538SAndroid Build Coastguard Worker * Initialize mutex.
105*6777b538SAndroid Build Coastguard Worker */
106*6777b538SAndroid Build Coastguard Worker void
xmlInitDictInternal(void)107*6777b538SAndroid Build Coastguard Worker xmlInitDictInternal(void) {
108*6777b538SAndroid Build Coastguard Worker xmlInitMutex(&xmlDictMutex);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker /**
112*6777b538SAndroid Build Coastguard Worker * xmlDictCleanup:
113*6777b538SAndroid Build Coastguard Worker *
114*6777b538SAndroid Build Coastguard Worker * DEPRECATED: This function is a no-op. Call xmlCleanupParser
115*6777b538SAndroid Build Coastguard Worker * to free global state but see the warnings there. xmlCleanupParser
116*6777b538SAndroid Build Coastguard Worker * should be only called once at program exit. In most cases, you don't
117*6777b538SAndroid Build Coastguard Worker * have call cleanup functions at all.
118*6777b538SAndroid Build Coastguard Worker */
119*6777b538SAndroid Build Coastguard Worker void
xmlDictCleanup(void)120*6777b538SAndroid Build Coastguard Worker xmlDictCleanup(void) {
121*6777b538SAndroid Build Coastguard Worker }
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker /**
124*6777b538SAndroid Build Coastguard Worker * xmlCleanupDictInternal:
125*6777b538SAndroid Build Coastguard Worker *
126*6777b538SAndroid Build Coastguard Worker * Free the dictionary mutex.
127*6777b538SAndroid Build Coastguard Worker */
128*6777b538SAndroid Build Coastguard Worker void
xmlCleanupDictInternal(void)129*6777b538SAndroid Build Coastguard Worker xmlCleanupDictInternal(void) {
130*6777b538SAndroid Build Coastguard Worker xmlCleanupMutex(&xmlDictMutex);
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker /*
134*6777b538SAndroid Build Coastguard Worker * xmlDictAddString:
135*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
136*6777b538SAndroid Build Coastguard Worker * @name: the name of the userdata
137*6777b538SAndroid Build Coastguard Worker * @len: the length of the name
138*6777b538SAndroid Build Coastguard Worker *
139*6777b538SAndroid Build Coastguard Worker * Add the string to the array[s]
140*6777b538SAndroid Build Coastguard Worker *
141*6777b538SAndroid Build Coastguard Worker * Returns the pointer of the local string, or NULL in case of error.
142*6777b538SAndroid Build Coastguard Worker */
143*6777b538SAndroid Build Coastguard Worker static const xmlChar *
xmlDictAddString(xmlDictPtr dict,const xmlChar * name,unsigned int namelen)144*6777b538SAndroid Build Coastguard Worker xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
145*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr pool;
146*6777b538SAndroid Build Coastguard Worker const xmlChar *ret;
147*6777b538SAndroid Build Coastguard Worker size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
148*6777b538SAndroid Build Coastguard Worker size_t limit = 0;
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker pool = dict->strings;
151*6777b538SAndroid Build Coastguard Worker while (pool != NULL) {
152*6777b538SAndroid Build Coastguard Worker if ((size_t)(pool->end - pool->free) > namelen)
153*6777b538SAndroid Build Coastguard Worker goto found_pool;
154*6777b538SAndroid Build Coastguard Worker if (pool->size > size) size = pool->size;
155*6777b538SAndroid Build Coastguard Worker limit += pool->size;
156*6777b538SAndroid Build Coastguard Worker pool = pool->next;
157*6777b538SAndroid Build Coastguard Worker }
158*6777b538SAndroid Build Coastguard Worker /*
159*6777b538SAndroid Build Coastguard Worker * Not found, need to allocate
160*6777b538SAndroid Build Coastguard Worker */
161*6777b538SAndroid Build Coastguard Worker if (pool == NULL) {
162*6777b538SAndroid Build Coastguard Worker if ((dict->limit > 0) && (limit > dict->limit)) {
163*6777b538SAndroid Build Coastguard Worker return(NULL);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker if (size == 0) {
167*6777b538SAndroid Build Coastguard Worker size = 1000;
168*6777b538SAndroid Build Coastguard Worker } else {
169*6777b538SAndroid Build Coastguard Worker if (size < (SIZE_MAX - sizeof(xmlDictStrings)) / 4)
170*6777b538SAndroid Build Coastguard Worker size *= 4; /* exponential growth */
171*6777b538SAndroid Build Coastguard Worker else
172*6777b538SAndroid Build Coastguard Worker size = SIZE_MAX - sizeof(xmlDictStrings);
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker if (size / 4 < namelen) {
175*6777b538SAndroid Build Coastguard Worker if ((size_t) namelen + 0 < (SIZE_MAX - sizeof(xmlDictStrings)) / 4)
176*6777b538SAndroid Build Coastguard Worker size = 4 * (size_t) namelen; /* just in case ! */
177*6777b538SAndroid Build Coastguard Worker else
178*6777b538SAndroid Build Coastguard Worker return(NULL);
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
181*6777b538SAndroid Build Coastguard Worker if (pool == NULL)
182*6777b538SAndroid Build Coastguard Worker return(NULL);
183*6777b538SAndroid Build Coastguard Worker pool->size = size;
184*6777b538SAndroid Build Coastguard Worker pool->nbStrings = 0;
185*6777b538SAndroid Build Coastguard Worker pool->free = &pool->array[0];
186*6777b538SAndroid Build Coastguard Worker pool->end = &pool->array[size];
187*6777b538SAndroid Build Coastguard Worker pool->next = dict->strings;
188*6777b538SAndroid Build Coastguard Worker dict->strings = pool;
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker found_pool:
191*6777b538SAndroid Build Coastguard Worker ret = pool->free;
192*6777b538SAndroid Build Coastguard Worker memcpy(pool->free, name, namelen);
193*6777b538SAndroid Build Coastguard Worker pool->free += namelen;
194*6777b538SAndroid Build Coastguard Worker *(pool->free++) = 0;
195*6777b538SAndroid Build Coastguard Worker pool->nbStrings++;
196*6777b538SAndroid Build Coastguard Worker return(ret);
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker /*
200*6777b538SAndroid Build Coastguard Worker * xmlDictAddQString:
201*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
202*6777b538SAndroid Build Coastguard Worker * @prefix: the prefix of the userdata
203*6777b538SAndroid Build Coastguard Worker * @plen: the prefix length
204*6777b538SAndroid Build Coastguard Worker * @name: the name of the userdata
205*6777b538SAndroid Build Coastguard Worker * @len: the length of the name
206*6777b538SAndroid Build Coastguard Worker *
207*6777b538SAndroid Build Coastguard Worker * Add the QName to the array[s]
208*6777b538SAndroid Build Coastguard Worker *
209*6777b538SAndroid Build Coastguard Worker * Returns the pointer of the local string, or NULL in case of error.
210*6777b538SAndroid Build Coastguard Worker */
211*6777b538SAndroid Build Coastguard Worker static const xmlChar *
xmlDictAddQString(xmlDictPtr dict,const xmlChar * prefix,unsigned int plen,const xmlChar * name,unsigned int namelen)212*6777b538SAndroid Build Coastguard Worker xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
213*6777b538SAndroid Build Coastguard Worker const xmlChar *name, unsigned int namelen)
214*6777b538SAndroid Build Coastguard Worker {
215*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr pool;
216*6777b538SAndroid Build Coastguard Worker const xmlChar *ret;
217*6777b538SAndroid Build Coastguard Worker size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
218*6777b538SAndroid Build Coastguard Worker size_t limit = 0;
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker pool = dict->strings;
221*6777b538SAndroid Build Coastguard Worker while (pool != NULL) {
222*6777b538SAndroid Build Coastguard Worker if ((size_t)(pool->end - pool->free) > namelen + plen + 1)
223*6777b538SAndroid Build Coastguard Worker goto found_pool;
224*6777b538SAndroid Build Coastguard Worker if (pool->size > size) size = pool->size;
225*6777b538SAndroid Build Coastguard Worker limit += pool->size;
226*6777b538SAndroid Build Coastguard Worker pool = pool->next;
227*6777b538SAndroid Build Coastguard Worker }
228*6777b538SAndroid Build Coastguard Worker /*
229*6777b538SAndroid Build Coastguard Worker * Not found, need to allocate
230*6777b538SAndroid Build Coastguard Worker */
231*6777b538SAndroid Build Coastguard Worker if (pool == NULL) {
232*6777b538SAndroid Build Coastguard Worker if ((dict->limit > 0) && (limit > dict->limit)) {
233*6777b538SAndroid Build Coastguard Worker return(NULL);
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker if (size == 0) size = 1000;
237*6777b538SAndroid Build Coastguard Worker else size *= 4; /* exponential growth */
238*6777b538SAndroid Build Coastguard Worker if (size < 4 * (namelen + plen + 1))
239*6777b538SAndroid Build Coastguard Worker size = 4 * (namelen + plen + 1); /* just in case ! */
240*6777b538SAndroid Build Coastguard Worker pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
241*6777b538SAndroid Build Coastguard Worker if (pool == NULL)
242*6777b538SAndroid Build Coastguard Worker return(NULL);
243*6777b538SAndroid Build Coastguard Worker pool->size = size;
244*6777b538SAndroid Build Coastguard Worker pool->nbStrings = 0;
245*6777b538SAndroid Build Coastguard Worker pool->free = &pool->array[0];
246*6777b538SAndroid Build Coastguard Worker pool->end = &pool->array[size];
247*6777b538SAndroid Build Coastguard Worker pool->next = dict->strings;
248*6777b538SAndroid Build Coastguard Worker dict->strings = pool;
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker found_pool:
251*6777b538SAndroid Build Coastguard Worker ret = pool->free;
252*6777b538SAndroid Build Coastguard Worker memcpy(pool->free, prefix, plen);
253*6777b538SAndroid Build Coastguard Worker pool->free += plen;
254*6777b538SAndroid Build Coastguard Worker *(pool->free++) = ':';
255*6777b538SAndroid Build Coastguard Worker memcpy(pool->free, name, namelen);
256*6777b538SAndroid Build Coastguard Worker pool->free += namelen;
257*6777b538SAndroid Build Coastguard Worker *(pool->free++) = 0;
258*6777b538SAndroid Build Coastguard Worker pool->nbStrings++;
259*6777b538SAndroid Build Coastguard Worker return(ret);
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker /**
263*6777b538SAndroid Build Coastguard Worker * xmlDictCreate:
264*6777b538SAndroid Build Coastguard Worker *
265*6777b538SAndroid Build Coastguard Worker * Create a new dictionary
266*6777b538SAndroid Build Coastguard Worker *
267*6777b538SAndroid Build Coastguard Worker * Returns the newly created dictionary, or NULL if an error occurred.
268*6777b538SAndroid Build Coastguard Worker */
269*6777b538SAndroid Build Coastguard Worker xmlDictPtr
xmlDictCreate(void)270*6777b538SAndroid Build Coastguard Worker xmlDictCreate(void) {
271*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict;
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker xmlInitParser();
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker dict = xmlMalloc(sizeof(xmlDict));
276*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
277*6777b538SAndroid Build Coastguard Worker return(NULL);
278*6777b538SAndroid Build Coastguard Worker dict->ref_counter = 1;
279*6777b538SAndroid Build Coastguard Worker dict->limit = 0;
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker dict->size = 0;
282*6777b538SAndroid Build Coastguard Worker dict->nbElems = 0;
283*6777b538SAndroid Build Coastguard Worker dict->table = NULL;
284*6777b538SAndroid Build Coastguard Worker dict->strings = NULL;
285*6777b538SAndroid Build Coastguard Worker dict->subdict = NULL;
286*6777b538SAndroid Build Coastguard Worker dict->seed = xmlRandom();
287*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
288*6777b538SAndroid Build Coastguard Worker dict->seed = 0;
289*6777b538SAndroid Build Coastguard Worker #endif
290*6777b538SAndroid Build Coastguard Worker return(dict);
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker /**
294*6777b538SAndroid Build Coastguard Worker * xmlDictCreateSub:
295*6777b538SAndroid Build Coastguard Worker * @sub: an existing dictionary
296*6777b538SAndroid Build Coastguard Worker *
297*6777b538SAndroid Build Coastguard Worker * Create a new dictionary, inheriting strings from the read-only
298*6777b538SAndroid Build Coastguard Worker * dictionary @sub. On lookup, strings are first searched in the
299*6777b538SAndroid Build Coastguard Worker * new dictionary, then in @sub, and if not found are created in the
300*6777b538SAndroid Build Coastguard Worker * new dictionary.
301*6777b538SAndroid Build Coastguard Worker *
302*6777b538SAndroid Build Coastguard Worker * Returns the newly created dictionary, or NULL if an error occurred.
303*6777b538SAndroid Build Coastguard Worker */
304*6777b538SAndroid Build Coastguard Worker xmlDictPtr
xmlDictCreateSub(xmlDictPtr sub)305*6777b538SAndroid Build Coastguard Worker xmlDictCreateSub(xmlDictPtr sub) {
306*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = xmlDictCreate();
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker if ((dict != NULL) && (sub != NULL)) {
309*6777b538SAndroid Build Coastguard Worker dict->seed = sub->seed;
310*6777b538SAndroid Build Coastguard Worker dict->subdict = sub;
311*6777b538SAndroid Build Coastguard Worker xmlDictReference(dict->subdict);
312*6777b538SAndroid Build Coastguard Worker }
313*6777b538SAndroid Build Coastguard Worker return(dict);
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker /**
317*6777b538SAndroid Build Coastguard Worker * xmlDictReference:
318*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
319*6777b538SAndroid Build Coastguard Worker *
320*6777b538SAndroid Build Coastguard Worker * Increment the reference counter of a dictionary
321*6777b538SAndroid Build Coastguard Worker *
322*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of error
323*6777b538SAndroid Build Coastguard Worker */
324*6777b538SAndroid Build Coastguard Worker int
xmlDictReference(xmlDictPtr dict)325*6777b538SAndroid Build Coastguard Worker xmlDictReference(xmlDictPtr dict) {
326*6777b538SAndroid Build Coastguard Worker if (dict == NULL) return -1;
327*6777b538SAndroid Build Coastguard Worker xmlMutexLock(&xmlDictMutex);
328*6777b538SAndroid Build Coastguard Worker dict->ref_counter++;
329*6777b538SAndroid Build Coastguard Worker xmlMutexUnlock(&xmlDictMutex);
330*6777b538SAndroid Build Coastguard Worker return(0);
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker /**
334*6777b538SAndroid Build Coastguard Worker * xmlDictFree:
335*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
336*6777b538SAndroid Build Coastguard Worker *
337*6777b538SAndroid Build Coastguard Worker * Free the hash @dict and its contents. The userdata is
338*6777b538SAndroid Build Coastguard Worker * deallocated with @f if provided.
339*6777b538SAndroid Build Coastguard Worker */
340*6777b538SAndroid Build Coastguard Worker void
xmlDictFree(xmlDictPtr dict)341*6777b538SAndroid Build Coastguard Worker xmlDictFree(xmlDictPtr dict) {
342*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr pool, nextp;
343*6777b538SAndroid Build Coastguard Worker
344*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
345*6777b538SAndroid Build Coastguard Worker return;
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker /* decrement the counter, it may be shared by a parser and docs */
348*6777b538SAndroid Build Coastguard Worker xmlMutexLock(&xmlDictMutex);
349*6777b538SAndroid Build Coastguard Worker dict->ref_counter--;
350*6777b538SAndroid Build Coastguard Worker if (dict->ref_counter > 0) {
351*6777b538SAndroid Build Coastguard Worker xmlMutexUnlock(&xmlDictMutex);
352*6777b538SAndroid Build Coastguard Worker return;
353*6777b538SAndroid Build Coastguard Worker }
354*6777b538SAndroid Build Coastguard Worker
355*6777b538SAndroid Build Coastguard Worker xmlMutexUnlock(&xmlDictMutex);
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker if (dict->subdict != NULL) {
358*6777b538SAndroid Build Coastguard Worker xmlDictFree(dict->subdict);
359*6777b538SAndroid Build Coastguard Worker }
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker if (dict->table) {
362*6777b538SAndroid Build Coastguard Worker xmlFree(dict->table);
363*6777b538SAndroid Build Coastguard Worker }
364*6777b538SAndroid Build Coastguard Worker pool = dict->strings;
365*6777b538SAndroid Build Coastguard Worker while (pool != NULL) {
366*6777b538SAndroid Build Coastguard Worker nextp = pool->next;
367*6777b538SAndroid Build Coastguard Worker xmlFree(pool);
368*6777b538SAndroid Build Coastguard Worker pool = nextp;
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker xmlFree(dict);
371*6777b538SAndroid Build Coastguard Worker }
372*6777b538SAndroid Build Coastguard Worker
373*6777b538SAndroid Build Coastguard Worker /**
374*6777b538SAndroid Build Coastguard Worker * xmlDictOwns:
375*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
376*6777b538SAndroid Build Coastguard Worker * @str: the string
377*6777b538SAndroid Build Coastguard Worker *
378*6777b538SAndroid Build Coastguard Worker * check if a string is owned by the dictionary
379*6777b538SAndroid Build Coastguard Worker *
380*6777b538SAndroid Build Coastguard Worker * Returns 1 if true, 0 if false and -1 in case of error
381*6777b538SAndroid Build Coastguard Worker * -1 in case of error
382*6777b538SAndroid Build Coastguard Worker */
383*6777b538SAndroid Build Coastguard Worker int
xmlDictOwns(xmlDictPtr dict,const xmlChar * str)384*6777b538SAndroid Build Coastguard Worker xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
385*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr pool;
386*6777b538SAndroid Build Coastguard Worker
387*6777b538SAndroid Build Coastguard Worker if ((dict == NULL) || (str == NULL))
388*6777b538SAndroid Build Coastguard Worker return(-1);
389*6777b538SAndroid Build Coastguard Worker pool = dict->strings;
390*6777b538SAndroid Build Coastguard Worker while (pool != NULL) {
391*6777b538SAndroid Build Coastguard Worker if ((str >= &pool->array[0]) && (str <= pool->free))
392*6777b538SAndroid Build Coastguard Worker return(1);
393*6777b538SAndroid Build Coastguard Worker pool = pool->next;
394*6777b538SAndroid Build Coastguard Worker }
395*6777b538SAndroid Build Coastguard Worker if (dict->subdict)
396*6777b538SAndroid Build Coastguard Worker return(xmlDictOwns(dict->subdict, str));
397*6777b538SAndroid Build Coastguard Worker return(0);
398*6777b538SAndroid Build Coastguard Worker }
399*6777b538SAndroid Build Coastguard Worker
400*6777b538SAndroid Build Coastguard Worker /**
401*6777b538SAndroid Build Coastguard Worker * xmlDictSize:
402*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
403*6777b538SAndroid Build Coastguard Worker *
404*6777b538SAndroid Build Coastguard Worker * Query the number of elements installed in the hash @dict.
405*6777b538SAndroid Build Coastguard Worker *
406*6777b538SAndroid Build Coastguard Worker * Returns the number of elements in the dictionary or
407*6777b538SAndroid Build Coastguard Worker * -1 in case of error
408*6777b538SAndroid Build Coastguard Worker */
409*6777b538SAndroid Build Coastguard Worker int
xmlDictSize(xmlDictPtr dict)410*6777b538SAndroid Build Coastguard Worker xmlDictSize(xmlDictPtr dict) {
411*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
412*6777b538SAndroid Build Coastguard Worker return(-1);
413*6777b538SAndroid Build Coastguard Worker if (dict->subdict)
414*6777b538SAndroid Build Coastguard Worker return(dict->nbElems + dict->subdict->nbElems);
415*6777b538SAndroid Build Coastguard Worker return(dict->nbElems);
416*6777b538SAndroid Build Coastguard Worker }
417*6777b538SAndroid Build Coastguard Worker
418*6777b538SAndroid Build Coastguard Worker /**
419*6777b538SAndroid Build Coastguard Worker * xmlDictSetLimit:
420*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
421*6777b538SAndroid Build Coastguard Worker * @limit: the limit in bytes
422*6777b538SAndroid Build Coastguard Worker *
423*6777b538SAndroid Build Coastguard Worker * Set a size limit for the dictionary
424*6777b538SAndroid Build Coastguard Worker * Added in 2.9.0
425*6777b538SAndroid Build Coastguard Worker *
426*6777b538SAndroid Build Coastguard Worker * Returns the previous limit of the dictionary or 0
427*6777b538SAndroid Build Coastguard Worker */
428*6777b538SAndroid Build Coastguard Worker size_t
xmlDictSetLimit(xmlDictPtr dict,size_t limit)429*6777b538SAndroid Build Coastguard Worker xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
430*6777b538SAndroid Build Coastguard Worker size_t ret;
431*6777b538SAndroid Build Coastguard Worker
432*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
433*6777b538SAndroid Build Coastguard Worker return(0);
434*6777b538SAndroid Build Coastguard Worker ret = dict->limit;
435*6777b538SAndroid Build Coastguard Worker dict->limit = limit;
436*6777b538SAndroid Build Coastguard Worker return(ret);
437*6777b538SAndroid Build Coastguard Worker }
438*6777b538SAndroid Build Coastguard Worker
439*6777b538SAndroid Build Coastguard Worker /**
440*6777b538SAndroid Build Coastguard Worker * xmlDictGetUsage:
441*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
442*6777b538SAndroid Build Coastguard Worker *
443*6777b538SAndroid Build Coastguard Worker * Get how much memory is used by a dictionary for strings
444*6777b538SAndroid Build Coastguard Worker * Added in 2.9.0
445*6777b538SAndroid Build Coastguard Worker *
446*6777b538SAndroid Build Coastguard Worker * Returns the amount of strings allocated
447*6777b538SAndroid Build Coastguard Worker */
448*6777b538SAndroid Build Coastguard Worker size_t
xmlDictGetUsage(xmlDictPtr dict)449*6777b538SAndroid Build Coastguard Worker xmlDictGetUsage(xmlDictPtr dict) {
450*6777b538SAndroid Build Coastguard Worker xmlDictStringsPtr pool;
451*6777b538SAndroid Build Coastguard Worker size_t limit = 0;
452*6777b538SAndroid Build Coastguard Worker
453*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
454*6777b538SAndroid Build Coastguard Worker return(0);
455*6777b538SAndroid Build Coastguard Worker pool = dict->strings;
456*6777b538SAndroid Build Coastguard Worker while (pool != NULL) {
457*6777b538SAndroid Build Coastguard Worker limit += pool->size;
458*6777b538SAndroid Build Coastguard Worker pool = pool->next;
459*6777b538SAndroid Build Coastguard Worker }
460*6777b538SAndroid Build Coastguard Worker return(limit);
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker
463*6777b538SAndroid Build Coastguard Worker /*****************************************************************
464*6777b538SAndroid Build Coastguard Worker *
465*6777b538SAndroid Build Coastguard Worker * The code below was rewritten and is additionally licensed under
466*6777b538SAndroid Build Coastguard Worker * the main license in file 'Copyright'.
467*6777b538SAndroid Build Coastguard Worker *
468*6777b538SAndroid Build Coastguard Worker *****************************************************************/
469*6777b538SAndroid Build Coastguard Worker
470*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
471*6777b538SAndroid Build Coastguard Worker static unsigned
xmlDictHashName(unsigned seed,const xmlChar * data,size_t maxLen,size_t * plen)472*6777b538SAndroid Build Coastguard Worker xmlDictHashName(unsigned seed, const xmlChar* data, size_t maxLen,
473*6777b538SAndroid Build Coastguard Worker size_t *plen) {
474*6777b538SAndroid Build Coastguard Worker unsigned h1, h2;
475*6777b538SAndroid Build Coastguard Worker size_t i;
476*6777b538SAndroid Build Coastguard Worker
477*6777b538SAndroid Build Coastguard Worker HASH_INIT(h1, h2, seed);
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker for (i = 0; i < maxLen && data[i]; i++) {
480*6777b538SAndroid Build Coastguard Worker HASH_UPDATE(h1, h2, data[i]);
481*6777b538SAndroid Build Coastguard Worker }
482*6777b538SAndroid Build Coastguard Worker
483*6777b538SAndroid Build Coastguard Worker HASH_FINISH(h1, h2);
484*6777b538SAndroid Build Coastguard Worker
485*6777b538SAndroid Build Coastguard Worker *plen = i;
486*6777b538SAndroid Build Coastguard Worker return(h2 | MAX_HASH_SIZE);
487*6777b538SAndroid Build Coastguard Worker }
488*6777b538SAndroid Build Coastguard Worker
489*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
490*6777b538SAndroid Build Coastguard Worker static unsigned
xmlDictHashQName(unsigned seed,const xmlChar * prefix,const xmlChar * name,size_t * pplen,size_t * plen)491*6777b538SAndroid Build Coastguard Worker xmlDictHashQName(unsigned seed, const xmlChar *prefix, const xmlChar *name,
492*6777b538SAndroid Build Coastguard Worker size_t *pplen, size_t *plen) {
493*6777b538SAndroid Build Coastguard Worker unsigned h1, h2;
494*6777b538SAndroid Build Coastguard Worker size_t i;
495*6777b538SAndroid Build Coastguard Worker
496*6777b538SAndroid Build Coastguard Worker HASH_INIT(h1, h2, seed);
497*6777b538SAndroid Build Coastguard Worker
498*6777b538SAndroid Build Coastguard Worker for (i = 0; prefix[i] != 0; i++) {
499*6777b538SAndroid Build Coastguard Worker HASH_UPDATE(h1, h2, prefix[i]);
500*6777b538SAndroid Build Coastguard Worker }
501*6777b538SAndroid Build Coastguard Worker *pplen = i;
502*6777b538SAndroid Build Coastguard Worker
503*6777b538SAndroid Build Coastguard Worker HASH_UPDATE(h1, h2, ':');
504*6777b538SAndroid Build Coastguard Worker
505*6777b538SAndroid Build Coastguard Worker for (i = 0; name[i] != 0; i++) {
506*6777b538SAndroid Build Coastguard Worker HASH_UPDATE(h1, h2, name[i]);
507*6777b538SAndroid Build Coastguard Worker }
508*6777b538SAndroid Build Coastguard Worker *plen = i;
509*6777b538SAndroid Build Coastguard Worker
510*6777b538SAndroid Build Coastguard Worker HASH_FINISH(h1, h2);
511*6777b538SAndroid Build Coastguard Worker
512*6777b538SAndroid Build Coastguard Worker /*
513*6777b538SAndroid Build Coastguard Worker * Always set the upper bit of hash values since 0 means an unoccupied
514*6777b538SAndroid Build Coastguard Worker * bucket.
515*6777b538SAndroid Build Coastguard Worker */
516*6777b538SAndroid Build Coastguard Worker return(h2 | MAX_HASH_SIZE);
517*6777b538SAndroid Build Coastguard Worker }
518*6777b538SAndroid Build Coastguard Worker
519*6777b538SAndroid Build Coastguard Worker unsigned
xmlDictComputeHash(const xmlDict * dict,const xmlChar * string)520*6777b538SAndroid Build Coastguard Worker xmlDictComputeHash(const xmlDict *dict, const xmlChar *string) {
521*6777b538SAndroid Build Coastguard Worker size_t len;
522*6777b538SAndroid Build Coastguard Worker return(xmlDictHashName(dict->seed, string, SIZE_MAX, &len));
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker
525*6777b538SAndroid Build Coastguard Worker #define HASH_ROL31(x,n) ((x) << (n) | ((x) & 0x7FFFFFFF) >> (31 - (n)))
526*6777b538SAndroid Build Coastguard Worker
527*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
528*6777b538SAndroid Build Coastguard Worker unsigned
xmlDictCombineHash(unsigned v1,unsigned v2)529*6777b538SAndroid Build Coastguard Worker xmlDictCombineHash(unsigned v1, unsigned v2) {
530*6777b538SAndroid Build Coastguard Worker /*
531*6777b538SAndroid Build Coastguard Worker * The upper bit of hash values is always set, so we have to operate on
532*6777b538SAndroid Build Coastguard Worker * 31-bit hashes here.
533*6777b538SAndroid Build Coastguard Worker */
534*6777b538SAndroid Build Coastguard Worker v1 ^= v2;
535*6777b538SAndroid Build Coastguard Worker v1 += HASH_ROL31(v2, 5);
536*6777b538SAndroid Build Coastguard Worker
537*6777b538SAndroid Build Coastguard Worker return((v1 & 0xFFFFFFFF) | 0x80000000);
538*6777b538SAndroid Build Coastguard Worker }
539*6777b538SAndroid Build Coastguard Worker
540*6777b538SAndroid Build Coastguard Worker /**
541*6777b538SAndroid Build Coastguard Worker * xmlDictFindEntry:
542*6777b538SAndroid Build Coastguard Worker * @dict: dict
543*6777b538SAndroid Build Coastguard Worker * @prefix: optional QName prefix
544*6777b538SAndroid Build Coastguard Worker * @name: string
545*6777b538SAndroid Build Coastguard Worker * @len: length of string
546*6777b538SAndroid Build Coastguard Worker * @hashValue: valid hash value of string
547*6777b538SAndroid Build Coastguard Worker * @pfound: result of search
548*6777b538SAndroid Build Coastguard Worker *
549*6777b538SAndroid Build Coastguard Worker * Try to find a matching hash table entry. If an entry was found, set
550*6777b538SAndroid Build Coastguard Worker * @found to 1 and return the entry. Otherwise, set @found to 0 and return
551*6777b538SAndroid Build Coastguard Worker * the location where a new entry should be inserted.
552*6777b538SAndroid Build Coastguard Worker */
553*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
554*6777b538SAndroid Build Coastguard Worker static xmlDictEntry *
xmlDictFindEntry(const xmlDict * dict,const xmlChar * prefix,const xmlChar * name,int len,unsigned hashValue,int * pfound)555*6777b538SAndroid Build Coastguard Worker xmlDictFindEntry(const xmlDict *dict, const xmlChar *prefix,
556*6777b538SAndroid Build Coastguard Worker const xmlChar *name, int len, unsigned hashValue,
557*6777b538SAndroid Build Coastguard Worker int *pfound) {
558*6777b538SAndroid Build Coastguard Worker xmlDictEntry *entry;
559*6777b538SAndroid Build Coastguard Worker unsigned mask, pos, displ;
560*6777b538SAndroid Build Coastguard Worker int found = 0;
561*6777b538SAndroid Build Coastguard Worker
562*6777b538SAndroid Build Coastguard Worker mask = dict->size - 1;
563*6777b538SAndroid Build Coastguard Worker pos = hashValue & mask;
564*6777b538SAndroid Build Coastguard Worker entry = &dict->table[pos];
565*6777b538SAndroid Build Coastguard Worker
566*6777b538SAndroid Build Coastguard Worker if (entry->hashValue != 0) {
567*6777b538SAndroid Build Coastguard Worker /*
568*6777b538SAndroid Build Coastguard Worker * Robin hood hashing: abort if the displacement of the entry
569*6777b538SAndroid Build Coastguard Worker * is smaller than the displacement of the key we look for.
570*6777b538SAndroid Build Coastguard Worker * This also stops at the correct position when inserting.
571*6777b538SAndroid Build Coastguard Worker */
572*6777b538SAndroid Build Coastguard Worker displ = 0;
573*6777b538SAndroid Build Coastguard Worker
574*6777b538SAndroid Build Coastguard Worker do {
575*6777b538SAndroid Build Coastguard Worker if (entry->hashValue == hashValue) {
576*6777b538SAndroid Build Coastguard Worker if (prefix == NULL) {
577*6777b538SAndroid Build Coastguard Worker /*
578*6777b538SAndroid Build Coastguard Worker * name is not necessarily null-terminated.
579*6777b538SAndroid Build Coastguard Worker */
580*6777b538SAndroid Build Coastguard Worker if ((strncmp((const char *) entry->name,
581*6777b538SAndroid Build Coastguard Worker (const char *) name, len) == 0) &&
582*6777b538SAndroid Build Coastguard Worker (entry->name[len] == 0)) {
583*6777b538SAndroid Build Coastguard Worker found = 1;
584*6777b538SAndroid Build Coastguard Worker break;
585*6777b538SAndroid Build Coastguard Worker }
586*6777b538SAndroid Build Coastguard Worker } else {
587*6777b538SAndroid Build Coastguard Worker if (xmlStrQEqual(prefix, name, entry->name)) {
588*6777b538SAndroid Build Coastguard Worker found = 1;
589*6777b538SAndroid Build Coastguard Worker break;
590*6777b538SAndroid Build Coastguard Worker }
591*6777b538SAndroid Build Coastguard Worker }
592*6777b538SAndroid Build Coastguard Worker }
593*6777b538SAndroid Build Coastguard Worker
594*6777b538SAndroid Build Coastguard Worker displ++;
595*6777b538SAndroid Build Coastguard Worker pos++;
596*6777b538SAndroid Build Coastguard Worker entry++;
597*6777b538SAndroid Build Coastguard Worker if ((pos & mask) == 0)
598*6777b538SAndroid Build Coastguard Worker entry = dict->table;
599*6777b538SAndroid Build Coastguard Worker } while ((entry->hashValue != 0) &&
600*6777b538SAndroid Build Coastguard Worker (((pos - entry->hashValue) & mask) >= displ));
601*6777b538SAndroid Build Coastguard Worker }
602*6777b538SAndroid Build Coastguard Worker
603*6777b538SAndroid Build Coastguard Worker *pfound = found;
604*6777b538SAndroid Build Coastguard Worker return(entry);
605*6777b538SAndroid Build Coastguard Worker }
606*6777b538SAndroid Build Coastguard Worker
607*6777b538SAndroid Build Coastguard Worker /**
608*6777b538SAndroid Build Coastguard Worker * xmlDictGrow:
609*6777b538SAndroid Build Coastguard Worker * @dict: dictionary
610*6777b538SAndroid Build Coastguard Worker * @size: new size of the dictionary
611*6777b538SAndroid Build Coastguard Worker *
612*6777b538SAndroid Build Coastguard Worker * Resize the dictionary hash table.
613*6777b538SAndroid Build Coastguard Worker *
614*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 if a memory allocation failed.
615*6777b538SAndroid Build Coastguard Worker */
616*6777b538SAndroid Build Coastguard Worker static int
xmlDictGrow(xmlDictPtr dict,unsigned size)617*6777b538SAndroid Build Coastguard Worker xmlDictGrow(xmlDictPtr dict, unsigned size) {
618*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *oldentry, *oldend, *end;
619*6777b538SAndroid Build Coastguard Worker xmlDictEntry *table;
620*6777b538SAndroid Build Coastguard Worker unsigned oldsize, i;
621*6777b538SAndroid Build Coastguard Worker
622*6777b538SAndroid Build Coastguard Worker /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */
623*6777b538SAndroid Build Coastguard Worker if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0]))
624*6777b538SAndroid Build Coastguard Worker return(-1);
625*6777b538SAndroid Build Coastguard Worker table = xmlMalloc(size * sizeof(table[0]));
626*6777b538SAndroid Build Coastguard Worker if (table == NULL)
627*6777b538SAndroid Build Coastguard Worker return(-1);
628*6777b538SAndroid Build Coastguard Worker memset(table, 0, size * sizeof(table[0]));
629*6777b538SAndroid Build Coastguard Worker
630*6777b538SAndroid Build Coastguard Worker oldsize = dict->size;
631*6777b538SAndroid Build Coastguard Worker if (oldsize == 0)
632*6777b538SAndroid Build Coastguard Worker goto done;
633*6777b538SAndroid Build Coastguard Worker
634*6777b538SAndroid Build Coastguard Worker oldend = &dict->table[oldsize];
635*6777b538SAndroid Build Coastguard Worker end = &table[size];
636*6777b538SAndroid Build Coastguard Worker
637*6777b538SAndroid Build Coastguard Worker /*
638*6777b538SAndroid Build Coastguard Worker * Robin Hood sorting order is maintained if we
639*6777b538SAndroid Build Coastguard Worker *
640*6777b538SAndroid Build Coastguard Worker * - compute dict indices with modulo
641*6777b538SAndroid Build Coastguard Worker * - resize by an integer factor
642*6777b538SAndroid Build Coastguard Worker * - start to copy from the beginning of a probe sequence
643*6777b538SAndroid Build Coastguard Worker */
644*6777b538SAndroid Build Coastguard Worker oldentry = dict->table;
645*6777b538SAndroid Build Coastguard Worker while (oldentry->hashValue != 0) {
646*6777b538SAndroid Build Coastguard Worker if (++oldentry >= oldend)
647*6777b538SAndroid Build Coastguard Worker oldentry = dict->table;
648*6777b538SAndroid Build Coastguard Worker }
649*6777b538SAndroid Build Coastguard Worker
650*6777b538SAndroid Build Coastguard Worker for (i = 0; i < oldsize; i++) {
651*6777b538SAndroid Build Coastguard Worker if (oldentry->hashValue != 0) {
652*6777b538SAndroid Build Coastguard Worker xmlDictEntry *entry = &table[oldentry->hashValue & (size - 1)];
653*6777b538SAndroid Build Coastguard Worker
654*6777b538SAndroid Build Coastguard Worker while (entry->hashValue != 0) {
655*6777b538SAndroid Build Coastguard Worker if (++entry >= end)
656*6777b538SAndroid Build Coastguard Worker entry = table;
657*6777b538SAndroid Build Coastguard Worker }
658*6777b538SAndroid Build Coastguard Worker *entry = *oldentry;
659*6777b538SAndroid Build Coastguard Worker }
660*6777b538SAndroid Build Coastguard Worker
661*6777b538SAndroid Build Coastguard Worker if (++oldentry >= oldend)
662*6777b538SAndroid Build Coastguard Worker oldentry = dict->table;
663*6777b538SAndroid Build Coastguard Worker }
664*6777b538SAndroid Build Coastguard Worker
665*6777b538SAndroid Build Coastguard Worker xmlFree(dict->table);
666*6777b538SAndroid Build Coastguard Worker
667*6777b538SAndroid Build Coastguard Worker done:
668*6777b538SAndroid Build Coastguard Worker dict->table = table;
669*6777b538SAndroid Build Coastguard Worker dict->size = size;
670*6777b538SAndroid Build Coastguard Worker
671*6777b538SAndroid Build Coastguard Worker return(0);
672*6777b538SAndroid Build Coastguard Worker }
673*6777b538SAndroid Build Coastguard Worker
674*6777b538SAndroid Build Coastguard Worker /**
675*6777b538SAndroid Build Coastguard Worker * xmlDictLookupInternal:
676*6777b538SAndroid Build Coastguard Worker * @dict: dict
677*6777b538SAndroid Build Coastguard Worker * @prefix: optional QName prefix
678*6777b538SAndroid Build Coastguard Worker * @name: string
679*6777b538SAndroid Build Coastguard Worker * @maybeLen: length of string or -1 if unknown
680*6777b538SAndroid Build Coastguard Worker * @update: whether the string should be added
681*6777b538SAndroid Build Coastguard Worker *
682*6777b538SAndroid Build Coastguard Worker * Internal lookup and update function.
683*6777b538SAndroid Build Coastguard Worker */
684*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
685*6777b538SAndroid Build Coastguard Worker static const xmlDictEntry *
xmlDictLookupInternal(xmlDictPtr dict,const xmlChar * prefix,const xmlChar * name,int maybeLen,int update)686*6777b538SAndroid Build Coastguard Worker xmlDictLookupInternal(xmlDictPtr dict, const xmlChar *prefix,
687*6777b538SAndroid Build Coastguard Worker const xmlChar *name, int maybeLen, int update) {
688*6777b538SAndroid Build Coastguard Worker xmlDictEntry *entry = NULL;
689*6777b538SAndroid Build Coastguard Worker const xmlChar *ret;
690*6777b538SAndroid Build Coastguard Worker unsigned hashValue;
691*6777b538SAndroid Build Coastguard Worker size_t maxLen, len, plen, klen;
692*6777b538SAndroid Build Coastguard Worker int found = 0;
693*6777b538SAndroid Build Coastguard Worker
694*6777b538SAndroid Build Coastguard Worker if ((dict == NULL) || (name == NULL))
695*6777b538SAndroid Build Coastguard Worker return(NULL);
696*6777b538SAndroid Build Coastguard Worker
697*6777b538SAndroid Build Coastguard Worker maxLen = (maybeLen < 0) ? SIZE_MAX : (size_t) maybeLen;
698*6777b538SAndroid Build Coastguard Worker
699*6777b538SAndroid Build Coastguard Worker if (prefix == NULL) {
700*6777b538SAndroid Build Coastguard Worker hashValue = xmlDictHashName(dict->seed, name, maxLen, &len);
701*6777b538SAndroid Build Coastguard Worker if (len > INT_MAX / 2)
702*6777b538SAndroid Build Coastguard Worker return(NULL);
703*6777b538SAndroid Build Coastguard Worker klen = len;
704*6777b538SAndroid Build Coastguard Worker } else {
705*6777b538SAndroid Build Coastguard Worker hashValue = xmlDictHashQName(dict->seed, prefix, name, &plen, &len);
706*6777b538SAndroid Build Coastguard Worker if ((len > INT_MAX / 2) || (plen >= INT_MAX / 2 - len))
707*6777b538SAndroid Build Coastguard Worker return(NULL);
708*6777b538SAndroid Build Coastguard Worker klen = plen + 1 + len;
709*6777b538SAndroid Build Coastguard Worker }
710*6777b538SAndroid Build Coastguard Worker
711*6777b538SAndroid Build Coastguard Worker if ((dict->limit > 0) && (klen >= dict->limit))
712*6777b538SAndroid Build Coastguard Worker return(NULL);
713*6777b538SAndroid Build Coastguard Worker
714*6777b538SAndroid Build Coastguard Worker /*
715*6777b538SAndroid Build Coastguard Worker * Check for an existing entry
716*6777b538SAndroid Build Coastguard Worker */
717*6777b538SAndroid Build Coastguard Worker if (dict->size > 0)
718*6777b538SAndroid Build Coastguard Worker entry = xmlDictFindEntry(dict, prefix, name, klen, hashValue, &found);
719*6777b538SAndroid Build Coastguard Worker if (found)
720*6777b538SAndroid Build Coastguard Worker return(entry);
721*6777b538SAndroid Build Coastguard Worker
722*6777b538SAndroid Build Coastguard Worker if ((dict->subdict != NULL) && (dict->subdict->size > 0)) {
723*6777b538SAndroid Build Coastguard Worker xmlDictEntry *subEntry;
724*6777b538SAndroid Build Coastguard Worker unsigned subHashValue;
725*6777b538SAndroid Build Coastguard Worker
726*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
727*6777b538SAndroid Build Coastguard Worker subHashValue = xmlDictHashName(dict->subdict->seed, name, len,
728*6777b538SAndroid Build Coastguard Worker &len);
729*6777b538SAndroid Build Coastguard Worker else
730*6777b538SAndroid Build Coastguard Worker subHashValue = xmlDictHashQName(dict->subdict->seed, prefix, name,
731*6777b538SAndroid Build Coastguard Worker &plen, &len);
732*6777b538SAndroid Build Coastguard Worker subEntry = xmlDictFindEntry(dict->subdict, prefix, name, klen,
733*6777b538SAndroid Build Coastguard Worker subHashValue, &found);
734*6777b538SAndroid Build Coastguard Worker if (found)
735*6777b538SAndroid Build Coastguard Worker return(subEntry);
736*6777b538SAndroid Build Coastguard Worker }
737*6777b538SAndroid Build Coastguard Worker
738*6777b538SAndroid Build Coastguard Worker if (!update)
739*6777b538SAndroid Build Coastguard Worker return(NULL);
740*6777b538SAndroid Build Coastguard Worker
741*6777b538SAndroid Build Coastguard Worker /*
742*6777b538SAndroid Build Coastguard Worker * Grow the hash table if needed
743*6777b538SAndroid Build Coastguard Worker */
744*6777b538SAndroid Build Coastguard Worker if (dict->nbElems + 1 > dict->size / MAX_FILL_DENOM * MAX_FILL_NUM) {
745*6777b538SAndroid Build Coastguard Worker unsigned newSize, mask, displ, pos;
746*6777b538SAndroid Build Coastguard Worker
747*6777b538SAndroid Build Coastguard Worker if (dict->size == 0) {
748*6777b538SAndroid Build Coastguard Worker newSize = MIN_HASH_SIZE;
749*6777b538SAndroid Build Coastguard Worker } else {
750*6777b538SAndroid Build Coastguard Worker if (dict->size >= MAX_HASH_SIZE)
751*6777b538SAndroid Build Coastguard Worker return(NULL);
752*6777b538SAndroid Build Coastguard Worker newSize = dict->size * 2;
753*6777b538SAndroid Build Coastguard Worker }
754*6777b538SAndroid Build Coastguard Worker if (xmlDictGrow(dict, newSize) != 0)
755*6777b538SAndroid Build Coastguard Worker return(NULL);
756*6777b538SAndroid Build Coastguard Worker
757*6777b538SAndroid Build Coastguard Worker /*
758*6777b538SAndroid Build Coastguard Worker * Find new entry
759*6777b538SAndroid Build Coastguard Worker */
760*6777b538SAndroid Build Coastguard Worker mask = dict->size - 1;
761*6777b538SAndroid Build Coastguard Worker displ = 0;
762*6777b538SAndroid Build Coastguard Worker pos = hashValue & mask;
763*6777b538SAndroid Build Coastguard Worker entry = &dict->table[pos];
764*6777b538SAndroid Build Coastguard Worker
765*6777b538SAndroid Build Coastguard Worker while ((entry->hashValue != 0) &&
766*6777b538SAndroid Build Coastguard Worker ((pos - entry->hashValue) & mask) >= displ) {
767*6777b538SAndroid Build Coastguard Worker displ++;
768*6777b538SAndroid Build Coastguard Worker pos++;
769*6777b538SAndroid Build Coastguard Worker entry++;
770*6777b538SAndroid Build Coastguard Worker if ((pos & mask) == 0)
771*6777b538SAndroid Build Coastguard Worker entry = dict->table;
772*6777b538SAndroid Build Coastguard Worker }
773*6777b538SAndroid Build Coastguard Worker }
774*6777b538SAndroid Build Coastguard Worker
775*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
776*6777b538SAndroid Build Coastguard Worker ret = xmlDictAddString(dict, name, len);
777*6777b538SAndroid Build Coastguard Worker else
778*6777b538SAndroid Build Coastguard Worker ret = xmlDictAddQString(dict, prefix, plen, name, len);
779*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
780*6777b538SAndroid Build Coastguard Worker return(NULL);
781*6777b538SAndroid Build Coastguard Worker
782*6777b538SAndroid Build Coastguard Worker /*
783*6777b538SAndroid Build Coastguard Worker * Shift the remainder of the probe sequence to the right
784*6777b538SAndroid Build Coastguard Worker */
785*6777b538SAndroid Build Coastguard Worker if (entry->hashValue != 0) {
786*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *end = &dict->table[dict->size];
787*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *cur = entry;
788*6777b538SAndroid Build Coastguard Worker
789*6777b538SAndroid Build Coastguard Worker do {
790*6777b538SAndroid Build Coastguard Worker cur++;
791*6777b538SAndroid Build Coastguard Worker if (cur >= end)
792*6777b538SAndroid Build Coastguard Worker cur = dict->table;
793*6777b538SAndroid Build Coastguard Worker } while (cur->hashValue != 0);
794*6777b538SAndroid Build Coastguard Worker
795*6777b538SAndroid Build Coastguard Worker if (cur < entry) {
796*6777b538SAndroid Build Coastguard Worker /*
797*6777b538SAndroid Build Coastguard Worker * If we traversed the end of the buffer, handle the part
798*6777b538SAndroid Build Coastguard Worker * at the start of the buffer.
799*6777b538SAndroid Build Coastguard Worker */
800*6777b538SAndroid Build Coastguard Worker memmove(&dict->table[1], dict->table,
801*6777b538SAndroid Build Coastguard Worker (char *) cur - (char *) dict->table);
802*6777b538SAndroid Build Coastguard Worker cur = end - 1;
803*6777b538SAndroid Build Coastguard Worker dict->table[0] = *cur;
804*6777b538SAndroid Build Coastguard Worker }
805*6777b538SAndroid Build Coastguard Worker
806*6777b538SAndroid Build Coastguard Worker memmove(&entry[1], entry, (char *) cur - (char *) entry);
807*6777b538SAndroid Build Coastguard Worker }
808*6777b538SAndroid Build Coastguard Worker
809*6777b538SAndroid Build Coastguard Worker /*
810*6777b538SAndroid Build Coastguard Worker * Populate entry
811*6777b538SAndroid Build Coastguard Worker */
812*6777b538SAndroid Build Coastguard Worker entry->hashValue = hashValue;
813*6777b538SAndroid Build Coastguard Worker entry->name = ret;
814*6777b538SAndroid Build Coastguard Worker
815*6777b538SAndroid Build Coastguard Worker dict->nbElems++;
816*6777b538SAndroid Build Coastguard Worker
817*6777b538SAndroid Build Coastguard Worker return(entry);
818*6777b538SAndroid Build Coastguard Worker }
819*6777b538SAndroid Build Coastguard Worker
820*6777b538SAndroid Build Coastguard Worker /**
821*6777b538SAndroid Build Coastguard Worker * xmlDictLookup:
822*6777b538SAndroid Build Coastguard Worker * @dict: dictionary
823*6777b538SAndroid Build Coastguard Worker * @name: string key
824*6777b538SAndroid Build Coastguard Worker * @len: length of the key, if -1 it is recomputed
825*6777b538SAndroid Build Coastguard Worker *
826*6777b538SAndroid Build Coastguard Worker * Lookup a string and add it to the dictionary if it wasn't found.
827*6777b538SAndroid Build Coastguard Worker *
828*6777b538SAndroid Build Coastguard Worker * Returns the interned copy of the string or NULL if a memory allocation
829*6777b538SAndroid Build Coastguard Worker * failed.
830*6777b538SAndroid Build Coastguard Worker */
831*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlDictLookup(xmlDictPtr dict,const xmlChar * name,int len)832*6777b538SAndroid Build Coastguard Worker xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
833*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *entry;
834*6777b538SAndroid Build Coastguard Worker
835*6777b538SAndroid Build Coastguard Worker entry = xmlDictLookupInternal(dict, NULL, name, len, 1);
836*6777b538SAndroid Build Coastguard Worker if (entry == NULL)
837*6777b538SAndroid Build Coastguard Worker return(NULL);
838*6777b538SAndroid Build Coastguard Worker return(entry->name);
839*6777b538SAndroid Build Coastguard Worker }
840*6777b538SAndroid Build Coastguard Worker
841*6777b538SAndroid Build Coastguard Worker /**
842*6777b538SAndroid Build Coastguard Worker * xmlDictLookupHashed:
843*6777b538SAndroid Build Coastguard Worker * @dict: dictionary
844*6777b538SAndroid Build Coastguard Worker * @name: string key
845*6777b538SAndroid Build Coastguard Worker * @len: length of the key, if -1 it is recomputed
846*6777b538SAndroid Build Coastguard Worker *
847*6777b538SAndroid Build Coastguard Worker * Lookup a dictionary entry and add the string to the dictionary if
848*6777b538SAndroid Build Coastguard Worker * it wasn't found.
849*6777b538SAndroid Build Coastguard Worker *
850*6777b538SAndroid Build Coastguard Worker * Returns the dictionary entry.
851*6777b538SAndroid Build Coastguard Worker */
852*6777b538SAndroid Build Coastguard Worker xmlHashedString
xmlDictLookupHashed(xmlDictPtr dict,const xmlChar * name,int len)853*6777b538SAndroid Build Coastguard Worker xmlDictLookupHashed(xmlDictPtr dict, const xmlChar *name, int len) {
854*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *entry;
855*6777b538SAndroid Build Coastguard Worker xmlHashedString ret;
856*6777b538SAndroid Build Coastguard Worker
857*6777b538SAndroid Build Coastguard Worker entry = xmlDictLookupInternal(dict, NULL, name, len, 1);
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker if (entry == NULL) {
860*6777b538SAndroid Build Coastguard Worker ret.name = NULL;
861*6777b538SAndroid Build Coastguard Worker ret.hashValue = 0;
862*6777b538SAndroid Build Coastguard Worker } else {
863*6777b538SAndroid Build Coastguard Worker ret = *entry;
864*6777b538SAndroid Build Coastguard Worker }
865*6777b538SAndroid Build Coastguard Worker
866*6777b538SAndroid Build Coastguard Worker return(ret);
867*6777b538SAndroid Build Coastguard Worker }
868*6777b538SAndroid Build Coastguard Worker
869*6777b538SAndroid Build Coastguard Worker /**
870*6777b538SAndroid Build Coastguard Worker * xmlDictExists:
871*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
872*6777b538SAndroid Build Coastguard Worker * @name: the name of the userdata
873*6777b538SAndroid Build Coastguard Worker * @len: the length of the name, if -1 it is recomputed
874*6777b538SAndroid Build Coastguard Worker *
875*6777b538SAndroid Build Coastguard Worker * Check if a string exists in the dictionary.
876*6777b538SAndroid Build Coastguard Worker *
877*6777b538SAndroid Build Coastguard Worker * Returns the internal copy of the name or NULL if not found.
878*6777b538SAndroid Build Coastguard Worker */
879*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlDictExists(xmlDictPtr dict,const xmlChar * name,int len)880*6777b538SAndroid Build Coastguard Worker xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
881*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *entry;
882*6777b538SAndroid Build Coastguard Worker
883*6777b538SAndroid Build Coastguard Worker entry = xmlDictLookupInternal(dict, NULL, name, len, 0);
884*6777b538SAndroid Build Coastguard Worker if (entry == NULL)
885*6777b538SAndroid Build Coastguard Worker return(NULL);
886*6777b538SAndroid Build Coastguard Worker return(entry->name);
887*6777b538SAndroid Build Coastguard Worker }
888*6777b538SAndroid Build Coastguard Worker
889*6777b538SAndroid Build Coastguard Worker /**
890*6777b538SAndroid Build Coastguard Worker * xmlDictQLookup:
891*6777b538SAndroid Build Coastguard Worker * @dict: the dictionary
892*6777b538SAndroid Build Coastguard Worker * @prefix: the prefix
893*6777b538SAndroid Build Coastguard Worker * @name: the name
894*6777b538SAndroid Build Coastguard Worker *
895*6777b538SAndroid Build Coastguard Worker * Lookup the QName @prefix:@name and add it to the dictionary if
896*6777b538SAndroid Build Coastguard Worker * it wasn't found.
897*6777b538SAndroid Build Coastguard Worker *
898*6777b538SAndroid Build Coastguard Worker * Returns the interned copy of the string or NULL if a memory allocation
899*6777b538SAndroid Build Coastguard Worker * failed.
900*6777b538SAndroid Build Coastguard Worker */
901*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlDictQLookup(xmlDictPtr dict,const xmlChar * prefix,const xmlChar * name)902*6777b538SAndroid Build Coastguard Worker xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
903*6777b538SAndroid Build Coastguard Worker const xmlDictEntry *entry;
904*6777b538SAndroid Build Coastguard Worker
905*6777b538SAndroid Build Coastguard Worker entry = xmlDictLookupInternal(dict, prefix, name, -1, 1);
906*6777b538SAndroid Build Coastguard Worker if (entry == NULL)
907*6777b538SAndroid Build Coastguard Worker return(NULL);
908*6777b538SAndroid Build Coastguard Worker return(entry->name);
909*6777b538SAndroid Build Coastguard Worker }
910*6777b538SAndroid Build Coastguard Worker
911*6777b538SAndroid Build Coastguard Worker /*
912*6777b538SAndroid Build Coastguard Worker * Pseudo-random generator
913*6777b538SAndroid Build Coastguard Worker */
914*6777b538SAndroid Build Coastguard Worker
915*6777b538SAndroid Build Coastguard Worker static xmlMutex xmlRngMutex;
916*6777b538SAndroid Build Coastguard Worker
917*6777b538SAndroid Build Coastguard Worker static unsigned globalRngState[2];
918*6777b538SAndroid Build Coastguard Worker
919*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
920*6777b538SAndroid Build Coastguard Worker void
xmlInitRandom(void)921*6777b538SAndroid Build Coastguard Worker xmlInitRandom(void) {
922*6777b538SAndroid Build Coastguard Worker xmlInitMutex(&xmlRngMutex);
923*6777b538SAndroid Build Coastguard Worker
924*6777b538SAndroid Build Coastguard Worker {
925*6777b538SAndroid Build Coastguard Worker int var;
926*6777b538SAndroid Build Coastguard Worker
927*6777b538SAndroid Build Coastguard Worker globalRngState[0] =
928*6777b538SAndroid Build Coastguard Worker (unsigned) time(NULL) ^
929*6777b538SAndroid Build Coastguard Worker HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8);
930*6777b538SAndroid Build Coastguard Worker globalRngState[1] =
931*6777b538SAndroid Build Coastguard Worker HASH_ROL((unsigned) ((size_t) &xmlRngMutex & 0xFFFFFFFF), 16) ^
932*6777b538SAndroid Build Coastguard Worker HASH_ROL((unsigned) ((size_t) &var & 0xFFFFFFFF), 24);
933*6777b538SAndroid Build Coastguard Worker }
934*6777b538SAndroid Build Coastguard Worker }
935*6777b538SAndroid Build Coastguard Worker
936*6777b538SAndroid Build Coastguard Worker void
xmlCleanupRandom(void)937*6777b538SAndroid Build Coastguard Worker xmlCleanupRandom(void) {
938*6777b538SAndroid Build Coastguard Worker xmlCleanupMutex(&xmlRngMutex);
939*6777b538SAndroid Build Coastguard Worker }
940*6777b538SAndroid Build Coastguard Worker
941*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
942*6777b538SAndroid Build Coastguard Worker static unsigned
xoroshiro64ss(unsigned * s)943*6777b538SAndroid Build Coastguard Worker xoroshiro64ss(unsigned *s) {
944*6777b538SAndroid Build Coastguard Worker unsigned s0 = s[0];
945*6777b538SAndroid Build Coastguard Worker unsigned s1 = s[1];
946*6777b538SAndroid Build Coastguard Worker unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5;
947*6777b538SAndroid Build Coastguard Worker
948*6777b538SAndroid Build Coastguard Worker s1 ^= s0;
949*6777b538SAndroid Build Coastguard Worker s[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9);
950*6777b538SAndroid Build Coastguard Worker s[1] = HASH_ROL(s1, 13);
951*6777b538SAndroid Build Coastguard Worker
952*6777b538SAndroid Build Coastguard Worker return(result & 0xFFFFFFFF);
953*6777b538SAndroid Build Coastguard Worker }
954*6777b538SAndroid Build Coastguard Worker
955*6777b538SAndroid Build Coastguard Worker unsigned
xmlGlobalRandom(void)956*6777b538SAndroid Build Coastguard Worker xmlGlobalRandom(void) {
957*6777b538SAndroid Build Coastguard Worker unsigned ret;
958*6777b538SAndroid Build Coastguard Worker
959*6777b538SAndroid Build Coastguard Worker xmlMutexLock(&xmlRngMutex);
960*6777b538SAndroid Build Coastguard Worker ret = xoroshiro64ss(globalRngState);
961*6777b538SAndroid Build Coastguard Worker xmlMutexUnlock(&xmlRngMutex);
962*6777b538SAndroid Build Coastguard Worker
963*6777b538SAndroid Build Coastguard Worker return(ret);
964*6777b538SAndroid Build Coastguard Worker }
965*6777b538SAndroid Build Coastguard Worker
966*6777b538SAndroid Build Coastguard Worker unsigned
xmlRandom(void)967*6777b538SAndroid Build Coastguard Worker xmlRandom(void) {
968*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_THREAD_ENABLED
969*6777b538SAndroid Build Coastguard Worker return(xoroshiro64ss(xmlGetLocalRngState()));
970*6777b538SAndroid Build Coastguard Worker #else
971*6777b538SAndroid Build Coastguard Worker return(xmlGlobalRandom());
972*6777b538SAndroid Build Coastguard Worker #endif
973*6777b538SAndroid Build Coastguard Worker }
974*6777b538SAndroid Build Coastguard Worker
975