xref: /aosp_15_r20/external/cronet/third_party/libxml/src/xmlstring.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker  * string.c : an XML string utilities module
3*6777b538SAndroid Build Coastguard Worker  *
4*6777b538SAndroid Build Coastguard Worker  * This module provides various utility functions for manipulating
5*6777b538SAndroid Build Coastguard Worker  * the xmlChar* type. All functions named xmlStr* have been moved here
6*6777b538SAndroid Build Coastguard Worker  * from the parser.c file (their original home).
7*6777b538SAndroid Build Coastguard Worker  *
8*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
9*6777b538SAndroid Build Coastguard Worker  *
10*6777b538SAndroid Build Coastguard Worker  * UTF8 string routines from:
11*6777b538SAndroid Build Coastguard Worker  * William Brack <[email protected]>
12*6777b538SAndroid Build Coastguard Worker  *
13*6777b538SAndroid Build Coastguard Worker  * [email protected]
14*6777b538SAndroid Build Coastguard Worker  */
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
17*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
20*6777b538SAndroid Build Coastguard Worker #include <string.h>
21*6777b538SAndroid Build Coastguard Worker #include <limits.h>
22*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
23*6777b538SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
24*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlstring.h>
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker #include "private/parser.h"
27*6777b538SAndroid Build Coastguard Worker #include "private/string.h"
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker #ifndef va_copy
30*6777b538SAndroid Build Coastguard Worker   #ifdef __va_copy
31*6777b538SAndroid Build Coastguard Worker     #define va_copy(dest, src) __va_copy(dest, src)
32*6777b538SAndroid Build Coastguard Worker   #else
33*6777b538SAndroid Build Coastguard Worker     #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
34*6777b538SAndroid Build Coastguard Worker   #endif
35*6777b538SAndroid Build Coastguard Worker #endif
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker /************************************************************************
38*6777b538SAndroid Build Coastguard Worker  *                                                                      *
39*6777b538SAndroid Build Coastguard Worker  *                Commodity functions to handle xmlChars                *
40*6777b538SAndroid Build Coastguard Worker  *                                                                      *
41*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker /**
44*6777b538SAndroid Build Coastguard Worker  * xmlStrndup:
45*6777b538SAndroid Build Coastguard Worker  * @cur:  the input xmlChar *
46*6777b538SAndroid Build Coastguard Worker  * @len:  the len of @cur
47*6777b538SAndroid Build Coastguard Worker  *
48*6777b538SAndroid Build Coastguard Worker  * a strndup for array of xmlChar's
49*6777b538SAndroid Build Coastguard Worker  *
50*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * or NULL
51*6777b538SAndroid Build Coastguard Worker  */
52*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrndup(const xmlChar * cur,int len)53*6777b538SAndroid Build Coastguard Worker xmlStrndup(const xmlChar *cur, int len) {
54*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker     if ((cur == NULL) || (len < 0)) return(NULL);
57*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMallocAtomic((size_t) len + 1);
58*6777b538SAndroid Build Coastguard Worker     if (ret == NULL) {
59*6777b538SAndroid Build Coastguard Worker         return(NULL);
60*6777b538SAndroid Build Coastguard Worker     }
61*6777b538SAndroid Build Coastguard Worker     memcpy(ret, cur, len);
62*6777b538SAndroid Build Coastguard Worker     ret[len] = 0;
63*6777b538SAndroid Build Coastguard Worker     return(ret);
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker /**
67*6777b538SAndroid Build Coastguard Worker  * xmlStrdup:
68*6777b538SAndroid Build Coastguard Worker  * @cur:  the input xmlChar *
69*6777b538SAndroid Build Coastguard Worker  *
70*6777b538SAndroid Build Coastguard Worker  * a strdup for array of xmlChar's. Since they are supposed to be
71*6777b538SAndroid Build Coastguard Worker  * encoded in UTF-8 or an encoding with 8bit based chars, we assume
72*6777b538SAndroid Build Coastguard Worker  * a termination mark of '0'.
73*6777b538SAndroid Build Coastguard Worker  *
74*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * or NULL
75*6777b538SAndroid Build Coastguard Worker  */
76*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrdup(const xmlChar * cur)77*6777b538SAndroid Build Coastguard Worker xmlStrdup(const xmlChar *cur) {
78*6777b538SAndroid Build Coastguard Worker     const xmlChar *p = cur;
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker     if (cur == NULL) return(NULL);
81*6777b538SAndroid Build Coastguard Worker     while (*p != 0) p++; /* non input consuming */
82*6777b538SAndroid Build Coastguard Worker     return(xmlStrndup(cur, p - cur));
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker /**
86*6777b538SAndroid Build Coastguard Worker  * xmlCharStrndup:
87*6777b538SAndroid Build Coastguard Worker  * @cur:  the input char *
88*6777b538SAndroid Build Coastguard Worker  * @len:  the len of @cur
89*6777b538SAndroid Build Coastguard Worker  *
90*6777b538SAndroid Build Coastguard Worker  * a strndup for char's to xmlChar's
91*6777b538SAndroid Build Coastguard Worker  *
92*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * or NULL
93*6777b538SAndroid Build Coastguard Worker  */
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlCharStrndup(const char * cur,int len)96*6777b538SAndroid Build Coastguard Worker xmlCharStrndup(const char *cur, int len) {
97*6777b538SAndroid Build Coastguard Worker     int i;
98*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker     if ((cur == NULL) || (len < 0)) return(NULL);
101*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMallocAtomic((size_t) len + 1);
102*6777b538SAndroid Build Coastguard Worker     if (ret == NULL) {
103*6777b538SAndroid Build Coastguard Worker         return(NULL);
104*6777b538SAndroid Build Coastguard Worker     }
105*6777b538SAndroid Build Coastguard Worker     for (i = 0;i < len;i++) {
106*6777b538SAndroid Build Coastguard Worker         /* Explicit sign change */
107*6777b538SAndroid Build Coastguard Worker         ret[i] = (xmlChar) cur[i];
108*6777b538SAndroid Build Coastguard Worker         if (ret[i] == 0) return(ret);
109*6777b538SAndroid Build Coastguard Worker     }
110*6777b538SAndroid Build Coastguard Worker     ret[len] = 0;
111*6777b538SAndroid Build Coastguard Worker     return(ret);
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker /**
115*6777b538SAndroid Build Coastguard Worker  * xmlCharStrdup:
116*6777b538SAndroid Build Coastguard Worker  * @cur:  the input char *
117*6777b538SAndroid Build Coastguard Worker  *
118*6777b538SAndroid Build Coastguard Worker  * a strdup for char's to xmlChar's
119*6777b538SAndroid Build Coastguard Worker  *
120*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * or NULL
121*6777b538SAndroid Build Coastguard Worker  */
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlCharStrdup(const char * cur)124*6777b538SAndroid Build Coastguard Worker xmlCharStrdup(const char *cur) {
125*6777b538SAndroid Build Coastguard Worker     const char *p = cur;
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker     if (cur == NULL) return(NULL);
128*6777b538SAndroid Build Coastguard Worker     while (*p != '\0') p++; /* non input consuming */
129*6777b538SAndroid Build Coastguard Worker     return(xmlCharStrndup(cur, p - cur));
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker /**
133*6777b538SAndroid Build Coastguard Worker  * xmlStrcmp:
134*6777b538SAndroid Build Coastguard Worker  * @str1:  the first xmlChar *
135*6777b538SAndroid Build Coastguard Worker  * @str2:  the second xmlChar *
136*6777b538SAndroid Build Coastguard Worker  *
137*6777b538SAndroid Build Coastguard Worker  * a strcmp for xmlChar's
138*6777b538SAndroid Build Coastguard Worker  *
139*6777b538SAndroid Build Coastguard Worker  * Returns the integer result of the comparison
140*6777b538SAndroid Build Coastguard Worker  */
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker int
xmlStrcmp(const xmlChar * str1,const xmlChar * str2)143*6777b538SAndroid Build Coastguard Worker xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
144*6777b538SAndroid Build Coastguard Worker     if (str1 == str2) return(0);
145*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL) return(-1);
146*6777b538SAndroid Build Coastguard Worker     if (str2 == NULL) return(1);
147*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
148*6777b538SAndroid Build Coastguard Worker     return(strcmp((const char *)str1, (const char *)str2));
149*6777b538SAndroid Build Coastguard Worker #else
150*6777b538SAndroid Build Coastguard Worker     do {
151*6777b538SAndroid Build Coastguard Worker         int tmp = *str1++ - *str2;
152*6777b538SAndroid Build Coastguard Worker         if (tmp != 0) return(tmp);
153*6777b538SAndroid Build Coastguard Worker     } while (*str2++ != 0);
154*6777b538SAndroid Build Coastguard Worker     return 0;
155*6777b538SAndroid Build Coastguard Worker #endif
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker /**
159*6777b538SAndroid Build Coastguard Worker  * xmlStrEqual:
160*6777b538SAndroid Build Coastguard Worker  * @str1:  the first xmlChar *
161*6777b538SAndroid Build Coastguard Worker  * @str2:  the second xmlChar *
162*6777b538SAndroid Build Coastguard Worker  *
163*6777b538SAndroid Build Coastguard Worker  * Check if both strings are equal of have same content.
164*6777b538SAndroid Build Coastguard Worker  * Should be a bit more readable and faster than xmlStrcmp()
165*6777b538SAndroid Build Coastguard Worker  *
166*6777b538SAndroid Build Coastguard Worker  * Returns 1 if they are equal, 0 if they are different
167*6777b538SAndroid Build Coastguard Worker  */
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker int
xmlStrEqual(const xmlChar * str1,const xmlChar * str2)170*6777b538SAndroid Build Coastguard Worker xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
171*6777b538SAndroid Build Coastguard Worker     if (str1 == str2) return(1);
172*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL) return(0);
173*6777b538SAndroid Build Coastguard Worker     if (str2 == NULL) return(0);
174*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
175*6777b538SAndroid Build Coastguard Worker     return(strcmp((const char *)str1, (const char *)str2) == 0);
176*6777b538SAndroid Build Coastguard Worker #else
177*6777b538SAndroid Build Coastguard Worker     do {
178*6777b538SAndroid Build Coastguard Worker         if (*str1++ != *str2) return(0);
179*6777b538SAndroid Build Coastguard Worker     } while (*str2++);
180*6777b538SAndroid Build Coastguard Worker     return(1);
181*6777b538SAndroid Build Coastguard Worker #endif
182*6777b538SAndroid Build Coastguard Worker }
183*6777b538SAndroid Build Coastguard Worker 
184*6777b538SAndroid Build Coastguard Worker /**
185*6777b538SAndroid Build Coastguard Worker  * xmlStrQEqual:
186*6777b538SAndroid Build Coastguard Worker  * @pref:  the prefix of the QName
187*6777b538SAndroid Build Coastguard Worker  * @name:  the localname of the QName
188*6777b538SAndroid Build Coastguard Worker  * @str:  the second xmlChar *
189*6777b538SAndroid Build Coastguard Worker  *
190*6777b538SAndroid Build Coastguard Worker  * Check if a QName is Equal to a given string
191*6777b538SAndroid Build Coastguard Worker  *
192*6777b538SAndroid Build Coastguard Worker  * Returns 1 if they are equal, 0 if they are different
193*6777b538SAndroid Build Coastguard Worker  */
194*6777b538SAndroid Build Coastguard Worker 
195*6777b538SAndroid Build Coastguard Worker int
xmlStrQEqual(const xmlChar * pref,const xmlChar * name,const xmlChar * str)196*6777b538SAndroid Build Coastguard Worker xmlStrQEqual(const xmlChar *pref, const xmlChar *name, const xmlChar *str) {
197*6777b538SAndroid Build Coastguard Worker     if (pref == NULL) return(xmlStrEqual(name, str));
198*6777b538SAndroid Build Coastguard Worker     if (name == NULL) return(0);
199*6777b538SAndroid Build Coastguard Worker     if (str == NULL) return(0);
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker     do {
202*6777b538SAndroid Build Coastguard Worker         if (*pref++ != *str) return(0);
203*6777b538SAndroid Build Coastguard Worker     } while ((*str++) && (*pref));
204*6777b538SAndroid Build Coastguard Worker     if (*str++ != ':') return(0);
205*6777b538SAndroid Build Coastguard Worker     do {
206*6777b538SAndroid Build Coastguard Worker         if (*name++ != *str) return(0);
207*6777b538SAndroid Build Coastguard Worker     } while (*str++);
208*6777b538SAndroid Build Coastguard Worker     return(1);
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker /**
212*6777b538SAndroid Build Coastguard Worker  * xmlStrncmp:
213*6777b538SAndroid Build Coastguard Worker  * @str1:  the first xmlChar *
214*6777b538SAndroid Build Coastguard Worker  * @str2:  the second xmlChar *
215*6777b538SAndroid Build Coastguard Worker  * @len:  the max comparison length
216*6777b538SAndroid Build Coastguard Worker  *
217*6777b538SAndroid Build Coastguard Worker  * a strncmp for xmlChar's
218*6777b538SAndroid Build Coastguard Worker  *
219*6777b538SAndroid Build Coastguard Worker  * Returns the integer result of the comparison
220*6777b538SAndroid Build Coastguard Worker  */
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker int
xmlStrncmp(const xmlChar * str1,const xmlChar * str2,int len)223*6777b538SAndroid Build Coastguard Worker xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
224*6777b538SAndroid Build Coastguard Worker     if (len <= 0) return(0);
225*6777b538SAndroid Build Coastguard Worker     if (str1 == str2) return(0);
226*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL) return(-1);
227*6777b538SAndroid Build Coastguard Worker     if (str2 == NULL) return(1);
228*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
229*6777b538SAndroid Build Coastguard Worker     return(strncmp((const char *)str1, (const char *)str2, len));
230*6777b538SAndroid Build Coastguard Worker #else
231*6777b538SAndroid Build Coastguard Worker     do {
232*6777b538SAndroid Build Coastguard Worker         int tmp = *str1++ - *str2;
233*6777b538SAndroid Build Coastguard Worker         if (tmp != 0 || --len == 0) return(tmp);
234*6777b538SAndroid Build Coastguard Worker     } while (*str2++ != 0);
235*6777b538SAndroid Build Coastguard Worker     return 0;
236*6777b538SAndroid Build Coastguard Worker #endif
237*6777b538SAndroid Build Coastguard Worker }
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker static const xmlChar casemap[256] = {
240*6777b538SAndroid Build Coastguard Worker     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
241*6777b538SAndroid Build Coastguard Worker     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
242*6777b538SAndroid Build Coastguard Worker     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
243*6777b538SAndroid Build Coastguard Worker     0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
244*6777b538SAndroid Build Coastguard Worker     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
245*6777b538SAndroid Build Coastguard Worker     0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
246*6777b538SAndroid Build Coastguard Worker     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
247*6777b538SAndroid Build Coastguard Worker     0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
248*6777b538SAndroid Build Coastguard Worker     0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
249*6777b538SAndroid Build Coastguard Worker     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
250*6777b538SAndroid Build Coastguard Worker     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
251*6777b538SAndroid Build Coastguard Worker     0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
252*6777b538SAndroid Build Coastguard Worker     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
253*6777b538SAndroid Build Coastguard Worker     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
254*6777b538SAndroid Build Coastguard Worker     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
255*6777b538SAndroid Build Coastguard Worker     0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
256*6777b538SAndroid Build Coastguard Worker     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
257*6777b538SAndroid Build Coastguard Worker     0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
258*6777b538SAndroid Build Coastguard Worker     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
259*6777b538SAndroid Build Coastguard Worker     0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
260*6777b538SAndroid Build Coastguard Worker     0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
261*6777b538SAndroid Build Coastguard Worker     0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
262*6777b538SAndroid Build Coastguard Worker     0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
263*6777b538SAndroid Build Coastguard Worker     0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
264*6777b538SAndroid Build Coastguard Worker     0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
265*6777b538SAndroid Build Coastguard Worker     0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
266*6777b538SAndroid Build Coastguard Worker     0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
267*6777b538SAndroid Build Coastguard Worker     0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
268*6777b538SAndroid Build Coastguard Worker     0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
269*6777b538SAndroid Build Coastguard Worker     0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
270*6777b538SAndroid Build Coastguard Worker     0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
271*6777b538SAndroid Build Coastguard Worker     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
272*6777b538SAndroid Build Coastguard Worker };
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker /**
275*6777b538SAndroid Build Coastguard Worker  * xmlStrcasecmp:
276*6777b538SAndroid Build Coastguard Worker  * @str1:  the first xmlChar *
277*6777b538SAndroid Build Coastguard Worker  * @str2:  the second xmlChar *
278*6777b538SAndroid Build Coastguard Worker  *
279*6777b538SAndroid Build Coastguard Worker  * a strcasecmp for xmlChar's
280*6777b538SAndroid Build Coastguard Worker  *
281*6777b538SAndroid Build Coastguard Worker  * Returns the integer result of the comparison
282*6777b538SAndroid Build Coastguard Worker  */
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker int
xmlStrcasecmp(const xmlChar * str1,const xmlChar * str2)285*6777b538SAndroid Build Coastguard Worker xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) {
286*6777b538SAndroid Build Coastguard Worker     register int tmp;
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker     if (str1 == str2) return(0);
289*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL) return(-1);
290*6777b538SAndroid Build Coastguard Worker     if (str2 == NULL) return(1);
291*6777b538SAndroid Build Coastguard Worker     do {
292*6777b538SAndroid Build Coastguard Worker         tmp = casemap[*str1++] - casemap[*str2];
293*6777b538SAndroid Build Coastguard Worker         if (tmp != 0) return(tmp);
294*6777b538SAndroid Build Coastguard Worker     } while (*str2++ != 0);
295*6777b538SAndroid Build Coastguard Worker     return 0;
296*6777b538SAndroid Build Coastguard Worker }
297*6777b538SAndroid Build Coastguard Worker 
298*6777b538SAndroid Build Coastguard Worker /**
299*6777b538SAndroid Build Coastguard Worker  * xmlStrncasecmp:
300*6777b538SAndroid Build Coastguard Worker  * @str1:  the first xmlChar *
301*6777b538SAndroid Build Coastguard Worker  * @str2:  the second xmlChar *
302*6777b538SAndroid Build Coastguard Worker  * @len:  the max comparison length
303*6777b538SAndroid Build Coastguard Worker  *
304*6777b538SAndroid Build Coastguard Worker  * a strncasecmp for xmlChar's
305*6777b538SAndroid Build Coastguard Worker  *
306*6777b538SAndroid Build Coastguard Worker  * Returns the integer result of the comparison
307*6777b538SAndroid Build Coastguard Worker  */
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker int
xmlStrncasecmp(const xmlChar * str1,const xmlChar * str2,int len)310*6777b538SAndroid Build Coastguard Worker xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) {
311*6777b538SAndroid Build Coastguard Worker     register int tmp;
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker     if (len <= 0) return(0);
314*6777b538SAndroid Build Coastguard Worker     if (str1 == str2) return(0);
315*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL) return(-1);
316*6777b538SAndroid Build Coastguard Worker     if (str2 == NULL) return(1);
317*6777b538SAndroid Build Coastguard Worker     do {
318*6777b538SAndroid Build Coastguard Worker         tmp = casemap[*str1++] - casemap[*str2];
319*6777b538SAndroid Build Coastguard Worker         if (tmp != 0 || --len == 0) return(tmp);
320*6777b538SAndroid Build Coastguard Worker     } while (*str2++ != 0);
321*6777b538SAndroid Build Coastguard Worker     return 0;
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker /**
325*6777b538SAndroid Build Coastguard Worker  * xmlStrchr:
326*6777b538SAndroid Build Coastguard Worker  * @str:  the xmlChar * array
327*6777b538SAndroid Build Coastguard Worker  * @val:  the xmlChar to search
328*6777b538SAndroid Build Coastguard Worker  *
329*6777b538SAndroid Build Coastguard Worker  * a strchr for xmlChar's
330*6777b538SAndroid Build Coastguard Worker  *
331*6777b538SAndroid Build Coastguard Worker  * Returns the xmlChar * for the first occurrence or NULL.
332*6777b538SAndroid Build Coastguard Worker  */
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlStrchr(const xmlChar * str,xmlChar val)335*6777b538SAndroid Build Coastguard Worker xmlStrchr(const xmlChar *str, xmlChar val) {
336*6777b538SAndroid Build Coastguard Worker     if (str == NULL) return(NULL);
337*6777b538SAndroid Build Coastguard Worker     while (*str != 0) { /* non input consuming */
338*6777b538SAndroid Build Coastguard Worker         if (*str == val) return((xmlChar *) str);
339*6777b538SAndroid Build Coastguard Worker         str++;
340*6777b538SAndroid Build Coastguard Worker     }
341*6777b538SAndroid Build Coastguard Worker     return(NULL);
342*6777b538SAndroid Build Coastguard Worker }
343*6777b538SAndroid Build Coastguard Worker 
344*6777b538SAndroid Build Coastguard Worker /**
345*6777b538SAndroid Build Coastguard Worker  * xmlStrstr:
346*6777b538SAndroid Build Coastguard Worker  * @str:  the xmlChar * array (haystack)
347*6777b538SAndroid Build Coastguard Worker  * @val:  the xmlChar to search (needle)
348*6777b538SAndroid Build Coastguard Worker  *
349*6777b538SAndroid Build Coastguard Worker  * a strstr for xmlChar's
350*6777b538SAndroid Build Coastguard Worker  *
351*6777b538SAndroid Build Coastguard Worker  * Returns the xmlChar * for the first occurrence or NULL.
352*6777b538SAndroid Build Coastguard Worker  */
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlStrstr(const xmlChar * str,const xmlChar * val)355*6777b538SAndroid Build Coastguard Worker xmlStrstr(const xmlChar *str, const xmlChar *val) {
356*6777b538SAndroid Build Coastguard Worker     int n;
357*6777b538SAndroid Build Coastguard Worker 
358*6777b538SAndroid Build Coastguard Worker     if (str == NULL) return(NULL);
359*6777b538SAndroid Build Coastguard Worker     if (val == NULL) return(NULL);
360*6777b538SAndroid Build Coastguard Worker     n = xmlStrlen(val);
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker     if (n == 0) return(str);
363*6777b538SAndroid Build Coastguard Worker     while (*str != 0) { /* non input consuming */
364*6777b538SAndroid Build Coastguard Worker         if (*str == *val) {
365*6777b538SAndroid Build Coastguard Worker             if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
366*6777b538SAndroid Build Coastguard Worker         }
367*6777b538SAndroid Build Coastguard Worker         str++;
368*6777b538SAndroid Build Coastguard Worker     }
369*6777b538SAndroid Build Coastguard Worker     return(NULL);
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker 
372*6777b538SAndroid Build Coastguard Worker /**
373*6777b538SAndroid Build Coastguard Worker  * xmlStrcasestr:
374*6777b538SAndroid Build Coastguard Worker  * @str:  the xmlChar * array (haystack)
375*6777b538SAndroid Build Coastguard Worker  * @val:  the xmlChar to search (needle)
376*6777b538SAndroid Build Coastguard Worker  *
377*6777b538SAndroid Build Coastguard Worker  * a case-ignoring strstr for xmlChar's
378*6777b538SAndroid Build Coastguard Worker  *
379*6777b538SAndroid Build Coastguard Worker  * Returns the xmlChar * for the first occurrence or NULL.
380*6777b538SAndroid Build Coastguard Worker  */
381*6777b538SAndroid Build Coastguard Worker 
382*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlStrcasestr(const xmlChar * str,const xmlChar * val)383*6777b538SAndroid Build Coastguard Worker xmlStrcasestr(const xmlChar *str, const xmlChar *val) {
384*6777b538SAndroid Build Coastguard Worker     int n;
385*6777b538SAndroid Build Coastguard Worker 
386*6777b538SAndroid Build Coastguard Worker     if (str == NULL) return(NULL);
387*6777b538SAndroid Build Coastguard Worker     if (val == NULL) return(NULL);
388*6777b538SAndroid Build Coastguard Worker     n = xmlStrlen(val);
389*6777b538SAndroid Build Coastguard Worker 
390*6777b538SAndroid Build Coastguard Worker     if (n == 0) return(str);
391*6777b538SAndroid Build Coastguard Worker     while (*str != 0) { /* non input consuming */
392*6777b538SAndroid Build Coastguard Worker         if (casemap[*str] == casemap[*val])
393*6777b538SAndroid Build Coastguard Worker             if (!xmlStrncasecmp(str, val, n)) return(str);
394*6777b538SAndroid Build Coastguard Worker         str++;
395*6777b538SAndroid Build Coastguard Worker     }
396*6777b538SAndroid Build Coastguard Worker     return(NULL);
397*6777b538SAndroid Build Coastguard Worker }
398*6777b538SAndroid Build Coastguard Worker 
399*6777b538SAndroid Build Coastguard Worker /**
400*6777b538SAndroid Build Coastguard Worker  * xmlStrsub:
401*6777b538SAndroid Build Coastguard Worker  * @str:  the xmlChar * array (haystack)
402*6777b538SAndroid Build Coastguard Worker  * @start:  the index of the first char (zero based)
403*6777b538SAndroid Build Coastguard Worker  * @len:  the length of the substring
404*6777b538SAndroid Build Coastguard Worker  *
405*6777b538SAndroid Build Coastguard Worker  * Extract a substring of a given string
406*6777b538SAndroid Build Coastguard Worker  *
407*6777b538SAndroid Build Coastguard Worker  * Returns the xmlChar * for the first occurrence or NULL.
408*6777b538SAndroid Build Coastguard Worker  */
409*6777b538SAndroid Build Coastguard Worker 
410*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrsub(const xmlChar * str,int start,int len)411*6777b538SAndroid Build Coastguard Worker xmlStrsub(const xmlChar *str, int start, int len) {
412*6777b538SAndroid Build Coastguard Worker     int i;
413*6777b538SAndroid Build Coastguard Worker 
414*6777b538SAndroid Build Coastguard Worker     if (str == NULL) return(NULL);
415*6777b538SAndroid Build Coastguard Worker     if (start < 0) return(NULL);
416*6777b538SAndroid Build Coastguard Worker     if (len < 0) return(NULL);
417*6777b538SAndroid Build Coastguard Worker 
418*6777b538SAndroid Build Coastguard Worker     for (i = 0;i < start;i++) {
419*6777b538SAndroid Build Coastguard Worker         if (*str == 0) return(NULL);
420*6777b538SAndroid Build Coastguard Worker         str++;
421*6777b538SAndroid Build Coastguard Worker     }
422*6777b538SAndroid Build Coastguard Worker     if (*str == 0) return(NULL);
423*6777b538SAndroid Build Coastguard Worker     return(xmlStrndup(str, len));
424*6777b538SAndroid Build Coastguard Worker }
425*6777b538SAndroid Build Coastguard Worker 
426*6777b538SAndroid Build Coastguard Worker /**
427*6777b538SAndroid Build Coastguard Worker  * xmlStrlen:
428*6777b538SAndroid Build Coastguard Worker  * @str:  the xmlChar * array
429*6777b538SAndroid Build Coastguard Worker  *
430*6777b538SAndroid Build Coastguard Worker  * length of a xmlChar's string
431*6777b538SAndroid Build Coastguard Worker  *
432*6777b538SAndroid Build Coastguard Worker  * Returns the number of xmlChar contained in the ARRAY.
433*6777b538SAndroid Build Coastguard Worker  */
434*6777b538SAndroid Build Coastguard Worker 
435*6777b538SAndroid Build Coastguard Worker int
xmlStrlen(const xmlChar * str)436*6777b538SAndroid Build Coastguard Worker xmlStrlen(const xmlChar *str) {
437*6777b538SAndroid Build Coastguard Worker     size_t len = str ? strlen((const char *)str) : 0;
438*6777b538SAndroid Build Coastguard Worker     return(len > INT_MAX ? 0 : len);
439*6777b538SAndroid Build Coastguard Worker }
440*6777b538SAndroid Build Coastguard Worker 
441*6777b538SAndroid Build Coastguard Worker /**
442*6777b538SAndroid Build Coastguard Worker  * xmlStrncat:
443*6777b538SAndroid Build Coastguard Worker  * @cur:  the original xmlChar * array
444*6777b538SAndroid Build Coastguard Worker  * @add:  the xmlChar * array added
445*6777b538SAndroid Build Coastguard Worker  * @len:  the length of @add
446*6777b538SAndroid Build Coastguard Worker  *
447*6777b538SAndroid Build Coastguard Worker  * a strncat for array of xmlChar's, it will extend @cur with the len
448*6777b538SAndroid Build Coastguard Worker  * first bytes of @add. Note that if @len < 0 then this is an API error
449*6777b538SAndroid Build Coastguard Worker  * and NULL will be returned.
450*6777b538SAndroid Build Coastguard Worker  *
451*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar *, the original @cur is reallocated and should
452*6777b538SAndroid Build Coastguard Worker  * not be freed.
453*6777b538SAndroid Build Coastguard Worker  */
454*6777b538SAndroid Build Coastguard Worker 
455*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrncat(xmlChar * cur,const xmlChar * add,int len)456*6777b538SAndroid Build Coastguard Worker xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
457*6777b538SAndroid Build Coastguard Worker     int size;
458*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
459*6777b538SAndroid Build Coastguard Worker 
460*6777b538SAndroid Build Coastguard Worker     if ((add == NULL) || (len == 0))
461*6777b538SAndroid Build Coastguard Worker         return(cur);
462*6777b538SAndroid Build Coastguard Worker     if (len < 0)
463*6777b538SAndroid Build Coastguard Worker 	return(NULL);
464*6777b538SAndroid Build Coastguard Worker     if (cur == NULL)
465*6777b538SAndroid Build Coastguard Worker         return(xmlStrndup(add, len));
466*6777b538SAndroid Build Coastguard Worker 
467*6777b538SAndroid Build Coastguard Worker     size = xmlStrlen(cur);
468*6777b538SAndroid Build Coastguard Worker     if ((size < 0) || (size > INT_MAX - len))
469*6777b538SAndroid Build Coastguard Worker         return(NULL);
470*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlRealloc(cur, (size_t) size + len + 1);
471*6777b538SAndroid Build Coastguard Worker     if (ret == NULL) {
472*6777b538SAndroid Build Coastguard Worker         xmlFree(cur);
473*6777b538SAndroid Build Coastguard Worker         return(NULL);
474*6777b538SAndroid Build Coastguard Worker     }
475*6777b538SAndroid Build Coastguard Worker     memcpy(&ret[size], add, len);
476*6777b538SAndroid Build Coastguard Worker     ret[size + len] = 0;
477*6777b538SAndroid Build Coastguard Worker     return(ret);
478*6777b538SAndroid Build Coastguard Worker }
479*6777b538SAndroid Build Coastguard Worker 
480*6777b538SAndroid Build Coastguard Worker /**
481*6777b538SAndroid Build Coastguard Worker  * xmlStrncatNew:
482*6777b538SAndroid Build Coastguard Worker  * @str1:  first xmlChar string
483*6777b538SAndroid Build Coastguard Worker  * @str2:  second xmlChar string
484*6777b538SAndroid Build Coastguard Worker  * @len:  the len of @str2 or < 0
485*6777b538SAndroid Build Coastguard Worker  *
486*6777b538SAndroid Build Coastguard Worker  * same as xmlStrncat, but creates a new string.  The original
487*6777b538SAndroid Build Coastguard Worker  * two strings are not freed. If @len is < 0 then the length
488*6777b538SAndroid Build Coastguard Worker  * will be calculated automatically.
489*6777b538SAndroid Build Coastguard Worker  *
490*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * or NULL
491*6777b538SAndroid Build Coastguard Worker  */
492*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrncatNew(const xmlChar * str1,const xmlChar * str2,int len)493*6777b538SAndroid Build Coastguard Worker xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) {
494*6777b538SAndroid Build Coastguard Worker     int size;
495*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
496*6777b538SAndroid Build Coastguard Worker 
497*6777b538SAndroid Build Coastguard Worker     if (len < 0) {
498*6777b538SAndroid Build Coastguard Worker         len = xmlStrlen(str2);
499*6777b538SAndroid Build Coastguard Worker         if (len < 0)
500*6777b538SAndroid Build Coastguard Worker             return(NULL);
501*6777b538SAndroid Build Coastguard Worker     }
502*6777b538SAndroid Build Coastguard Worker     if ((str2 == NULL) || (len == 0))
503*6777b538SAndroid Build Coastguard Worker         return(xmlStrdup(str1));
504*6777b538SAndroid Build Coastguard Worker     if (str1 == NULL)
505*6777b538SAndroid Build Coastguard Worker         return(xmlStrndup(str2, len));
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker     size = xmlStrlen(str1);
508*6777b538SAndroid Build Coastguard Worker     if ((size < 0) || (size > INT_MAX - len))
509*6777b538SAndroid Build Coastguard Worker         return(NULL);
510*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMalloc((size_t) size + len + 1);
511*6777b538SAndroid Build Coastguard Worker     if (ret == NULL)
512*6777b538SAndroid Build Coastguard Worker         return(NULL);
513*6777b538SAndroid Build Coastguard Worker     memcpy(ret, str1, size);
514*6777b538SAndroid Build Coastguard Worker     memcpy(&ret[size], str2, len);
515*6777b538SAndroid Build Coastguard Worker     ret[size + len] = 0;
516*6777b538SAndroid Build Coastguard Worker     return(ret);
517*6777b538SAndroid Build Coastguard Worker }
518*6777b538SAndroid Build Coastguard Worker 
519*6777b538SAndroid Build Coastguard Worker /**
520*6777b538SAndroid Build Coastguard Worker  * xmlStrcat:
521*6777b538SAndroid Build Coastguard Worker  * @cur:  the original xmlChar * array
522*6777b538SAndroid Build Coastguard Worker  * @add:  the xmlChar * array added
523*6777b538SAndroid Build Coastguard Worker  *
524*6777b538SAndroid Build Coastguard Worker  * a strcat for array of xmlChar's. Since they are supposed to be
525*6777b538SAndroid Build Coastguard Worker  * encoded in UTF-8 or an encoding with 8bit based chars, we assume
526*6777b538SAndroid Build Coastguard Worker  * a termination mark of '0'.
527*6777b538SAndroid Build Coastguard Worker  *
528*6777b538SAndroid Build Coastguard Worker  * Returns a new xmlChar * containing the concatenated string. The original
529*6777b538SAndroid Build Coastguard Worker  * @cur is reallocated and should not be freed.
530*6777b538SAndroid Build Coastguard Worker  */
531*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlStrcat(xmlChar * cur,const xmlChar * add)532*6777b538SAndroid Build Coastguard Worker xmlStrcat(xmlChar *cur, const xmlChar *add) {
533*6777b538SAndroid Build Coastguard Worker     const xmlChar *p = add;
534*6777b538SAndroid Build Coastguard Worker 
535*6777b538SAndroid Build Coastguard Worker     if (add == NULL) return(cur);
536*6777b538SAndroid Build Coastguard Worker     if (cur == NULL)
537*6777b538SAndroid Build Coastguard Worker         return(xmlStrdup(add));
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker     while (*p != 0) p++; /* non input consuming */
540*6777b538SAndroid Build Coastguard Worker     return(xmlStrncat(cur, add, p - add));
541*6777b538SAndroid Build Coastguard Worker }
542*6777b538SAndroid Build Coastguard Worker 
543*6777b538SAndroid Build Coastguard Worker /**
544*6777b538SAndroid Build Coastguard Worker  * xmlStrPrintf:
545*6777b538SAndroid Build Coastguard Worker  * @buf:   the result buffer.
546*6777b538SAndroid Build Coastguard Worker  * @len:   the result buffer length.
547*6777b538SAndroid Build Coastguard Worker  * @msg:   the message with printf formatting.
548*6777b538SAndroid Build Coastguard Worker  * @...:   extra parameters for the message.
549*6777b538SAndroid Build Coastguard Worker  *
550*6777b538SAndroid Build Coastguard Worker  * Formats @msg and places result into @buf.
551*6777b538SAndroid Build Coastguard Worker  *
552*6777b538SAndroid Build Coastguard Worker  * Returns the number of characters written to @buf or -1 if an error occurs.
553*6777b538SAndroid Build Coastguard Worker  */
554*6777b538SAndroid Build Coastguard Worker int
xmlStrPrintf(xmlChar * buf,int len,const char * msg,...)555*6777b538SAndroid Build Coastguard Worker xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
556*6777b538SAndroid Build Coastguard Worker     va_list args;
557*6777b538SAndroid Build Coastguard Worker     int ret;
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker     if((buf == NULL) || (msg == NULL)) {
560*6777b538SAndroid Build Coastguard Worker         return(-1);
561*6777b538SAndroid Build Coastguard Worker     }
562*6777b538SAndroid Build Coastguard Worker 
563*6777b538SAndroid Build Coastguard Worker     va_start(args, msg);
564*6777b538SAndroid Build Coastguard Worker     ret = vsnprintf((char *) buf, len, (const char *) msg, args);
565*6777b538SAndroid Build Coastguard Worker     va_end(args);
566*6777b538SAndroid Build Coastguard Worker     buf[len - 1] = 0; /* be safe ! */
567*6777b538SAndroid Build Coastguard Worker 
568*6777b538SAndroid Build Coastguard Worker     return(ret);
569*6777b538SAndroid Build Coastguard Worker }
570*6777b538SAndroid Build Coastguard Worker 
571*6777b538SAndroid Build Coastguard Worker /**
572*6777b538SAndroid Build Coastguard Worker  * xmlStrVPrintf:
573*6777b538SAndroid Build Coastguard Worker  * @buf:   the result buffer.
574*6777b538SAndroid Build Coastguard Worker  * @len:   the result buffer length.
575*6777b538SAndroid Build Coastguard Worker  * @msg:   the message with printf formatting.
576*6777b538SAndroid Build Coastguard Worker  * @ap:    extra parameters for the message.
577*6777b538SAndroid Build Coastguard Worker  *
578*6777b538SAndroid Build Coastguard Worker  * Formats @msg and places result into @buf.
579*6777b538SAndroid Build Coastguard Worker  *
580*6777b538SAndroid Build Coastguard Worker  * Returns the number of characters written to @buf or -1 if an error occurs.
581*6777b538SAndroid Build Coastguard Worker  */
582*6777b538SAndroid Build Coastguard Worker int
xmlStrVPrintf(xmlChar * buf,int len,const char * msg,va_list ap)583*6777b538SAndroid Build Coastguard Worker xmlStrVPrintf(xmlChar *buf, int len, const char *msg, va_list ap) {
584*6777b538SAndroid Build Coastguard Worker     int ret;
585*6777b538SAndroid Build Coastguard Worker 
586*6777b538SAndroid Build Coastguard Worker     if((buf == NULL) || (msg == NULL)) {
587*6777b538SAndroid Build Coastguard Worker         return(-1);
588*6777b538SAndroid Build Coastguard Worker     }
589*6777b538SAndroid Build Coastguard Worker 
590*6777b538SAndroid Build Coastguard Worker     ret = vsnprintf((char *) buf, len, (const char *) msg, ap);
591*6777b538SAndroid Build Coastguard Worker     buf[len - 1] = 0; /* be safe ! */
592*6777b538SAndroid Build Coastguard Worker 
593*6777b538SAndroid Build Coastguard Worker     return(ret);
594*6777b538SAndroid Build Coastguard Worker }
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker /**
597*6777b538SAndroid Build Coastguard Worker  * xmlStrVASPrintf:
598*6777b538SAndroid Build Coastguard Worker  * @out:  pointer to the resulting string
599*6777b538SAndroid Build Coastguard Worker  * @maxSize:  maximum size of the output buffer
600*6777b538SAndroid Build Coastguard Worker  * @fmt:  printf format string
601*6777b538SAndroid Build Coastguard Worker  * @ap:  arguments for format string
602*6777b538SAndroid Build Coastguard Worker  *
603*6777b538SAndroid Build Coastguard Worker  * Creates a newly allocated string according to format.
604*6777b538SAndroid Build Coastguard Worker  *
605*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, 1 if the result was truncated or on other
606*6777b538SAndroid Build Coastguard Worker  * errors, -1 if a memory allocation failed.
607*6777b538SAndroid Build Coastguard Worker  */
608*6777b538SAndroid Build Coastguard Worker int
xmlStrVASPrintf(xmlChar ** out,int maxSize,const char * msg,va_list ap)609*6777b538SAndroid Build Coastguard Worker xmlStrVASPrintf(xmlChar **out, int maxSize, const char *msg, va_list ap) {
610*6777b538SAndroid Build Coastguard Worker     char empty[1];
611*6777b538SAndroid Build Coastguard Worker     va_list copy;
612*6777b538SAndroid Build Coastguard Worker     xmlChar *buf;
613*6777b538SAndroid Build Coastguard Worker     int res, size;
614*6777b538SAndroid Build Coastguard Worker     int truncated = 0;
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker     if (out == NULL)
617*6777b538SAndroid Build Coastguard Worker         return(1);
618*6777b538SAndroid Build Coastguard Worker     *out = NULL;
619*6777b538SAndroid Build Coastguard Worker     if (msg == NULL)
620*6777b538SAndroid Build Coastguard Worker         return(1);
621*6777b538SAndroid Build Coastguard Worker     if (maxSize < 32)
622*6777b538SAndroid Build Coastguard Worker         maxSize = 32;
623*6777b538SAndroid Build Coastguard Worker 
624*6777b538SAndroid Build Coastguard Worker     va_copy(copy, ap);
625*6777b538SAndroid Build Coastguard Worker     res = vsnprintf(empty, 1, msg, copy);
626*6777b538SAndroid Build Coastguard Worker     va_end(copy);
627*6777b538SAndroid Build Coastguard Worker 
628*6777b538SAndroid Build Coastguard Worker     if (res > 0) {
629*6777b538SAndroid Build Coastguard Worker         /* snprintf seems to work according to C99. */
630*6777b538SAndroid Build Coastguard Worker 
631*6777b538SAndroid Build Coastguard Worker         if (res < maxSize) {
632*6777b538SAndroid Build Coastguard Worker             size = res + 1;
633*6777b538SAndroid Build Coastguard Worker         } else {
634*6777b538SAndroid Build Coastguard Worker             size = maxSize;
635*6777b538SAndroid Build Coastguard Worker             truncated = 1;
636*6777b538SAndroid Build Coastguard Worker         }
637*6777b538SAndroid Build Coastguard Worker         buf = xmlMalloc(size);
638*6777b538SAndroid Build Coastguard Worker         if (buf == NULL)
639*6777b538SAndroid Build Coastguard Worker             return(-1);
640*6777b538SAndroid Build Coastguard Worker         if (vsnprintf((char *) buf, size, msg, ap) < 0) {
641*6777b538SAndroid Build Coastguard Worker             xmlFree(buf);
642*6777b538SAndroid Build Coastguard Worker             return(1);
643*6777b538SAndroid Build Coastguard Worker         }
644*6777b538SAndroid Build Coastguard Worker     } else {
645*6777b538SAndroid Build Coastguard Worker         /*
646*6777b538SAndroid Build Coastguard Worker          * Unfortunately, older snprintf implementations don't follow the
647*6777b538SAndroid Build Coastguard Worker          * C99 spec. If the output exceeds the size of the buffer, they can
648*6777b538SAndroid Build Coastguard Worker          * return -1, 0 or the number of characters written instead of the
649*6777b538SAndroid Build Coastguard Worker          * needed size. Older MSCVRT also won't write a terminating null
650*6777b538SAndroid Build Coastguard Worker          * byte if the buffer is too small.
651*6777b538SAndroid Build Coastguard Worker          *
652*6777b538SAndroid Build Coastguard Worker          * If the value returned is non-negative and strictly less than
653*6777b538SAndroid Build Coastguard Worker          * the buffer size (without terminating null), the result should
654*6777b538SAndroid Build Coastguard Worker          * have been written completely, so we double the buffer size
655*6777b538SAndroid Build Coastguard Worker          * until this condition is true. This assumes that snprintf will
656*6777b538SAndroid Build Coastguard Worker          * eventually return a non-negative value. Otherwise, we will
657*6777b538SAndroid Build Coastguard Worker          * allocate more and more memory until we run out.
658*6777b538SAndroid Build Coastguard Worker          *
659*6777b538SAndroid Build Coastguard Worker          * Note that this code path is also executed on conforming
660*6777b538SAndroid Build Coastguard Worker          * platforms if the output is the empty string.
661*6777b538SAndroid Build Coastguard Worker          */
662*6777b538SAndroid Build Coastguard Worker 
663*6777b538SAndroid Build Coastguard Worker         buf = NULL;
664*6777b538SAndroid Build Coastguard Worker         size = 32;
665*6777b538SAndroid Build Coastguard Worker         while (1) {
666*6777b538SAndroid Build Coastguard Worker             buf = xmlMalloc(size);
667*6777b538SAndroid Build Coastguard Worker             if (buf == NULL)
668*6777b538SAndroid Build Coastguard Worker                 return(-1);
669*6777b538SAndroid Build Coastguard Worker 
670*6777b538SAndroid Build Coastguard Worker             va_copy(copy, ap);
671*6777b538SAndroid Build Coastguard Worker             res = vsnprintf((char *) buf, size, msg, copy);
672*6777b538SAndroid Build Coastguard Worker             va_end(copy);
673*6777b538SAndroid Build Coastguard Worker             if ((res >= 0) && (res < size - 1))
674*6777b538SAndroid Build Coastguard Worker                 break;
675*6777b538SAndroid Build Coastguard Worker 
676*6777b538SAndroid Build Coastguard Worker             if (size >= maxSize) {
677*6777b538SAndroid Build Coastguard Worker                 truncated = 1;
678*6777b538SAndroid Build Coastguard Worker                 break;
679*6777b538SAndroid Build Coastguard Worker             }
680*6777b538SAndroid Build Coastguard Worker 
681*6777b538SAndroid Build Coastguard Worker             xmlFree(buf);
682*6777b538SAndroid Build Coastguard Worker 
683*6777b538SAndroid Build Coastguard Worker             if (size > maxSize / 2)
684*6777b538SAndroid Build Coastguard Worker                 size = maxSize;
685*6777b538SAndroid Build Coastguard Worker             else
686*6777b538SAndroid Build Coastguard Worker                 size *= 2;
687*6777b538SAndroid Build Coastguard Worker         }
688*6777b538SAndroid Build Coastguard Worker     }
689*6777b538SAndroid Build Coastguard Worker 
690*6777b538SAndroid Build Coastguard Worker     /*
691*6777b538SAndroid Build Coastguard Worker      * If the output was truncated, make sure that the buffer doesn't
692*6777b538SAndroid Build Coastguard Worker      * end with a truncated UTF-8 sequence.
693*6777b538SAndroid Build Coastguard Worker      */
694*6777b538SAndroid Build Coastguard Worker     if (truncated != 0) {
695*6777b538SAndroid Build Coastguard Worker         int i = size - 1;
696*6777b538SAndroid Build Coastguard Worker 
697*6777b538SAndroid Build Coastguard Worker         while (i > 0) {
698*6777b538SAndroid Build Coastguard Worker             /* Break after ASCII */
699*6777b538SAndroid Build Coastguard Worker             if (buf[i-1] < 0x80)
700*6777b538SAndroid Build Coastguard Worker                 break;
701*6777b538SAndroid Build Coastguard Worker             i -= 1;
702*6777b538SAndroid Build Coastguard Worker             /* Break before non-ASCII */
703*6777b538SAndroid Build Coastguard Worker             if (buf[i] >= 0xc0)
704*6777b538SAndroid Build Coastguard Worker                 break;
705*6777b538SAndroid Build Coastguard Worker         }
706*6777b538SAndroid Build Coastguard Worker 
707*6777b538SAndroid Build Coastguard Worker         buf[i] = 0;
708*6777b538SAndroid Build Coastguard Worker     }
709*6777b538SAndroid Build Coastguard Worker 
710*6777b538SAndroid Build Coastguard Worker     *out = (xmlChar *) buf;
711*6777b538SAndroid Build Coastguard Worker     return(truncated);
712*6777b538SAndroid Build Coastguard Worker }
713*6777b538SAndroid Build Coastguard Worker 
714*6777b538SAndroid Build Coastguard Worker /**
715*6777b538SAndroid Build Coastguard Worker  * xmlStrASPrintf:
716*6777b538SAndroid Build Coastguard Worker  * @out:  pointer to the resulting string
717*6777b538SAndroid Build Coastguard Worker  * @maxSize:  maximum size of the output buffer
718*6777b538SAndroid Build Coastguard Worker  * @fmt:  printf format string
719*6777b538SAndroid Build Coastguard Worker  * @ap:  arguments for format string
720*6777b538SAndroid Build Coastguard Worker  *
721*6777b538SAndroid Build Coastguard Worker  * See xmlStrVASPrintf.
722*6777b538SAndroid Build Coastguard Worker  *
723*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, 1 if the result was truncated or on other
724*6777b538SAndroid Build Coastguard Worker  * errors, -1 if a memory allocation failed.
725*6777b538SAndroid Build Coastguard Worker  */
726*6777b538SAndroid Build Coastguard Worker int
xmlStrASPrintf(xmlChar ** out,int maxSize,const char * msg,...)727*6777b538SAndroid Build Coastguard Worker xmlStrASPrintf(xmlChar **out, int maxSize, const char *msg, ...) {
728*6777b538SAndroid Build Coastguard Worker     va_list ap;
729*6777b538SAndroid Build Coastguard Worker     int ret;
730*6777b538SAndroid Build Coastguard Worker 
731*6777b538SAndroid Build Coastguard Worker     va_start(ap, msg);
732*6777b538SAndroid Build Coastguard Worker     ret = xmlStrVASPrintf(out, maxSize, msg, ap);
733*6777b538SAndroid Build Coastguard Worker     va_end(ap);
734*6777b538SAndroid Build Coastguard Worker 
735*6777b538SAndroid Build Coastguard Worker     return(ret);
736*6777b538SAndroid Build Coastguard Worker }
737*6777b538SAndroid Build Coastguard Worker 
738*6777b538SAndroid Build Coastguard Worker /************************************************************************
739*6777b538SAndroid Build Coastguard Worker  *                                                                      *
740*6777b538SAndroid Build Coastguard Worker  *              Generic UTF8 handling routines                          *
741*6777b538SAndroid Build Coastguard Worker  *                                                                      *
742*6777b538SAndroid Build Coastguard Worker  * From rfc2044: encoding of the Unicode values on UTF-8:               *
743*6777b538SAndroid Build Coastguard Worker  *                                                                      *
744*6777b538SAndroid Build Coastguard Worker  * UCS-4 range (hex.)           UTF-8 octet sequence (binary)           *
745*6777b538SAndroid Build Coastguard Worker  * 0000 0000-0000 007F   0xxxxxxx                                       *
746*6777b538SAndroid Build Coastguard Worker  * 0000 0080-0000 07FF   110xxxxx 10xxxxxx                              *
747*6777b538SAndroid Build Coastguard Worker  * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx                     *
748*6777b538SAndroid Build Coastguard Worker  *                                                                      *
749*6777b538SAndroid Build Coastguard Worker  * I hope we won't use values > 0xFFFF anytime soon !                   *
750*6777b538SAndroid Build Coastguard Worker  *                                                                      *
751*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
752*6777b538SAndroid Build Coastguard Worker 
753*6777b538SAndroid Build Coastguard Worker 
754*6777b538SAndroid Build Coastguard Worker /**
755*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Size:
756*6777b538SAndroid Build Coastguard Worker  * @utf: pointer to the UTF8 character
757*6777b538SAndroid Build Coastguard Worker  *
758*6777b538SAndroid Build Coastguard Worker  * calculates the internal size of a UTF8 character
759*6777b538SAndroid Build Coastguard Worker  *
760*6777b538SAndroid Build Coastguard Worker  * returns the numbers of bytes in the character, -1 on format error
761*6777b538SAndroid Build Coastguard Worker  */
762*6777b538SAndroid Build Coastguard Worker int
xmlUTF8Size(const xmlChar * utf)763*6777b538SAndroid Build Coastguard Worker xmlUTF8Size(const xmlChar *utf) {
764*6777b538SAndroid Build Coastguard Worker     xmlChar mask;
765*6777b538SAndroid Build Coastguard Worker     int len;
766*6777b538SAndroid Build Coastguard Worker 
767*6777b538SAndroid Build Coastguard Worker     if (utf == NULL)
768*6777b538SAndroid Build Coastguard Worker         return -1;
769*6777b538SAndroid Build Coastguard Worker     if (*utf < 0x80)
770*6777b538SAndroid Build Coastguard Worker         return 1;
771*6777b538SAndroid Build Coastguard Worker     /* check valid UTF8 character */
772*6777b538SAndroid Build Coastguard Worker     if (!(*utf & 0x40))
773*6777b538SAndroid Build Coastguard Worker         return -1;
774*6777b538SAndroid Build Coastguard Worker     /* determine number of bytes in char */
775*6777b538SAndroid Build Coastguard Worker     len = 2;
776*6777b538SAndroid Build Coastguard Worker     for (mask=0x20; mask != 0; mask>>=1) {
777*6777b538SAndroid Build Coastguard Worker         if (!(*utf & mask))
778*6777b538SAndroid Build Coastguard Worker             return len;
779*6777b538SAndroid Build Coastguard Worker         len++;
780*6777b538SAndroid Build Coastguard Worker     }
781*6777b538SAndroid Build Coastguard Worker     return -1;
782*6777b538SAndroid Build Coastguard Worker }
783*6777b538SAndroid Build Coastguard Worker 
784*6777b538SAndroid Build Coastguard Worker /**
785*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Charcmp:
786*6777b538SAndroid Build Coastguard Worker  * @utf1: pointer to first UTF8 char
787*6777b538SAndroid Build Coastguard Worker  * @utf2: pointer to second UTF8 char
788*6777b538SAndroid Build Coastguard Worker  *
789*6777b538SAndroid Build Coastguard Worker  * compares the two UCS4 values
790*6777b538SAndroid Build Coastguard Worker  *
791*6777b538SAndroid Build Coastguard Worker  * returns result of the compare as with xmlStrncmp
792*6777b538SAndroid Build Coastguard Worker  */
793*6777b538SAndroid Build Coastguard Worker int
xmlUTF8Charcmp(const xmlChar * utf1,const xmlChar * utf2)794*6777b538SAndroid Build Coastguard Worker xmlUTF8Charcmp(const xmlChar *utf1, const xmlChar *utf2) {
795*6777b538SAndroid Build Coastguard Worker 
796*6777b538SAndroid Build Coastguard Worker     if (utf1 == NULL ) {
797*6777b538SAndroid Build Coastguard Worker         if (utf2 == NULL)
798*6777b538SAndroid Build Coastguard Worker             return 0;
799*6777b538SAndroid Build Coastguard Worker         return -1;
800*6777b538SAndroid Build Coastguard Worker     }
801*6777b538SAndroid Build Coastguard Worker     return xmlStrncmp(utf1, utf2, xmlUTF8Size(utf1));
802*6777b538SAndroid Build Coastguard Worker }
803*6777b538SAndroid Build Coastguard Worker 
804*6777b538SAndroid Build Coastguard Worker /**
805*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strlen:
806*6777b538SAndroid Build Coastguard Worker  * @utf:  a sequence of UTF-8 encoded bytes
807*6777b538SAndroid Build Coastguard Worker  *
808*6777b538SAndroid Build Coastguard Worker  * compute the length of an UTF8 string, it doesn't do a full UTF8
809*6777b538SAndroid Build Coastguard Worker  * checking of the content of the string.
810*6777b538SAndroid Build Coastguard Worker  *
811*6777b538SAndroid Build Coastguard Worker  * Returns the number of characters in the string or -1 in case of error
812*6777b538SAndroid Build Coastguard Worker  */
813*6777b538SAndroid Build Coastguard Worker int
xmlUTF8Strlen(const xmlChar * utf)814*6777b538SAndroid Build Coastguard Worker xmlUTF8Strlen(const xmlChar *utf) {
815*6777b538SAndroid Build Coastguard Worker     size_t ret = 0;
816*6777b538SAndroid Build Coastguard Worker 
817*6777b538SAndroid Build Coastguard Worker     if (utf == NULL)
818*6777b538SAndroid Build Coastguard Worker         return(-1);
819*6777b538SAndroid Build Coastguard Worker 
820*6777b538SAndroid Build Coastguard Worker     while (*utf != 0) {
821*6777b538SAndroid Build Coastguard Worker         if (utf[0] & 0x80) {
822*6777b538SAndroid Build Coastguard Worker             if ((utf[1] & 0xc0) != 0x80)
823*6777b538SAndroid Build Coastguard Worker                 return(-1);
824*6777b538SAndroid Build Coastguard Worker             if ((utf[0] & 0xe0) == 0xe0) {
825*6777b538SAndroid Build Coastguard Worker                 if ((utf[2] & 0xc0) != 0x80)
826*6777b538SAndroid Build Coastguard Worker                     return(-1);
827*6777b538SAndroid Build Coastguard Worker                 if ((utf[0] & 0xf0) == 0xf0) {
828*6777b538SAndroid Build Coastguard Worker                     if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
829*6777b538SAndroid Build Coastguard Worker                         return(-1);
830*6777b538SAndroid Build Coastguard Worker                     utf += 4;
831*6777b538SAndroid Build Coastguard Worker                 } else {
832*6777b538SAndroid Build Coastguard Worker                     utf += 3;
833*6777b538SAndroid Build Coastguard Worker                 }
834*6777b538SAndroid Build Coastguard Worker             } else {
835*6777b538SAndroid Build Coastguard Worker                 utf += 2;
836*6777b538SAndroid Build Coastguard Worker             }
837*6777b538SAndroid Build Coastguard Worker         } else {
838*6777b538SAndroid Build Coastguard Worker             utf++;
839*6777b538SAndroid Build Coastguard Worker         }
840*6777b538SAndroid Build Coastguard Worker         ret++;
841*6777b538SAndroid Build Coastguard Worker     }
842*6777b538SAndroid Build Coastguard Worker     return(ret > INT_MAX ? 0 : ret);
843*6777b538SAndroid Build Coastguard Worker }
844*6777b538SAndroid Build Coastguard Worker 
845*6777b538SAndroid Build Coastguard Worker /**
846*6777b538SAndroid Build Coastguard Worker  * xmlGetUTF8Char:
847*6777b538SAndroid Build Coastguard Worker  * @utf:  a sequence of UTF-8 encoded bytes
848*6777b538SAndroid Build Coastguard Worker  * @len:  a pointer to the minimum number of bytes present in
849*6777b538SAndroid Build Coastguard Worker  *        the sequence.  This is used to assure the next character
850*6777b538SAndroid Build Coastguard Worker  *        is completely contained within the sequence.
851*6777b538SAndroid Build Coastguard Worker  *
852*6777b538SAndroid Build Coastguard Worker  * Read the first UTF8 character from @utf
853*6777b538SAndroid Build Coastguard Worker  *
854*6777b538SAndroid Build Coastguard Worker  * Returns the char value or -1 in case of error, and sets *len to
855*6777b538SAndroid Build Coastguard Worker  *        the actual number of bytes consumed (0 in case of error)
856*6777b538SAndroid Build Coastguard Worker  */
857*6777b538SAndroid Build Coastguard Worker int
xmlGetUTF8Char(const unsigned char * utf,int * len)858*6777b538SAndroid Build Coastguard Worker xmlGetUTF8Char(const unsigned char *utf, int *len) {
859*6777b538SAndroid Build Coastguard Worker     unsigned int c;
860*6777b538SAndroid Build Coastguard Worker 
861*6777b538SAndroid Build Coastguard Worker     if (utf == NULL)
862*6777b538SAndroid Build Coastguard Worker         goto error;
863*6777b538SAndroid Build Coastguard Worker     if (len == NULL)
864*6777b538SAndroid Build Coastguard Worker         goto error;
865*6777b538SAndroid Build Coastguard Worker 
866*6777b538SAndroid Build Coastguard Worker     c = utf[0];
867*6777b538SAndroid Build Coastguard Worker     if (c < 0x80) {
868*6777b538SAndroid Build Coastguard Worker         if (*len < 1)
869*6777b538SAndroid Build Coastguard Worker             goto error;
870*6777b538SAndroid Build Coastguard Worker         /* 1-byte code */
871*6777b538SAndroid Build Coastguard Worker         *len = 1;
872*6777b538SAndroid Build Coastguard Worker     } else {
873*6777b538SAndroid Build Coastguard Worker         if ((*len < 2) || ((utf[1] & 0xc0) != 0x80))
874*6777b538SAndroid Build Coastguard Worker             goto error;
875*6777b538SAndroid Build Coastguard Worker         if (c < 0xe0) {
876*6777b538SAndroid Build Coastguard Worker             if (c < 0xc2)
877*6777b538SAndroid Build Coastguard Worker                 goto error;
878*6777b538SAndroid Build Coastguard Worker             /* 2-byte code */
879*6777b538SAndroid Build Coastguard Worker             *len = 2;
880*6777b538SAndroid Build Coastguard Worker             c = (c & 0x1f) << 6;
881*6777b538SAndroid Build Coastguard Worker             c |= utf[1] & 0x3f;
882*6777b538SAndroid Build Coastguard Worker         } else {
883*6777b538SAndroid Build Coastguard Worker             if ((*len < 3) || ((utf[2] & 0xc0) != 0x80))
884*6777b538SAndroid Build Coastguard Worker                 goto error;
885*6777b538SAndroid Build Coastguard Worker             if (c < 0xf0) {
886*6777b538SAndroid Build Coastguard Worker                 /* 3-byte code */
887*6777b538SAndroid Build Coastguard Worker                 *len = 3;
888*6777b538SAndroid Build Coastguard Worker                 c = (c & 0xf) << 12;
889*6777b538SAndroid Build Coastguard Worker                 c |= (utf[1] & 0x3f) << 6;
890*6777b538SAndroid Build Coastguard Worker                 c |= utf[2] & 0x3f;
891*6777b538SAndroid Build Coastguard Worker                 if ((c < 0x800) || ((c >= 0xd800) && (c < 0xe000)))
892*6777b538SAndroid Build Coastguard Worker                     goto error;
893*6777b538SAndroid Build Coastguard Worker             } else {
894*6777b538SAndroid Build Coastguard Worker                 if ((*len < 4) || ((utf[3] & 0xc0) != 0x80))
895*6777b538SAndroid Build Coastguard Worker                     goto error;
896*6777b538SAndroid Build Coastguard Worker                 *len = 4;
897*6777b538SAndroid Build Coastguard Worker                 /* 4-byte code */
898*6777b538SAndroid Build Coastguard Worker                 c = (c & 0x7) << 18;
899*6777b538SAndroid Build Coastguard Worker                 c |= (utf[1] & 0x3f) << 12;
900*6777b538SAndroid Build Coastguard Worker                 c |= (utf[2] & 0x3f) << 6;
901*6777b538SAndroid Build Coastguard Worker                 c |= utf[3] & 0x3f;
902*6777b538SAndroid Build Coastguard Worker                 if ((c < 0x10000) || (c >= 0x110000))
903*6777b538SAndroid Build Coastguard Worker                     goto error;
904*6777b538SAndroid Build Coastguard Worker             }
905*6777b538SAndroid Build Coastguard Worker         }
906*6777b538SAndroid Build Coastguard Worker     }
907*6777b538SAndroid Build Coastguard Worker     return(c);
908*6777b538SAndroid Build Coastguard Worker 
909*6777b538SAndroid Build Coastguard Worker error:
910*6777b538SAndroid Build Coastguard Worker     if (len != NULL)
911*6777b538SAndroid Build Coastguard Worker 	*len = 0;
912*6777b538SAndroid Build Coastguard Worker     return(-1);
913*6777b538SAndroid Build Coastguard Worker }
914*6777b538SAndroid Build Coastguard Worker 
915*6777b538SAndroid Build Coastguard Worker /**
916*6777b538SAndroid Build Coastguard Worker  * xmlCheckUTF8:
917*6777b538SAndroid Build Coastguard Worker  * @utf: Pointer to putative UTF-8 encoded string.
918*6777b538SAndroid Build Coastguard Worker  *
919*6777b538SAndroid Build Coastguard Worker  * Checks @utf for being valid UTF-8. @utf is assumed to be
920*6777b538SAndroid Build Coastguard Worker  * null-terminated. This function is not super-strict, as it will
921*6777b538SAndroid Build Coastguard Worker  * allow longer UTF-8 sequences than necessary. Note that Java is
922*6777b538SAndroid Build Coastguard Worker  * capable of producing these sequences if provoked. Also note, this
923*6777b538SAndroid Build Coastguard Worker  * routine checks for the 4-byte maximum size, but does not check for
924*6777b538SAndroid Build Coastguard Worker  * 0x10ffff maximum value.
925*6777b538SAndroid Build Coastguard Worker  *
926*6777b538SAndroid Build Coastguard Worker  * Return value: true if @utf is valid.
927*6777b538SAndroid Build Coastguard Worker  **/
928*6777b538SAndroid Build Coastguard Worker int
xmlCheckUTF8(const unsigned char * utf)929*6777b538SAndroid Build Coastguard Worker xmlCheckUTF8(const unsigned char *utf)
930*6777b538SAndroid Build Coastguard Worker {
931*6777b538SAndroid Build Coastguard Worker     int ix;
932*6777b538SAndroid Build Coastguard Worker     unsigned char c;
933*6777b538SAndroid Build Coastguard Worker 
934*6777b538SAndroid Build Coastguard Worker     if (utf == NULL)
935*6777b538SAndroid Build Coastguard Worker         return(0);
936*6777b538SAndroid Build Coastguard Worker     /*
937*6777b538SAndroid Build Coastguard Worker      * utf is a string of 1, 2, 3 or 4 bytes.  The valid strings
938*6777b538SAndroid Build Coastguard Worker      * are as follows (in "bit format"):
939*6777b538SAndroid Build Coastguard Worker      *    0xxxxxxx                                      valid 1-byte
940*6777b538SAndroid Build Coastguard Worker      *    110xxxxx 10xxxxxx                             valid 2-byte
941*6777b538SAndroid Build Coastguard Worker      *    1110xxxx 10xxxxxx 10xxxxxx                    valid 3-byte
942*6777b538SAndroid Build Coastguard Worker      *    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx           valid 4-byte
943*6777b538SAndroid Build Coastguard Worker      */
944*6777b538SAndroid Build Coastguard Worker     while ((c = utf[0])) {      /* string is 0-terminated */
945*6777b538SAndroid Build Coastguard Worker         ix = 0;
946*6777b538SAndroid Build Coastguard Worker         if ((c & 0x80) == 0x00) {	/* 1-byte code, starts with 10 */
947*6777b538SAndroid Build Coastguard Worker             ix = 1;
948*6777b538SAndroid Build Coastguard Worker 	} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
949*6777b538SAndroid Build Coastguard Worker 	    if ((utf[1] & 0xc0 ) != 0x80)
950*6777b538SAndroid Build Coastguard Worker 	        return 0;
951*6777b538SAndroid Build Coastguard Worker 	    ix = 2;
952*6777b538SAndroid Build Coastguard Worker 	} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
953*6777b538SAndroid Build Coastguard Worker 	    if (((utf[1] & 0xc0) != 0x80) ||
954*6777b538SAndroid Build Coastguard Worker 	        ((utf[2] & 0xc0) != 0x80))
955*6777b538SAndroid Build Coastguard Worker 		    return 0;
956*6777b538SAndroid Build Coastguard Worker 	    ix = 3;
957*6777b538SAndroid Build Coastguard Worker 	} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
958*6777b538SAndroid Build Coastguard Worker 	    if (((utf[1] & 0xc0) != 0x80) ||
959*6777b538SAndroid Build Coastguard Worker 	        ((utf[2] & 0xc0) != 0x80) ||
960*6777b538SAndroid Build Coastguard Worker 		((utf[3] & 0xc0) != 0x80))
961*6777b538SAndroid Build Coastguard Worker 		    return 0;
962*6777b538SAndroid Build Coastguard Worker 	    ix = 4;
963*6777b538SAndroid Build Coastguard Worker 	} else				/* unknown encoding */
964*6777b538SAndroid Build Coastguard Worker 	    return 0;
965*6777b538SAndroid Build Coastguard Worker         utf += ix;
966*6777b538SAndroid Build Coastguard Worker       }
967*6777b538SAndroid Build Coastguard Worker       return(1);
968*6777b538SAndroid Build Coastguard Worker }
969*6777b538SAndroid Build Coastguard Worker 
970*6777b538SAndroid Build Coastguard Worker /**
971*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strsize:
972*6777b538SAndroid Build Coastguard Worker  * @utf:  a sequence of UTF-8 encoded bytes
973*6777b538SAndroid Build Coastguard Worker  * @len:  the number of characters in the array
974*6777b538SAndroid Build Coastguard Worker  *
975*6777b538SAndroid Build Coastguard Worker  * storage size of an UTF8 string
976*6777b538SAndroid Build Coastguard Worker  * the behaviour is not guaranteed if the input string is not UTF-8
977*6777b538SAndroid Build Coastguard Worker  *
978*6777b538SAndroid Build Coastguard Worker  * Returns the storage size of
979*6777b538SAndroid Build Coastguard Worker  * the first 'len' characters of ARRAY
980*6777b538SAndroid Build Coastguard Worker  */
981*6777b538SAndroid Build Coastguard Worker 
982*6777b538SAndroid Build Coastguard Worker int
xmlUTF8Strsize(const xmlChar * utf,int len)983*6777b538SAndroid Build Coastguard Worker xmlUTF8Strsize(const xmlChar *utf, int len) {
984*6777b538SAndroid Build Coastguard Worker     const xmlChar *ptr=utf;
985*6777b538SAndroid Build Coastguard Worker     int ch;
986*6777b538SAndroid Build Coastguard Worker     size_t ret;
987*6777b538SAndroid Build Coastguard Worker 
988*6777b538SAndroid Build Coastguard Worker     if (utf == NULL)
989*6777b538SAndroid Build Coastguard Worker         return(0);
990*6777b538SAndroid Build Coastguard Worker 
991*6777b538SAndroid Build Coastguard Worker     if (len <= 0)
992*6777b538SAndroid Build Coastguard Worker         return(0);
993*6777b538SAndroid Build Coastguard Worker 
994*6777b538SAndroid Build Coastguard Worker     while ( len-- > 0) {
995*6777b538SAndroid Build Coastguard Worker         if ( !*ptr )
996*6777b538SAndroid Build Coastguard Worker             break;
997*6777b538SAndroid Build Coastguard Worker         if ( (ch = *ptr++) & 0x80)
998*6777b538SAndroid Build Coastguard Worker             while ((ch<<=1) & 0x80 ) {
999*6777b538SAndroid Build Coastguard Worker 		if (*ptr == 0) break;
1000*6777b538SAndroid Build Coastguard Worker                 ptr++;
1001*6777b538SAndroid Build Coastguard Worker 	    }
1002*6777b538SAndroid Build Coastguard Worker     }
1003*6777b538SAndroid Build Coastguard Worker     ret = ptr - utf;
1004*6777b538SAndroid Build Coastguard Worker     return (ret > INT_MAX ? 0 : ret);
1005*6777b538SAndroid Build Coastguard Worker }
1006*6777b538SAndroid Build Coastguard Worker 
1007*6777b538SAndroid Build Coastguard Worker 
1008*6777b538SAndroid Build Coastguard Worker /**
1009*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strndup:
1010*6777b538SAndroid Build Coastguard Worker  * @utf:  the input UTF8 *
1011*6777b538SAndroid Build Coastguard Worker  * @len:  the len of @utf (in chars)
1012*6777b538SAndroid Build Coastguard Worker  *
1013*6777b538SAndroid Build Coastguard Worker  * a strndup for array of UTF8's
1014*6777b538SAndroid Build Coastguard Worker  *
1015*6777b538SAndroid Build Coastguard Worker  * Returns a new UTF8 * or NULL
1016*6777b538SAndroid Build Coastguard Worker  */
1017*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlUTF8Strndup(const xmlChar * utf,int len)1018*6777b538SAndroid Build Coastguard Worker xmlUTF8Strndup(const xmlChar *utf, int len) {
1019*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
1020*6777b538SAndroid Build Coastguard Worker     int i;
1021*6777b538SAndroid Build Coastguard Worker 
1022*6777b538SAndroid Build Coastguard Worker     if ((utf == NULL) || (len < 0)) return(NULL);
1023*6777b538SAndroid Build Coastguard Worker     i = xmlUTF8Strsize(utf, len);
1024*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMallocAtomic((size_t) i + 1);
1025*6777b538SAndroid Build Coastguard Worker     if (ret == NULL) {
1026*6777b538SAndroid Build Coastguard Worker         return(NULL);
1027*6777b538SAndroid Build Coastguard Worker     }
1028*6777b538SAndroid Build Coastguard Worker     memcpy(ret, utf, i);
1029*6777b538SAndroid Build Coastguard Worker     ret[i] = 0;
1030*6777b538SAndroid Build Coastguard Worker     return(ret);
1031*6777b538SAndroid Build Coastguard Worker }
1032*6777b538SAndroid Build Coastguard Worker 
1033*6777b538SAndroid Build Coastguard Worker /**
1034*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strpos:
1035*6777b538SAndroid Build Coastguard Worker  * @utf:  the input UTF8 *
1036*6777b538SAndroid Build Coastguard Worker  * @pos:  the position of the desired UTF8 char (in chars)
1037*6777b538SAndroid Build Coastguard Worker  *
1038*6777b538SAndroid Build Coastguard Worker  * a function to provide the equivalent of fetching a
1039*6777b538SAndroid Build Coastguard Worker  * character from a string array
1040*6777b538SAndroid Build Coastguard Worker  *
1041*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the UTF8 character or NULL
1042*6777b538SAndroid Build Coastguard Worker  */
1043*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlUTF8Strpos(const xmlChar * utf,int pos)1044*6777b538SAndroid Build Coastguard Worker xmlUTF8Strpos(const xmlChar *utf, int pos) {
1045*6777b538SAndroid Build Coastguard Worker     int ch;
1046*6777b538SAndroid Build Coastguard Worker 
1047*6777b538SAndroid Build Coastguard Worker     if (utf == NULL) return(NULL);
1048*6777b538SAndroid Build Coastguard Worker     if (pos < 0)
1049*6777b538SAndroid Build Coastguard Worker         return(NULL);
1050*6777b538SAndroid Build Coastguard Worker     while (pos--) {
1051*6777b538SAndroid Build Coastguard Worker         if ((ch=*utf++) == 0) return(NULL);
1052*6777b538SAndroid Build Coastguard Worker         if ( ch & 0x80 ) {
1053*6777b538SAndroid Build Coastguard Worker             /* if not simple ascii, verify proper format */
1054*6777b538SAndroid Build Coastguard Worker             if ( (ch & 0xc0) != 0xc0 )
1055*6777b538SAndroid Build Coastguard Worker                 return(NULL);
1056*6777b538SAndroid Build Coastguard Worker             /* then skip over remaining bytes for this char */
1057*6777b538SAndroid Build Coastguard Worker             while ( (ch <<= 1) & 0x80 )
1058*6777b538SAndroid Build Coastguard Worker                 if ( (*utf++ & 0xc0) != 0x80 )
1059*6777b538SAndroid Build Coastguard Worker                     return(NULL);
1060*6777b538SAndroid Build Coastguard Worker         }
1061*6777b538SAndroid Build Coastguard Worker     }
1062*6777b538SAndroid Build Coastguard Worker     return((xmlChar *)utf);
1063*6777b538SAndroid Build Coastguard Worker }
1064*6777b538SAndroid Build Coastguard Worker 
1065*6777b538SAndroid Build Coastguard Worker /**
1066*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strloc:
1067*6777b538SAndroid Build Coastguard Worker  * @utf:  the input UTF8 *
1068*6777b538SAndroid Build Coastguard Worker  * @utfchar:  the UTF8 character to be found
1069*6777b538SAndroid Build Coastguard Worker  *
1070*6777b538SAndroid Build Coastguard Worker  * a function to provide the relative location of a UTF8 char
1071*6777b538SAndroid Build Coastguard Worker  *
1072*6777b538SAndroid Build Coastguard Worker  * Returns the relative character position of the desired char
1073*6777b538SAndroid Build Coastguard Worker  * or -1 if not found
1074*6777b538SAndroid Build Coastguard Worker  */
1075*6777b538SAndroid Build Coastguard Worker int
xmlUTF8Strloc(const xmlChar * utf,const xmlChar * utfchar)1076*6777b538SAndroid Build Coastguard Worker xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) {
1077*6777b538SAndroid Build Coastguard Worker     size_t i;
1078*6777b538SAndroid Build Coastguard Worker     int size;
1079*6777b538SAndroid Build Coastguard Worker     int ch;
1080*6777b538SAndroid Build Coastguard Worker 
1081*6777b538SAndroid Build Coastguard Worker     if (utf==NULL || utfchar==NULL) return -1;
1082*6777b538SAndroid Build Coastguard Worker     size = xmlUTF8Strsize(utfchar, 1);
1083*6777b538SAndroid Build Coastguard Worker         for(i=0; (ch=*utf) != 0; i++) {
1084*6777b538SAndroid Build Coastguard Worker             if (xmlStrncmp(utf, utfchar, size)==0)
1085*6777b538SAndroid Build Coastguard Worker                 return(i > INT_MAX ? 0 : i);
1086*6777b538SAndroid Build Coastguard Worker             utf++;
1087*6777b538SAndroid Build Coastguard Worker             if ( ch & 0x80 ) {
1088*6777b538SAndroid Build Coastguard Worker                 /* if not simple ascii, verify proper format */
1089*6777b538SAndroid Build Coastguard Worker                 if ( (ch & 0xc0) != 0xc0 )
1090*6777b538SAndroid Build Coastguard Worker                     return(-1);
1091*6777b538SAndroid Build Coastguard Worker                 /* then skip over remaining bytes for this char */
1092*6777b538SAndroid Build Coastguard Worker                 while ( (ch <<= 1) & 0x80 )
1093*6777b538SAndroid Build Coastguard Worker                     if ( (*utf++ & 0xc0) != 0x80 )
1094*6777b538SAndroid Build Coastguard Worker                         return(-1);
1095*6777b538SAndroid Build Coastguard Worker             }
1096*6777b538SAndroid Build Coastguard Worker         }
1097*6777b538SAndroid Build Coastguard Worker 
1098*6777b538SAndroid Build Coastguard Worker     return(-1);
1099*6777b538SAndroid Build Coastguard Worker }
1100*6777b538SAndroid Build Coastguard Worker /**
1101*6777b538SAndroid Build Coastguard Worker  * xmlUTF8Strsub:
1102*6777b538SAndroid Build Coastguard Worker  * @utf:  a sequence of UTF-8 encoded bytes
1103*6777b538SAndroid Build Coastguard Worker  * @start: relative pos of first char
1104*6777b538SAndroid Build Coastguard Worker  * @len:   total number to copy
1105*6777b538SAndroid Build Coastguard Worker  *
1106*6777b538SAndroid Build Coastguard Worker  * Create a substring from a given UTF-8 string
1107*6777b538SAndroid Build Coastguard Worker  * Note:  positions are given in units of UTF-8 chars
1108*6777b538SAndroid Build Coastguard Worker  *
1109*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to a newly created string
1110*6777b538SAndroid Build Coastguard Worker  * or NULL if any problem
1111*6777b538SAndroid Build Coastguard Worker  */
1112*6777b538SAndroid Build Coastguard Worker 
1113*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlUTF8Strsub(const xmlChar * utf,int start,int len)1114*6777b538SAndroid Build Coastguard Worker xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
1115*6777b538SAndroid Build Coastguard Worker     int i;
1116*6777b538SAndroid Build Coastguard Worker     int ch;
1117*6777b538SAndroid Build Coastguard Worker 
1118*6777b538SAndroid Build Coastguard Worker     if (utf == NULL) return(NULL);
1119*6777b538SAndroid Build Coastguard Worker     if (start < 0) return(NULL);
1120*6777b538SAndroid Build Coastguard Worker     if (len < 0) return(NULL);
1121*6777b538SAndroid Build Coastguard Worker 
1122*6777b538SAndroid Build Coastguard Worker     /*
1123*6777b538SAndroid Build Coastguard Worker      * Skip over any leading chars
1124*6777b538SAndroid Build Coastguard Worker      */
1125*6777b538SAndroid Build Coastguard Worker     for (i = 0;i < start;i++) {
1126*6777b538SAndroid Build Coastguard Worker         if ((ch=*utf++) == 0) return(NULL);
1127*6777b538SAndroid Build Coastguard Worker         if ( ch & 0x80 ) {
1128*6777b538SAndroid Build Coastguard Worker             /* if not simple ascii, verify proper format */
1129*6777b538SAndroid Build Coastguard Worker             if ( (ch & 0xc0) != 0xc0 )
1130*6777b538SAndroid Build Coastguard Worker                 return(NULL);
1131*6777b538SAndroid Build Coastguard Worker             /* then skip over remaining bytes for this char */
1132*6777b538SAndroid Build Coastguard Worker             while ( (ch <<= 1) & 0x80 )
1133*6777b538SAndroid Build Coastguard Worker                 if ( (*utf++ & 0xc0) != 0x80 )
1134*6777b538SAndroid Build Coastguard Worker                     return(NULL);
1135*6777b538SAndroid Build Coastguard Worker         }
1136*6777b538SAndroid Build Coastguard Worker     }
1137*6777b538SAndroid Build Coastguard Worker 
1138*6777b538SAndroid Build Coastguard Worker     return(xmlUTF8Strndup(utf, len));
1139*6777b538SAndroid Build Coastguard Worker }
1140*6777b538SAndroid Build Coastguard Worker 
1141*6777b538SAndroid Build Coastguard Worker /**
1142*6777b538SAndroid Build Coastguard Worker  * xmlEscapeFormatString:
1143*6777b538SAndroid Build Coastguard Worker  * @msg:  a pointer to the string in which to escape '%' characters.
1144*6777b538SAndroid Build Coastguard Worker  * Must be a heap-allocated buffer created by libxml2 that may be
1145*6777b538SAndroid Build Coastguard Worker  * returned, or that may be freed and replaced.
1146*6777b538SAndroid Build Coastguard Worker  *
1147*6777b538SAndroid Build Coastguard Worker  * Replaces the string pointed to by 'msg' with an escaped string.
1148*6777b538SAndroid Build Coastguard Worker  * Returns the same string with all '%' characters escaped.
1149*6777b538SAndroid Build Coastguard Worker  */
1150*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlEscapeFormatString(xmlChar ** msg)1151*6777b538SAndroid Build Coastguard Worker xmlEscapeFormatString(xmlChar **msg)
1152*6777b538SAndroid Build Coastguard Worker {
1153*6777b538SAndroid Build Coastguard Worker     xmlChar *msgPtr = NULL;
1154*6777b538SAndroid Build Coastguard Worker     xmlChar *result = NULL;
1155*6777b538SAndroid Build Coastguard Worker     xmlChar *resultPtr = NULL;
1156*6777b538SAndroid Build Coastguard Worker     size_t count = 0;
1157*6777b538SAndroid Build Coastguard Worker     size_t msgLen = 0;
1158*6777b538SAndroid Build Coastguard Worker     size_t resultLen = 0;
1159*6777b538SAndroid Build Coastguard Worker 
1160*6777b538SAndroid Build Coastguard Worker     if (!msg || !*msg)
1161*6777b538SAndroid Build Coastguard Worker         return(NULL);
1162*6777b538SAndroid Build Coastguard Worker 
1163*6777b538SAndroid Build Coastguard Worker     for (msgPtr = *msg; *msgPtr != '\0'; ++msgPtr) {
1164*6777b538SAndroid Build Coastguard Worker         ++msgLen;
1165*6777b538SAndroid Build Coastguard Worker         if (*msgPtr == '%')
1166*6777b538SAndroid Build Coastguard Worker             ++count;
1167*6777b538SAndroid Build Coastguard Worker     }
1168*6777b538SAndroid Build Coastguard Worker 
1169*6777b538SAndroid Build Coastguard Worker     if (count == 0)
1170*6777b538SAndroid Build Coastguard Worker         return(*msg);
1171*6777b538SAndroid Build Coastguard Worker 
1172*6777b538SAndroid Build Coastguard Worker     if ((count > INT_MAX) || (msgLen > INT_MAX - count))
1173*6777b538SAndroid Build Coastguard Worker         return(NULL);
1174*6777b538SAndroid Build Coastguard Worker     resultLen = msgLen + count + 1;
1175*6777b538SAndroid Build Coastguard Worker     result = (xmlChar *) xmlMallocAtomic(resultLen);
1176*6777b538SAndroid Build Coastguard Worker     if (result == NULL) {
1177*6777b538SAndroid Build Coastguard Worker         /* Clear *msg to prevent format string vulnerabilities in
1178*6777b538SAndroid Build Coastguard Worker            out-of-memory situations. */
1179*6777b538SAndroid Build Coastguard Worker         xmlFree(*msg);
1180*6777b538SAndroid Build Coastguard Worker         *msg = NULL;
1181*6777b538SAndroid Build Coastguard Worker         return(NULL);
1182*6777b538SAndroid Build Coastguard Worker     }
1183*6777b538SAndroid Build Coastguard Worker 
1184*6777b538SAndroid Build Coastguard Worker     for (msgPtr = *msg, resultPtr = result; *msgPtr != '\0'; ++msgPtr, ++resultPtr) {
1185*6777b538SAndroid Build Coastguard Worker         *resultPtr = *msgPtr;
1186*6777b538SAndroid Build Coastguard Worker         if (*msgPtr == '%')
1187*6777b538SAndroid Build Coastguard Worker             *(++resultPtr) = '%';
1188*6777b538SAndroid Build Coastguard Worker     }
1189*6777b538SAndroid Build Coastguard Worker     result[resultLen - 1] = '\0';
1190*6777b538SAndroid Build Coastguard Worker 
1191*6777b538SAndroid Build Coastguard Worker     xmlFree(*msg);
1192*6777b538SAndroid Build Coastguard Worker     *msg = result;
1193*6777b538SAndroid Build Coastguard Worker 
1194*6777b538SAndroid Build Coastguard Worker     return *msg;
1195*6777b538SAndroid Build Coastguard Worker }
1196*6777b538SAndroid Build Coastguard Worker 
1197