1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker *
6*0e209d39SAndroid Build Coastguard Worker * Copyright (C) 2000-2012, International Business Machines
7*0e209d39SAndroid Build Coastguard Worker * Corporation and others. All Rights Reserved.
8*0e209d39SAndroid Build Coastguard Worker *
9*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
10*0e209d39SAndroid Build Coastguard Worker * file name: uparse.c
11*0e209d39SAndroid Build Coastguard Worker * encoding: UTF-8
12*0e209d39SAndroid Build Coastguard Worker * tab size: 8 (not used)
13*0e209d39SAndroid Build Coastguard Worker * indentation:4
14*0e209d39SAndroid Build Coastguard Worker *
15*0e209d39SAndroid Build Coastguard Worker * created on: 2000apr18
16*0e209d39SAndroid Build Coastguard Worker * created by: Markus W. Scherer
17*0e209d39SAndroid Build Coastguard Worker *
18*0e209d39SAndroid Build Coastguard Worker * This file provides a parser for files that are delimited by one single
19*0e209d39SAndroid Build Coastguard Worker * character like ';' or TAB. Example: the Unicode Character Properties files
20*0e209d39SAndroid Build Coastguard Worker * like UnicodeData.txt are semicolon-delimited.
21*0e209d39SAndroid Build Coastguard Worker */
22*0e209d39SAndroid Build Coastguard Worker
23*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
24*0e209d39SAndroid Build Coastguard Worker #include "unicode/uchar.h"
25*0e209d39SAndroid Build Coastguard Worker #include "unicode/ustring.h"
26*0e209d39SAndroid Build Coastguard Worker #include "unicode/utf16.h"
27*0e209d39SAndroid Build Coastguard Worker #include "cstring.h"
28*0e209d39SAndroid Build Coastguard Worker #include "filestrm.h"
29*0e209d39SAndroid Build Coastguard Worker #include "uparse.h"
30*0e209d39SAndroid Build Coastguard Worker #include "ustr_imp.h"
31*0e209d39SAndroid Build Coastguard Worker
32*0e209d39SAndroid Build Coastguard Worker #include <stdio.h>
33*0e209d39SAndroid Build Coastguard Worker
34*0e209d39SAndroid Build Coastguard Worker U_CAPI const char * U_EXPORT2
u_skipWhitespace(const char * s)35*0e209d39SAndroid Build Coastguard Worker u_skipWhitespace(const char *s) {
36*0e209d39SAndroid Build Coastguard Worker while(U_IS_INV_WHITESPACE(*s)) {
37*0e209d39SAndroid Build Coastguard Worker ++s;
38*0e209d39SAndroid Build Coastguard Worker }
39*0e209d39SAndroid Build Coastguard Worker return s;
40*0e209d39SAndroid Build Coastguard Worker }
41*0e209d39SAndroid Build Coastguard Worker
42*0e209d39SAndroid Build Coastguard Worker U_CAPI char * U_EXPORT2
u_rtrim(char * s)43*0e209d39SAndroid Build Coastguard Worker u_rtrim(char *s) {
44*0e209d39SAndroid Build Coastguard Worker char *end=uprv_strchr(s, 0);
45*0e209d39SAndroid Build Coastguard Worker while(s<end && U_IS_INV_WHITESPACE(*(end-1))) {
46*0e209d39SAndroid Build Coastguard Worker *--end = 0;
47*0e209d39SAndroid Build Coastguard Worker }
48*0e209d39SAndroid Build Coastguard Worker return end;
49*0e209d39SAndroid Build Coastguard Worker }
50*0e209d39SAndroid Build Coastguard Worker
51*0e209d39SAndroid Build Coastguard Worker /*
52*0e209d39SAndroid Build Coastguard Worker * If the string starts with # @missing: then return the pointer to the
53*0e209d39SAndroid Build Coastguard Worker * following non-whitespace character.
54*0e209d39SAndroid Build Coastguard Worker * Otherwise return the original pointer.
55*0e209d39SAndroid Build Coastguard Worker * Unicode 5.0 adds such lines in some data files to document
56*0e209d39SAndroid Build Coastguard Worker * default property values.
57*0e209d39SAndroid Build Coastguard Worker * Poor man's regex for variable amounts of white space.
58*0e209d39SAndroid Build Coastguard Worker */
59*0e209d39SAndroid Build Coastguard Worker static const char *
getMissingLimit(const char * s)60*0e209d39SAndroid Build Coastguard Worker getMissingLimit(const char *s) {
61*0e209d39SAndroid Build Coastguard Worker const char *s0=s;
62*0e209d39SAndroid Build Coastguard Worker if(
63*0e209d39SAndroid Build Coastguard Worker *(s=u_skipWhitespace(s))=='#' &&
64*0e209d39SAndroid Build Coastguard Worker *(s=u_skipWhitespace(s+1))=='@' &&
65*0e209d39SAndroid Build Coastguard Worker 0==strncmp((s=u_skipWhitespace(s+1)), "missing", 7) &&
66*0e209d39SAndroid Build Coastguard Worker *(s=u_skipWhitespace(s+7))==':'
67*0e209d39SAndroid Build Coastguard Worker ) {
68*0e209d39SAndroid Build Coastguard Worker return u_skipWhitespace(s+1);
69*0e209d39SAndroid Build Coastguard Worker } else {
70*0e209d39SAndroid Build Coastguard Worker return s0;
71*0e209d39SAndroid Build Coastguard Worker }
72*0e209d39SAndroid Build Coastguard Worker }
73*0e209d39SAndroid Build Coastguard Worker
74*0e209d39SAndroid Build Coastguard Worker U_CAPI void U_EXPORT2
u_parseDelimitedFile(const char * filename,char delimiter,char * fields[][2],int32_t fieldCount,UParseLineFn * lineFn,void * context,UErrorCode * pErrorCode)75*0e209d39SAndroid Build Coastguard Worker u_parseDelimitedFile(const char *filename, char delimiter,
76*0e209d39SAndroid Build Coastguard Worker char *fields[][2], int32_t fieldCount,
77*0e209d39SAndroid Build Coastguard Worker UParseLineFn *lineFn, void *context,
78*0e209d39SAndroid Build Coastguard Worker UErrorCode *pErrorCode) {
79*0e209d39SAndroid Build Coastguard Worker FileStream *file;
80*0e209d39SAndroid Build Coastguard Worker char line[10000];
81*0e209d39SAndroid Build Coastguard Worker char *start, *limit;
82*0e209d39SAndroid Build Coastguard Worker int32_t i, length;
83*0e209d39SAndroid Build Coastguard Worker
84*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
85*0e209d39SAndroid Build Coastguard Worker return;
86*0e209d39SAndroid Build Coastguard Worker }
87*0e209d39SAndroid Build Coastguard Worker
88*0e209d39SAndroid Build Coastguard Worker if(fields==nullptr || lineFn==nullptr || fieldCount<=0) {
89*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
90*0e209d39SAndroid Build Coastguard Worker return;
91*0e209d39SAndroid Build Coastguard Worker }
92*0e209d39SAndroid Build Coastguard Worker
93*0e209d39SAndroid Build Coastguard Worker if(filename==nullptr || *filename==0 || (*filename=='-' && filename[1]==0)) {
94*0e209d39SAndroid Build Coastguard Worker filename=nullptr;
95*0e209d39SAndroid Build Coastguard Worker file=T_FileStream_stdin();
96*0e209d39SAndroid Build Coastguard Worker } else {
97*0e209d39SAndroid Build Coastguard Worker file=T_FileStream_open(filename, "r");
98*0e209d39SAndroid Build Coastguard Worker }
99*0e209d39SAndroid Build Coastguard Worker if(file==nullptr) {
100*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_FILE_ACCESS_ERROR;
101*0e209d39SAndroid Build Coastguard Worker return;
102*0e209d39SAndroid Build Coastguard Worker }
103*0e209d39SAndroid Build Coastguard Worker
104*0e209d39SAndroid Build Coastguard Worker while(T_FileStream_readLine(file, line, sizeof(line))!=nullptr) {
105*0e209d39SAndroid Build Coastguard Worker /* remove trailing newline characters */
106*0e209d39SAndroid Build Coastguard Worker length=(int32_t)(u_rtrim(line)-line);
107*0e209d39SAndroid Build Coastguard Worker
108*0e209d39SAndroid Build Coastguard Worker /*
109*0e209d39SAndroid Build Coastguard Worker * detect a line with # @missing:
110*0e209d39SAndroid Build Coastguard Worker * start parsing after that, or else from the beginning of the line
111*0e209d39SAndroid Build Coastguard Worker * set the default warning for @missing lines
112*0e209d39SAndroid Build Coastguard Worker */
113*0e209d39SAndroid Build Coastguard Worker start=(char *)getMissingLimit(line);
114*0e209d39SAndroid Build Coastguard Worker if(start==line) {
115*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_ZERO_ERROR;
116*0e209d39SAndroid Build Coastguard Worker } else {
117*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_USING_DEFAULT_WARNING;
118*0e209d39SAndroid Build Coastguard Worker }
119*0e209d39SAndroid Build Coastguard Worker
120*0e209d39SAndroid Build Coastguard Worker /* skip this line if it is empty or a comment */
121*0e209d39SAndroid Build Coastguard Worker if(*start==0 || *start=='#') {
122*0e209d39SAndroid Build Coastguard Worker continue;
123*0e209d39SAndroid Build Coastguard Worker }
124*0e209d39SAndroid Build Coastguard Worker
125*0e209d39SAndroid Build Coastguard Worker /* remove in-line comments */
126*0e209d39SAndroid Build Coastguard Worker limit=uprv_strchr(start, '#');
127*0e209d39SAndroid Build Coastguard Worker if(limit!=nullptr) {
128*0e209d39SAndroid Build Coastguard Worker /* get white space before the pound sign */
129*0e209d39SAndroid Build Coastguard Worker while(limit>start && U_IS_INV_WHITESPACE(*(limit-1))) {
130*0e209d39SAndroid Build Coastguard Worker --limit;
131*0e209d39SAndroid Build Coastguard Worker }
132*0e209d39SAndroid Build Coastguard Worker
133*0e209d39SAndroid Build Coastguard Worker /* truncate the line */
134*0e209d39SAndroid Build Coastguard Worker *limit=0;
135*0e209d39SAndroid Build Coastguard Worker }
136*0e209d39SAndroid Build Coastguard Worker
137*0e209d39SAndroid Build Coastguard Worker /* skip lines with only whitespace */
138*0e209d39SAndroid Build Coastguard Worker if(u_skipWhitespace(start)[0]==0) {
139*0e209d39SAndroid Build Coastguard Worker continue;
140*0e209d39SAndroid Build Coastguard Worker }
141*0e209d39SAndroid Build Coastguard Worker
142*0e209d39SAndroid Build Coastguard Worker /* for each field, call the corresponding field function */
143*0e209d39SAndroid Build Coastguard Worker for(i=0; i<fieldCount; ++i) {
144*0e209d39SAndroid Build Coastguard Worker /* set the limit pointer of this field */
145*0e209d39SAndroid Build Coastguard Worker limit=start;
146*0e209d39SAndroid Build Coastguard Worker while(*limit!=delimiter && *limit!=0) {
147*0e209d39SAndroid Build Coastguard Worker ++limit;
148*0e209d39SAndroid Build Coastguard Worker }
149*0e209d39SAndroid Build Coastguard Worker
150*0e209d39SAndroid Build Coastguard Worker /* set the field start and limit in the fields array */
151*0e209d39SAndroid Build Coastguard Worker fields[i][0]=start;
152*0e209d39SAndroid Build Coastguard Worker fields[i][1]=limit;
153*0e209d39SAndroid Build Coastguard Worker
154*0e209d39SAndroid Build Coastguard Worker /* set start to the beginning of the next field, if any */
155*0e209d39SAndroid Build Coastguard Worker start=limit;
156*0e209d39SAndroid Build Coastguard Worker if(*start!=0) {
157*0e209d39SAndroid Build Coastguard Worker ++start;
158*0e209d39SAndroid Build Coastguard Worker } else if(i+1<fieldCount) {
159*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
160*0e209d39SAndroid Build Coastguard Worker limit=line+length;
161*0e209d39SAndroid Build Coastguard Worker i=fieldCount;
162*0e209d39SAndroid Build Coastguard Worker break;
163*0e209d39SAndroid Build Coastguard Worker }
164*0e209d39SAndroid Build Coastguard Worker }
165*0e209d39SAndroid Build Coastguard Worker
166*0e209d39SAndroid Build Coastguard Worker /* too few fields? */
167*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
168*0e209d39SAndroid Build Coastguard Worker break;
169*0e209d39SAndroid Build Coastguard Worker }
170*0e209d39SAndroid Build Coastguard Worker
171*0e209d39SAndroid Build Coastguard Worker /* call the field function */
172*0e209d39SAndroid Build Coastguard Worker lineFn(context, fields, fieldCount, pErrorCode);
173*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
174*0e209d39SAndroid Build Coastguard Worker break;
175*0e209d39SAndroid Build Coastguard Worker }
176*0e209d39SAndroid Build Coastguard Worker }
177*0e209d39SAndroid Build Coastguard Worker
178*0e209d39SAndroid Build Coastguard Worker if(filename!=nullptr) {
179*0e209d39SAndroid Build Coastguard Worker T_FileStream_close(file);
180*0e209d39SAndroid Build Coastguard Worker }
181*0e209d39SAndroid Build Coastguard Worker }
182*0e209d39SAndroid Build Coastguard Worker
183*0e209d39SAndroid Build Coastguard Worker /*
184*0e209d39SAndroid Build Coastguard Worker * parse a list of code points
185*0e209d39SAndroid Build Coastguard Worker * store them as a UTF-32 string in dest[destCapacity]
186*0e209d39SAndroid Build Coastguard Worker * return the number of code points
187*0e209d39SAndroid Build Coastguard Worker */
188*0e209d39SAndroid Build Coastguard Worker U_CAPI int32_t U_EXPORT2
u_parseCodePoints(const char * s,uint32_t * dest,int32_t destCapacity,UErrorCode * pErrorCode)189*0e209d39SAndroid Build Coastguard Worker u_parseCodePoints(const char *s,
190*0e209d39SAndroid Build Coastguard Worker uint32_t *dest, int32_t destCapacity,
191*0e209d39SAndroid Build Coastguard Worker UErrorCode *pErrorCode) {
192*0e209d39SAndroid Build Coastguard Worker char *end;
193*0e209d39SAndroid Build Coastguard Worker uint32_t value;
194*0e209d39SAndroid Build Coastguard Worker int32_t count;
195*0e209d39SAndroid Build Coastguard Worker
196*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
197*0e209d39SAndroid Build Coastguard Worker return 0;
198*0e209d39SAndroid Build Coastguard Worker }
199*0e209d39SAndroid Build Coastguard Worker if(s==nullptr || destCapacity<0 || (destCapacity>0 && dest==nullptr)) {
200*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
201*0e209d39SAndroid Build Coastguard Worker return 0;
202*0e209d39SAndroid Build Coastguard Worker }
203*0e209d39SAndroid Build Coastguard Worker
204*0e209d39SAndroid Build Coastguard Worker count=0;
205*0e209d39SAndroid Build Coastguard Worker for(;;) {
206*0e209d39SAndroid Build Coastguard Worker s=u_skipWhitespace(s);
207*0e209d39SAndroid Build Coastguard Worker if(*s==';' || *s==0) {
208*0e209d39SAndroid Build Coastguard Worker return count;
209*0e209d39SAndroid Build Coastguard Worker }
210*0e209d39SAndroid Build Coastguard Worker
211*0e209d39SAndroid Build Coastguard Worker /* read one code point */
212*0e209d39SAndroid Build Coastguard Worker value=(uint32_t)uprv_strtoul(s, &end, 16);
213*0e209d39SAndroid Build Coastguard Worker if(end<=s || (!U_IS_INV_WHITESPACE(*end) && *end!=';' && *end!=0) || value>=0x110000) {
214*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
215*0e209d39SAndroid Build Coastguard Worker return 0;
216*0e209d39SAndroid Build Coastguard Worker }
217*0e209d39SAndroid Build Coastguard Worker
218*0e209d39SAndroid Build Coastguard Worker /* append it to the destination array */
219*0e209d39SAndroid Build Coastguard Worker if(count<destCapacity) {
220*0e209d39SAndroid Build Coastguard Worker dest[count++]=value;
221*0e209d39SAndroid Build Coastguard Worker } else {
222*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
223*0e209d39SAndroid Build Coastguard Worker }
224*0e209d39SAndroid Build Coastguard Worker
225*0e209d39SAndroid Build Coastguard Worker /* go to the following characters */
226*0e209d39SAndroid Build Coastguard Worker s=end;
227*0e209d39SAndroid Build Coastguard Worker }
228*0e209d39SAndroid Build Coastguard Worker }
229*0e209d39SAndroid Build Coastguard Worker
230*0e209d39SAndroid Build Coastguard Worker /*
231*0e209d39SAndroid Build Coastguard Worker * parse a list of code points
232*0e209d39SAndroid Build Coastguard Worker * store them as a string in dest[destCapacity]
233*0e209d39SAndroid Build Coastguard Worker * set the first code point in *pFirst
234*0e209d39SAndroid Build Coastguard Worker * @return The length of the string in numbers of UChars.
235*0e209d39SAndroid Build Coastguard Worker */
236*0e209d39SAndroid Build Coastguard Worker U_CAPI int32_t U_EXPORT2
u_parseString(const char * s,char16_t * dest,int32_t destCapacity,uint32_t * pFirst,UErrorCode * pErrorCode)237*0e209d39SAndroid Build Coastguard Worker u_parseString(const char *s,
238*0e209d39SAndroid Build Coastguard Worker char16_t *dest, int32_t destCapacity,
239*0e209d39SAndroid Build Coastguard Worker uint32_t *pFirst,
240*0e209d39SAndroid Build Coastguard Worker UErrorCode *pErrorCode) {
241*0e209d39SAndroid Build Coastguard Worker char *end;
242*0e209d39SAndroid Build Coastguard Worker uint32_t value;
243*0e209d39SAndroid Build Coastguard Worker int32_t destLength;
244*0e209d39SAndroid Build Coastguard Worker
245*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
246*0e209d39SAndroid Build Coastguard Worker return 0;
247*0e209d39SAndroid Build Coastguard Worker }
248*0e209d39SAndroid Build Coastguard Worker if(s==nullptr || destCapacity<0 || (destCapacity>0 && dest==nullptr)) {
249*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
250*0e209d39SAndroid Build Coastguard Worker return 0;
251*0e209d39SAndroid Build Coastguard Worker }
252*0e209d39SAndroid Build Coastguard Worker
253*0e209d39SAndroid Build Coastguard Worker if(pFirst!=nullptr) {
254*0e209d39SAndroid Build Coastguard Worker *pFirst=0xffffffff;
255*0e209d39SAndroid Build Coastguard Worker }
256*0e209d39SAndroid Build Coastguard Worker
257*0e209d39SAndroid Build Coastguard Worker destLength=0;
258*0e209d39SAndroid Build Coastguard Worker for(;;) {
259*0e209d39SAndroid Build Coastguard Worker s=u_skipWhitespace(s);
260*0e209d39SAndroid Build Coastguard Worker if(*s==';' || *s==0) {
261*0e209d39SAndroid Build Coastguard Worker if(destLength<destCapacity) {
262*0e209d39SAndroid Build Coastguard Worker dest[destLength]=0;
263*0e209d39SAndroid Build Coastguard Worker } else if(destLength==destCapacity) {
264*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_STRING_NOT_TERMINATED_WARNING;
265*0e209d39SAndroid Build Coastguard Worker } else {
266*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
267*0e209d39SAndroid Build Coastguard Worker }
268*0e209d39SAndroid Build Coastguard Worker return destLength;
269*0e209d39SAndroid Build Coastguard Worker }
270*0e209d39SAndroid Build Coastguard Worker
271*0e209d39SAndroid Build Coastguard Worker /* read one code point */
272*0e209d39SAndroid Build Coastguard Worker value=(uint32_t)uprv_strtoul(s, &end, 16);
273*0e209d39SAndroid Build Coastguard Worker if(end<=s || (!U_IS_INV_WHITESPACE(*end) && *end!=';' && *end!=0) || value>=0x110000) {
274*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
275*0e209d39SAndroid Build Coastguard Worker return 0;
276*0e209d39SAndroid Build Coastguard Worker }
277*0e209d39SAndroid Build Coastguard Worker
278*0e209d39SAndroid Build Coastguard Worker /* store the first code point */
279*0e209d39SAndroid Build Coastguard Worker if(pFirst!=nullptr) {
280*0e209d39SAndroid Build Coastguard Worker *pFirst=value;
281*0e209d39SAndroid Build Coastguard Worker pFirst=nullptr;
282*0e209d39SAndroid Build Coastguard Worker }
283*0e209d39SAndroid Build Coastguard Worker
284*0e209d39SAndroid Build Coastguard Worker /* append it to the destination array */
285*0e209d39SAndroid Build Coastguard Worker if((destLength+U16_LENGTH(value))<=destCapacity) {
286*0e209d39SAndroid Build Coastguard Worker U16_APPEND_UNSAFE(dest, destLength, value);
287*0e209d39SAndroid Build Coastguard Worker } else {
288*0e209d39SAndroid Build Coastguard Worker destLength+=U16_LENGTH(value);
289*0e209d39SAndroid Build Coastguard Worker }
290*0e209d39SAndroid Build Coastguard Worker
291*0e209d39SAndroid Build Coastguard Worker /* go to the following characters */
292*0e209d39SAndroid Build Coastguard Worker s=end;
293*0e209d39SAndroid Build Coastguard Worker }
294*0e209d39SAndroid Build Coastguard Worker }
295*0e209d39SAndroid Build Coastguard Worker
296*0e209d39SAndroid Build Coastguard Worker /* read a range like start or start..end */
297*0e209d39SAndroid Build Coastguard Worker U_CAPI int32_t U_EXPORT2
u_parseCodePointRangeAnyTerminator(const char * s,uint32_t * pStart,uint32_t * pEnd,const char ** terminator,UErrorCode * pErrorCode)298*0e209d39SAndroid Build Coastguard Worker u_parseCodePointRangeAnyTerminator(const char *s,
299*0e209d39SAndroid Build Coastguard Worker uint32_t *pStart, uint32_t *pEnd,
300*0e209d39SAndroid Build Coastguard Worker const char **terminator,
301*0e209d39SAndroid Build Coastguard Worker UErrorCode *pErrorCode) {
302*0e209d39SAndroid Build Coastguard Worker char *end;
303*0e209d39SAndroid Build Coastguard Worker uint32_t value;
304*0e209d39SAndroid Build Coastguard Worker
305*0e209d39SAndroid Build Coastguard Worker if(U_FAILURE(*pErrorCode)) {
306*0e209d39SAndroid Build Coastguard Worker return 0;
307*0e209d39SAndroid Build Coastguard Worker }
308*0e209d39SAndroid Build Coastguard Worker if(s==nullptr || pStart==nullptr || pEnd==nullptr) {
309*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
310*0e209d39SAndroid Build Coastguard Worker return 0;
311*0e209d39SAndroid Build Coastguard Worker }
312*0e209d39SAndroid Build Coastguard Worker
313*0e209d39SAndroid Build Coastguard Worker /* read the start code point */
314*0e209d39SAndroid Build Coastguard Worker s=u_skipWhitespace(s);
315*0e209d39SAndroid Build Coastguard Worker value=(uint32_t)uprv_strtoul(s, &end, 16);
316*0e209d39SAndroid Build Coastguard Worker if(end<=s || value>=0x110000) {
317*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
318*0e209d39SAndroid Build Coastguard Worker return 0;
319*0e209d39SAndroid Build Coastguard Worker }
320*0e209d39SAndroid Build Coastguard Worker *pStart=*pEnd=value;
321*0e209d39SAndroid Build Coastguard Worker
322*0e209d39SAndroid Build Coastguard Worker /* is there a "..end"? */
323*0e209d39SAndroid Build Coastguard Worker s=u_skipWhitespace(end);
324*0e209d39SAndroid Build Coastguard Worker if(*s!='.' || s[1]!='.') {
325*0e209d39SAndroid Build Coastguard Worker *terminator=end;
326*0e209d39SAndroid Build Coastguard Worker return 1;
327*0e209d39SAndroid Build Coastguard Worker }
328*0e209d39SAndroid Build Coastguard Worker s=u_skipWhitespace(s+2);
329*0e209d39SAndroid Build Coastguard Worker
330*0e209d39SAndroid Build Coastguard Worker /* read the end code point */
331*0e209d39SAndroid Build Coastguard Worker value=(uint32_t)uprv_strtoul(s, &end, 16);
332*0e209d39SAndroid Build Coastguard Worker if(end<=s || value>=0x110000) {
333*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
334*0e209d39SAndroid Build Coastguard Worker return 0;
335*0e209d39SAndroid Build Coastguard Worker }
336*0e209d39SAndroid Build Coastguard Worker *pEnd=value;
337*0e209d39SAndroid Build Coastguard Worker
338*0e209d39SAndroid Build Coastguard Worker /* is this a valid range? */
339*0e209d39SAndroid Build Coastguard Worker if(value<*pStart) {
340*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
341*0e209d39SAndroid Build Coastguard Worker return 0;
342*0e209d39SAndroid Build Coastguard Worker }
343*0e209d39SAndroid Build Coastguard Worker
344*0e209d39SAndroid Build Coastguard Worker *terminator=end;
345*0e209d39SAndroid Build Coastguard Worker return value-*pStart+1;
346*0e209d39SAndroid Build Coastguard Worker }
347*0e209d39SAndroid Build Coastguard Worker
348*0e209d39SAndroid Build Coastguard Worker U_CAPI int32_t U_EXPORT2
u_parseCodePointRange(const char * s,uint32_t * pStart,uint32_t * pEnd,UErrorCode * pErrorCode)349*0e209d39SAndroid Build Coastguard Worker u_parseCodePointRange(const char *s,
350*0e209d39SAndroid Build Coastguard Worker uint32_t *pStart, uint32_t *pEnd,
351*0e209d39SAndroid Build Coastguard Worker UErrorCode *pErrorCode) {
352*0e209d39SAndroid Build Coastguard Worker const char *terminator;
353*0e209d39SAndroid Build Coastguard Worker int32_t rangeLength=
354*0e209d39SAndroid Build Coastguard Worker u_parseCodePointRangeAnyTerminator(s, pStart, pEnd, &terminator, pErrorCode);
355*0e209d39SAndroid Build Coastguard Worker if(U_SUCCESS(*pErrorCode)) {
356*0e209d39SAndroid Build Coastguard Worker terminator=u_skipWhitespace(terminator);
357*0e209d39SAndroid Build Coastguard Worker if(*terminator!=';' && *terminator!=0) {
358*0e209d39SAndroid Build Coastguard Worker *pErrorCode=U_PARSE_ERROR;
359*0e209d39SAndroid Build Coastguard Worker return 0;
360*0e209d39SAndroid Build Coastguard Worker }
361*0e209d39SAndroid Build Coastguard Worker }
362*0e209d39SAndroid Build Coastguard Worker return rangeLength;
363*0e209d39SAndroid Build Coastguard Worker }
364*0e209d39SAndroid Build Coastguard Worker
365*0e209d39SAndroid Build Coastguard Worker U_CAPI int32_t U_EXPORT2
u_parseUTF8(const char * source,int32_t sLen,char * dest,int32_t destCapacity,UErrorCode * status)366*0e209d39SAndroid Build Coastguard Worker u_parseUTF8(const char *source, int32_t sLen, char *dest, int32_t destCapacity, UErrorCode *status) {
367*0e209d39SAndroid Build Coastguard Worker const char *read = source;
368*0e209d39SAndroid Build Coastguard Worker int32_t i = 0;
369*0e209d39SAndroid Build Coastguard Worker unsigned int value = 0;
370*0e209d39SAndroid Build Coastguard Worker if(sLen == -1) {
371*0e209d39SAndroid Build Coastguard Worker sLen = (int32_t)strlen(source);
372*0e209d39SAndroid Build Coastguard Worker }
373*0e209d39SAndroid Build Coastguard Worker
374*0e209d39SAndroid Build Coastguard Worker while(read < source+sLen) {
375*0e209d39SAndroid Build Coastguard Worker sscanf(read, "%2x", &value);
376*0e209d39SAndroid Build Coastguard Worker if(i < destCapacity) {
377*0e209d39SAndroid Build Coastguard Worker dest[i] = (char)value;
378*0e209d39SAndroid Build Coastguard Worker }
379*0e209d39SAndroid Build Coastguard Worker i++;
380*0e209d39SAndroid Build Coastguard Worker read += 2;
381*0e209d39SAndroid Build Coastguard Worker }
382*0e209d39SAndroid Build Coastguard Worker return u_terminateChars(dest, destCapacity, i, status);
383*0e209d39SAndroid Build Coastguard Worker }
384