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