xref: /aosp_15_r20/external/cronet/third_party/libxml/src/dict.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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