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