]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ****************************************************************************** | |
3 | * | |
4 | * Copyright (C) 2000-2003, International Business Machines | |
5 | * Corporation and others. All Rights Reserved. | |
6 | * | |
7 | ****************************************************************************** | |
8 | * | |
9 | * File sscanf.c | |
10 | * | |
11 | * Modification History: | |
12 | * | |
13 | * Date Name Description | |
14 | * 02/08/00 george Creation. Copied from uscanf.c | |
15 | ****************************************************************************** | |
16 | */ | |
17 | ||
18 | #include "unicode/utypes.h" | |
19 | ||
20 | #if !UCONFIG_NO_FORMATTING | |
21 | ||
22 | #include "unicode/uchar.h" | |
23 | ||
24 | #include "sscanf.h" | |
25 | #include "sscanf_p.h" | |
26 | #include "uscanset.h" | |
27 | #include "unicode/ustdio.h" | |
28 | #include "unicode/ustring.h" | |
29 | #include "locbund.h" | |
30 | #include "loccache.h" | |
31 | #include "unicode/unum.h" | |
32 | #include "unicode/udat.h" | |
33 | #include "unicode/uloc.h" | |
34 | ||
35 | #include "cmemory.h" | |
36 | #include "ustr_imp.h" | |
37 | ||
38 | /* --- Prototypes ---------------------------- */ | |
39 | ||
40 | int32_t | |
41 | u_sscanf_simple_percent_handler(u_localized_string *input, | |
42 | const u_sscanf_spec_info *info, | |
43 | ufmt_args *args, | |
44 | const UChar *fmt, | |
45 | int32_t *consumed); | |
46 | ||
47 | int32_t | |
48 | u_sscanf_ustring_handler(u_localized_string *input, | |
49 | const u_sscanf_spec_info *info, | |
50 | ufmt_args *args, | |
51 | const UChar *fmt, | |
52 | int32_t *consumed); | |
53 | ||
54 | int32_t | |
55 | u_sscanf_count_handler(u_localized_string *input, | |
56 | const u_sscanf_spec_info *info, | |
57 | ufmt_args *args, | |
58 | const UChar *fmt, | |
59 | int32_t *consumed); | |
60 | ||
61 | int32_t | |
62 | u_sscanf_integer_handler(u_localized_string *input, | |
63 | const u_sscanf_spec_info *info, | |
64 | ufmt_args *args, | |
65 | const UChar *fmt, | |
66 | int32_t *consumed); | |
67 | ||
68 | int32_t | |
69 | u_sscanf_uinteger_handler(u_localized_string *input, | |
70 | const u_sscanf_spec_info *info, | |
71 | ufmt_args *args, | |
72 | const UChar *fmt, | |
73 | int32_t *consumed); | |
74 | ||
75 | int32_t | |
76 | u_sscanf_double_handler(u_localized_string *input, | |
77 | const u_sscanf_spec_info *info, | |
78 | ufmt_args *args, | |
79 | const UChar *fmt, | |
80 | int32_t *consumed); | |
81 | ||
82 | int32_t | |
83 | u_sscanf_scientific_handler(u_localized_string *input, | |
84 | const u_sscanf_spec_info *info, | |
85 | ufmt_args *args, | |
86 | const UChar *fmt, | |
87 | int32_t *consumed); | |
88 | ||
89 | int32_t | |
90 | u_sscanf_scidbl_handler(u_localized_string *input, | |
91 | const u_sscanf_spec_info *info, | |
92 | ufmt_args *args, | |
93 | const UChar *fmt, | |
94 | int32_t *consumed); | |
95 | ||
96 | int32_t | |
97 | u_sscanf_currency_handler(u_localized_string *input, | |
98 | const u_sscanf_spec_info *info, | |
99 | ufmt_args *args, | |
100 | const UChar *fmt, | |
101 | int32_t *consumed); | |
102 | ||
103 | int32_t | |
104 | u_sscanf_percent_handler(u_localized_string *input, | |
105 | const u_sscanf_spec_info *info, | |
106 | ufmt_args *args, | |
107 | const UChar *fmt, | |
108 | int32_t *consumed); | |
109 | ||
110 | int32_t | |
111 | u_sscanf_date_handler(u_localized_string *input, | |
112 | const u_sscanf_spec_info *info, | |
113 | ufmt_args *args, | |
114 | const UChar *fmt, | |
115 | int32_t *consumed); | |
116 | ||
117 | int32_t | |
118 | u_sscanf_time_handler(u_localized_string *input, | |
119 | const u_sscanf_spec_info *info, | |
120 | ufmt_args *args, | |
121 | const UChar *fmt, | |
122 | int32_t *consumed); | |
123 | ||
124 | int32_t | |
125 | u_sscanf_char_handler(u_localized_string *input, | |
126 | const u_sscanf_spec_info *info, | |
127 | ufmt_args *args, | |
128 | const UChar *fmt, | |
129 | int32_t *consumed); | |
130 | ||
131 | int32_t | |
132 | u_sscanf_uchar_handler(u_localized_string *input, | |
133 | const u_sscanf_spec_info *info, | |
134 | ufmt_args *args, | |
135 | const UChar *fmt, | |
136 | int32_t *consumed); | |
137 | ||
138 | int32_t | |
139 | u_sscanf_spellout_handler(u_localized_string *input, | |
140 | const u_sscanf_spec_info *info, | |
141 | ufmt_args *args, | |
142 | const UChar *fmt, | |
143 | int32_t *consumed); | |
144 | ||
145 | int32_t | |
146 | u_sscanf_hex_handler(u_localized_string *input, | |
147 | const u_sscanf_spec_info *info, | |
148 | ufmt_args *args, | |
149 | const UChar *fmt, | |
150 | int32_t *consumed); | |
151 | ||
152 | int32_t | |
153 | u_sscanf_octal_handler(u_localized_string *input, | |
154 | const u_sscanf_spec_info *info, | |
155 | ufmt_args *args, | |
156 | const UChar *fmt, | |
157 | int32_t *consumed); | |
158 | ||
159 | int32_t | |
160 | u_sscanf_pointer_handler(u_localized_string *input, | |
161 | const u_sscanf_spec_info *info, | |
162 | ufmt_args *args, | |
163 | const UChar *fmt, | |
164 | int32_t *consumed); | |
165 | ||
166 | int32_t | |
167 | u_sscanf_string_handler(u_localized_string *input, | |
168 | const u_sscanf_spec_info *info, | |
169 | ufmt_args *args, | |
170 | const UChar *fmt, | |
171 | int32_t *consumed); | |
172 | ||
173 | int32_t | |
174 | u_sscanf_scanset_handler(u_localized_string *input, | |
175 | const u_sscanf_spec_info *info, | |
176 | ufmt_args *args, | |
177 | const UChar *fmt, | |
178 | int32_t *consumed); | |
179 | ||
180 | /* ANSI style formatting */ | |
181 | /* Use US-ASCII characters only for formatting */ | |
182 | ||
183 | /* % */ | |
184 | #define UFMT_SIMPLE_PERCENT {ufmt_simple_percent, u_sscanf_simple_percent_handler} | |
185 | /* s */ | |
186 | #define UFMT_STRING {ufmt_string, u_sscanf_string_handler} | |
187 | /* c */ | |
188 | #define UFMT_CHAR {ufmt_string, u_sscanf_char_handler} | |
189 | /* d, i */ | |
190 | #define UFMT_INT {ufmt_int, u_sscanf_integer_handler} | |
191 | /* u */ | |
192 | #define UFMT_UINT {ufmt_int, u_sscanf_uinteger_handler} | |
193 | /* o */ | |
194 | #define UFMT_OCTAL {ufmt_int, u_sscanf_octal_handler} | |
195 | /* x, X */ | |
196 | #define UFMT_HEX {ufmt_int, u_sscanf_hex_handler} | |
197 | /* f */ | |
198 | #define UFMT_DOUBLE {ufmt_double, u_sscanf_double_handler} | |
199 | /* e, E */ | |
200 | #define UFMT_SCIENTIFIC {ufmt_double, u_sscanf_scientific_handler} | |
201 | /* g, G */ | |
202 | #define UFMT_SCIDBL {ufmt_double, u_sscanf_scidbl_handler} | |
203 | /* n */ | |
204 | #define UFMT_COUNT {ufmt_count, u_sscanf_count_handler} | |
205 | /* [ */ | |
206 | #define UFMT_SCANSET {ufmt_string, u_sscanf_scanset_handler} /* TODO: Is this also suppose to be ufmt_ustring */ | |
207 | ||
208 | /* non-ANSI extensions */ | |
209 | /* Use US-ASCII characters only for formatting */ | |
210 | ||
211 | /* p */ | |
212 | #define UFMT_POINTER {ufmt_pointer, u_sscanf_pointer_handler} | |
213 | /* D */ | |
214 | #define UFMT_DATE {ufmt_date, u_sscanf_date_handler} | |
215 | /* T */ | |
216 | #define UFMT_TIME {ufmt_date, u_sscanf_time_handler} | |
217 | /* V */ | |
218 | #define UFMT_SPELLOUT {ufmt_double, u_sscanf_spellout_handler} | |
219 | /* P */ | |
220 | #define UFMT_PERCENT {ufmt_double, u_sscanf_percent_handler} | |
221 | /* M */ | |
222 | #define UFMT_CURRENCY {ufmt_double, u_sscanf_currency_handler} | |
223 | /* K */ | |
224 | #define UFMT_UCHAR {ufmt_uchar, u_sscanf_uchar_handler} | |
225 | /* U */ | |
226 | #define UFMT_USTRING {ufmt_ustring, u_sscanf_ustring_handler} | |
227 | ||
228 | ||
229 | #define UFMT_EMPTY {ufmt_empty, NULL} | |
230 | ||
231 | struct u_sscanf_info { | |
232 | enum ufmt_type_info info; | |
233 | u_sscanf_handler handler; | |
234 | }; | |
235 | typedef struct u_sscanf_info u_sscanf_info; | |
236 | ||
237 | /* Use US-ASCII characters only for formatting. Most codepages have | |
238 | characters 20-7F from Unicode. Using any other codepage specific | |
239 | characters will make it very difficult to format the string on | |
240 | non-Unicode machines */ | |
241 | static const u_sscanf_info g_u_sscanf_infos[108] = { | |
242 | /* 0x20 */ | |
243 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
244 | UFMT_EMPTY, UFMT_SIMPLE_PERCENT,UFMT_EMPTY, UFMT_EMPTY, | |
245 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
246 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
247 | ||
248 | /* 0x30 */ | |
249 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
250 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
251 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
252 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
253 | ||
254 | /* 0x40 */ | |
255 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
256 | UFMT_DATE, UFMT_SCIENTIFIC, UFMT_EMPTY, UFMT_SCIDBL, | |
257 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_UCHAR, | |
258 | UFMT_EMPTY, UFMT_CURRENCY, UFMT_EMPTY, UFMT_EMPTY, | |
259 | ||
260 | /* 0x50 */ | |
261 | UFMT_PERCENT, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
262 | UFMT_TIME, UFMT_USTRING, UFMT_SPELLOUT, UFMT_EMPTY, | |
263 | UFMT_HEX, UFMT_EMPTY, UFMT_EMPTY, UFMT_SCANSET, | |
264 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
265 | ||
266 | /* 0x60 */ | |
267 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_CHAR, | |
268 | UFMT_INT, UFMT_SCIENTIFIC, UFMT_DOUBLE, UFMT_SCIDBL, | |
269 | UFMT_EMPTY, UFMT_INT, UFMT_EMPTY, UFMT_EMPTY, | |
270 | UFMT_EMPTY, UFMT_EMPTY, UFMT_COUNT, UFMT_OCTAL, | |
271 | ||
272 | /* 0x70 */ | |
273 | UFMT_POINTER, UFMT_EMPTY, UFMT_EMPTY, UFMT_STRING, | |
274 | UFMT_EMPTY, UFMT_UINT, UFMT_EMPTY, UFMT_EMPTY, | |
275 | UFMT_HEX, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
276 | UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, | |
277 | }; | |
278 | ||
279 | #define USCANF_NUM_FMT_HANDLERS sizeof(g_u_sscanf_infos) | |
280 | ||
281 | /* We do not use handlers for 0-0x1f */ | |
282 | #define USCANF_BASE_FMT_HANDLERS 0x20 | |
283 | ||
284 | int32_t | |
285 | u_sscanf(const UChar *buffer, | |
286 | const char *locale, | |
287 | const char *patternSpecification, | |
288 | ... ) | |
289 | { | |
290 | va_list ap; | |
291 | int32_t converted; | |
292 | ||
293 | va_start(ap, patternSpecification); | |
294 | converted = u_vsscanf(buffer, locale, patternSpecification, ap); | |
295 | va_end(ap); | |
296 | ||
297 | return converted; | |
298 | } | |
299 | ||
300 | int32_t | |
301 | u_sscanf_u(const UChar *buffer, | |
302 | const char *locale, | |
303 | const UChar *patternSpecification, | |
304 | ... ) | |
305 | { | |
306 | va_list ap; | |
307 | int32_t converted; | |
308 | ||
309 | va_start(ap, patternSpecification); | |
310 | converted = u_vsscanf_u(buffer, locale, patternSpecification, ap); | |
311 | va_end(ap); | |
312 | ||
313 | return converted; | |
314 | } | |
315 | ||
316 | U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
317 | u_vsscanf(const UChar *buffer, | |
318 | const char *locale, | |
319 | const char *patternSpecification, | |
320 | va_list ap) | |
321 | { | |
322 | int32_t converted; | |
323 | UChar *pattern; | |
324 | UChar patBuffer[UFMT_DEFAULT_BUFFER_SIZE]; | |
325 | int32_t size = (int32_t)strlen(patternSpecification) + 1; | |
326 | ||
327 | /* convert from the default codepage to Unicode */ | |
328 | if (size >= MAX_UCHAR_BUFFER_SIZE(patBuffer)) { | |
329 | pattern = (UChar *)uprv_malloc(size * sizeof(UChar)); | |
330 | if(pattern == 0) { | |
331 | return 0; | |
332 | } | |
333 | } | |
334 | else { | |
335 | pattern = patBuffer; | |
336 | } | |
337 | ufmt_defaultCPToUnicode(patternSpecification, size, pattern, size); | |
338 | ||
339 | /* do the work */ | |
340 | converted = u_vsscanf_u(buffer, locale, pattern, ap); | |
341 | ||
342 | /* clean up */ | |
343 | if (pattern != patBuffer) { | |
344 | uprv_free(pattern); | |
345 | } | |
346 | ||
347 | return converted; | |
348 | } | |
349 | ||
350 | static int32_t | |
351 | u_sscanf_skip_leading_ws(u_localized_string *input, | |
352 | UChar pad) | |
353 | { | |
354 | UChar c; | |
355 | int32_t count = input->pos; | |
356 | int32_t skipped; | |
357 | ||
358 | /* skip all leading ws in the stream */ | |
359 | while( ((c = input->str[count]) != U_EOF) && (c == pad || u_isWhitespace(c)) ) | |
360 | count++; | |
361 | ||
362 | if(c == U_EOF) | |
363 | count++; | |
364 | ||
365 | skipped = count - input->pos; | |
366 | input->pos = count; | |
367 | return skipped; | |
368 | } | |
369 | ||
370 | int32_t | |
371 | u_sscanf_simple_percent_handler(u_localized_string *input, | |
372 | const u_sscanf_spec_info *info, | |
373 | ufmt_args *args, | |
374 | const UChar *fmt, | |
375 | int32_t *consumed) | |
376 | { | |
377 | /* make sure the next character in the stream is a percent */ | |
378 | if(input->str[input->pos++] != 0x0025) { | |
379 | return -1; | |
380 | } | |
381 | ||
382 | return 0; | |
383 | } | |
384 | ||
385 | int32_t | |
386 | u_sscanf_string_handler(u_localized_string *input, | |
387 | const u_sscanf_spec_info *info, | |
388 | ufmt_args *args, | |
389 | const UChar *fmt, | |
390 | int32_t *consumed) | |
391 | { | |
392 | UChar c; | |
393 | int32_t count; | |
394 | const UChar *source; | |
395 | UConverter *conv; | |
396 | UErrorCode status = U_ZERO_ERROR; | |
397 | char *arg = (char*)(args[0].ptrValue); | |
398 | char *alias = arg; | |
399 | char *limit; | |
400 | ||
401 | /* skip all ws in the stream */ | |
402 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
403 | ||
404 | /* get the string one character at a time, truncating to the width */ | |
405 | count = 0; | |
406 | ||
407 | /* open the default converter */ | |
408 | conv = u_getDefaultConverter(&status); | |
409 | ||
410 | if(U_FAILURE(status)) | |
411 | return -1; | |
412 | ||
413 | while( ((c = input->str[input->pos++]) != U_EOF) | |
414 | && (c != info->fPadChar && !u_isWhitespace(c)) | |
415 | && (info->fWidth == -1 || count < info->fWidth) ) | |
416 | { | |
417 | ||
418 | /* put the character from the stream onto the target */ | |
419 | source = &c; | |
420 | /* Since we do this one character at a time, do it this way. */ | |
421 | limit = alias + ucnv_getMaxCharSize(conv); | |
422 | ||
423 | /* convert the character to the default codepage */ | |
424 | ucnv_fromUnicode(conv, &alias, limit, &source, source + 1, | |
425 | NULL, TRUE, &status); | |
426 | ||
427 | if(U_FAILURE(status)) { | |
428 | /* clean up */ | |
429 | u_releaseDefaultConverter(conv); | |
430 | return -1; | |
431 | } | |
432 | ||
433 | /* increment the count */ | |
434 | ++count; | |
435 | } | |
436 | ||
437 | /* clean up */ | |
438 | u_releaseDefaultConverter(conv); | |
439 | ||
440 | /* put the final character we read back on the stream */ | |
441 | if(c != U_EOF) | |
442 | input->pos--; | |
443 | ||
444 | /* add the terminator */ | |
445 | *alias = 0x00; | |
446 | ||
447 | /* we converted 1 arg */ | |
448 | return 1; | |
449 | } | |
450 | ||
451 | int32_t | |
452 | u_sscanf_ustring_handler(u_localized_string *input, | |
453 | const u_sscanf_spec_info *info, | |
454 | ufmt_args *args, | |
455 | const UChar *fmt, | |
456 | int32_t *consumed) | |
457 | { | |
458 | UChar c; | |
459 | int32_t count; | |
460 | UChar *arg = (UChar*)(args[0].ptrValue); | |
461 | UChar *alias = arg; | |
462 | ||
463 | /* skip all ws in the stream */ | |
464 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
465 | ||
466 | /* get the string one character at a time, truncating to the width */ | |
467 | count = 0; | |
468 | ||
469 | while( ((c = input->str[input->pos++]) != U_EOF) | |
470 | && (c != info->fPadChar && ! u_isWhitespace(c)) | |
471 | && (info->fWidth == -1 || count < info->fWidth) ) | |
472 | { | |
473 | ||
474 | /* put the character from the stream onto the target */ | |
475 | *alias++ = c; | |
476 | ||
477 | /* increment the count */ | |
478 | ++count; | |
479 | } | |
480 | ||
481 | /* put the final character we read back on the stream */ | |
482 | if(c != U_EOF) | |
483 | input->pos--; | |
484 | ||
485 | /* add the terminator */ | |
486 | *alias = 0x0000; | |
487 | ||
488 | /* we converted 1 arg */ | |
489 | return 1; | |
490 | } | |
491 | ||
492 | int32_t | |
493 | u_sscanf_count_handler(u_localized_string *input, | |
494 | const u_sscanf_spec_info *info, | |
495 | ufmt_args *args, | |
496 | const UChar *fmt, | |
497 | int32_t *consumed) | |
498 | { | |
499 | int *converted = (int*)(args[0].ptrValue); | |
500 | ||
501 | /* in the special case of count, the u_sscanf_spec_info's width */ | |
502 | /* will contain the # of items converted thus far */ | |
503 | *converted = info->fWidth; | |
504 | ||
505 | /* we converted 0 args */ | |
506 | return 0; | |
507 | } | |
508 | ||
509 | int32_t | |
510 | u_sscanf_integer_handler(u_localized_string *input, | |
511 | const u_sscanf_spec_info *info, | |
512 | ufmt_args *args, | |
513 | const UChar *fmt, | |
514 | int32_t *consumed) | |
515 | { | |
516 | int32_t len; | |
517 | long *num = (long*) (args[0].ptrValue); | |
518 | UNumberFormat *format; | |
519 | int32_t parsePos = 0; | |
520 | UErrorCode status = U_ZERO_ERROR; | |
521 | ||
522 | ||
523 | /* skip all ws in the stream */ | |
524 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
525 | ||
526 | /* determine the size of the stream's buffer */ | |
527 | len = input->len - input->pos; | |
528 | ||
529 | /* truncate to the width, if specified */ | |
530 | if(info->fWidth != -1) | |
531 | len = ufmt_min(len, info->fWidth); | |
532 | ||
533 | /* get the formatter */ | |
534 | format = u_locbund_getNumberFormat(input->fBundle); | |
535 | ||
536 | /* handle error */ | |
537 | if(format == 0) | |
538 | return 0; | |
539 | ||
540 | /* parse the number */ | |
541 | *num = unum_parse(format, &(input->str[input->pos]), len, &parsePos, &status); | |
542 | ||
543 | /* mask off any necessary bits */ | |
544 | if(info->fIsShort) | |
545 | *num &= UINT16_MAX; | |
546 | else if(! info->fIsLong || ! info->fIsLongLong) | |
547 | *num &= UINT32_MAX; | |
548 | ||
549 | /* update the stream's position to reflect consumed data */ | |
550 | input->pos += parsePos; | |
551 | ||
552 | /* we converted 1 arg */ | |
553 | return 1; | |
554 | } | |
555 | ||
556 | int32_t | |
557 | u_sscanf_uinteger_handler(u_localized_string *input, | |
558 | const u_sscanf_spec_info *info, | |
559 | ufmt_args *args, | |
560 | const UChar *fmt, | |
561 | int32_t *consumed) | |
562 | { | |
563 | ufmt_args uint_args; | |
564 | int32_t converted_args; | |
565 | uint32_t *num = (uint32_t*) (args[0].ptrValue); | |
566 | double currDouble; | |
567 | ||
568 | uint_args.ptrValue = &currDouble; | |
569 | converted_args = u_sscanf_double_handler(input, info, &uint_args, fmt, consumed); | |
570 | ||
571 | *num = (uint32_t)currDouble; | |
572 | ||
573 | return converted_args; | |
574 | } | |
575 | ||
576 | int32_t | |
577 | u_sscanf_double_handler(u_localized_string *input, | |
578 | const u_sscanf_spec_info *info, | |
579 | ufmt_args *args, | |
580 | const UChar *fmt, | |
581 | int32_t *consumed) | |
582 | { | |
583 | int32_t len; | |
584 | double *num = (double*) (args[0].ptrValue); | |
585 | UNumberFormat *format; | |
586 | int32_t parsePos = 0; | |
587 | UErrorCode status = U_ZERO_ERROR; | |
588 | ||
589 | ||
590 | /* skip all ws in the stream */ | |
591 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
592 | ||
593 | /* determine the size of the stream's buffer */ | |
594 | len = input->len - input->pos; | |
595 | ||
596 | /* truncate to the width, if specified */ | |
597 | if(info->fWidth != -1) | |
598 | len = ufmt_min(len, info->fWidth); | |
599 | ||
600 | /* get the formatter */ | |
601 | format = u_locbund_getNumberFormat(input->fBundle); | |
602 | ||
603 | /* handle error */ | |
604 | if(format == 0) | |
605 | return 0; | |
606 | ||
607 | /* parse the number */ | |
608 | *num = unum_parseDouble(format, &(input->str[input->pos]), len, &parsePos, &status); | |
609 | ||
610 | /* mask off any necessary bits */ | |
611 | /* if(! info->fIsLong_double) | |
612 | num &= DBL_MAX;*/ | |
613 | ||
614 | /* update the stream's position to reflect consumed data */ | |
615 | input->pos += parsePos; | |
616 | ||
617 | /* we converted 1 arg */ | |
618 | return 1; | |
619 | } | |
620 | ||
621 | int32_t | |
622 | u_sscanf_scientific_handler(u_localized_string *input, | |
623 | const u_sscanf_spec_info *info, | |
624 | ufmt_args *args, | |
625 | const UChar *fmt, | |
626 | int32_t *consumed) | |
627 | { | |
628 | int32_t len; | |
629 | double *num = (double*) (args[0].ptrValue); | |
630 | UNumberFormat *format; | |
631 | int32_t parsePos = 0; | |
632 | UErrorCode status = U_ZERO_ERROR; | |
633 | ||
634 | ||
635 | /* skip all ws in the stream */ | |
636 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
637 | ||
638 | /* determine the size of the stream's buffer */ | |
639 | len = input->len - input->pos; | |
640 | ||
641 | /* truncate to the width, if specified */ | |
642 | if(info->fWidth != -1) | |
643 | len = ufmt_min(len, info->fWidth); | |
644 | ||
645 | /* get the formatter */ | |
646 | format = u_locbund_getScientificFormat(input->fBundle); | |
647 | ||
648 | /* handle error */ | |
649 | if(format == 0) | |
650 | return 0; | |
651 | ||
652 | /* parse the number */ | |
653 | *num = unum_parseDouble(format, &(input->str[input->pos]), len, &parsePos, &status); | |
654 | ||
655 | /* mask off any necessary bits */ | |
656 | /* if(! info->fIsLong_double) | |
657 | num &= DBL_MAX;*/ | |
658 | ||
659 | /* update the stream's position to reflect consumed data */ | |
660 | input->pos += parsePos; | |
661 | ||
662 | /* we converted 1 arg */ | |
663 | return 1; | |
664 | } | |
665 | ||
666 | int32_t | |
667 | u_sscanf_scidbl_handler(u_localized_string *input, | |
668 | const u_sscanf_spec_info *info, | |
669 | ufmt_args *args, | |
670 | const UChar *fmt, | |
671 | int32_t *consumed) | |
672 | { | |
673 | int32_t len; | |
674 | double *num = (double*) (args[0].ptrValue); | |
675 | UNumberFormat *scientificFormat, *genericFormat; | |
676 | /*int32_t scientificResult, genericResult;*/ | |
677 | double scientificResult, genericResult; | |
678 | int32_t scientificParsePos = 0, genericParsePos = 0; | |
679 | UErrorCode scientificStatus = U_ZERO_ERROR; | |
680 | UErrorCode genericStatus = U_ZERO_ERROR; | |
681 | ||
682 | ||
683 | /* since we can't determine by scanning the characters whether */ | |
684 | /* a number was formatted in the 'f' or 'g' styles, parse the */ | |
685 | /* string with both formatters, and assume whichever one */ | |
686 | /* parsed the most is the correct formatter to use */ | |
687 | ||
688 | ||
689 | /* skip all ws in the stream */ | |
690 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
691 | ||
692 | /* determine the size of the stream's buffer */ | |
693 | len = input->len - input->pos; | |
694 | ||
695 | /* truncate to the width, if specified */ | |
696 | if(info->fWidth != -1) | |
697 | len = ufmt_min(len, info->fWidth); | |
698 | ||
699 | /* get the formatters */ | |
700 | scientificFormat = u_locbund_getScientificFormat(input->fBundle); | |
701 | genericFormat = u_locbund_getNumberFormat(input->fBundle); | |
702 | ||
703 | /* handle error */ | |
704 | if(scientificFormat == 0 || genericFormat == 0) | |
705 | return 0; | |
706 | ||
707 | /* parse the number using each format*/ | |
708 | ||
709 | scientificResult = unum_parseDouble(scientificFormat, &(input->str[input->pos]), len, | |
710 | &scientificParsePos, &scientificStatus); | |
711 | ||
712 | genericResult = unum_parseDouble(genericFormat, &(input->str[input->pos]), len, | |
713 | &genericParsePos, &genericStatus); | |
714 | ||
715 | /* determine which parse made it farther */ | |
716 | if(scientificParsePos > genericParsePos) { | |
717 | /* stash the result in num */ | |
718 | *num = scientificResult; | |
719 | /* update the stream's position to reflect consumed data */ | |
720 | input->pos += scientificParsePos; | |
721 | } | |
722 | else { | |
723 | /* stash the result in num */ | |
724 | *num = genericResult; | |
725 | /* update the stream's position to reflect consumed data */ | |
726 | input->pos += genericParsePos; | |
727 | } | |
728 | ||
729 | /* mask off any necessary bits */ | |
730 | /* if(! info->fIsLong_double) | |
731 | num &= DBL_MAX;*/ | |
732 | ||
733 | /* we converted 1 arg */ | |
734 | return 1; | |
735 | } | |
736 | ||
737 | int32_t | |
738 | u_sscanf_currency_handler(u_localized_string *input, | |
739 | const u_sscanf_spec_info *info, | |
740 | ufmt_args *args, | |
741 | const UChar *fmt, | |
742 | int32_t *consumed) | |
743 | { | |
744 | int32_t len; | |
745 | double *num = (double*) (args[0].ptrValue); | |
746 | UNumberFormat *format; | |
747 | int32_t parsePos = 0; | |
748 | UErrorCode status = U_ZERO_ERROR; | |
749 | ||
750 | ||
751 | /* skip all ws in the stream */ | |
752 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
753 | ||
754 | /* determine the size of the stream's buffer */ | |
755 | len = input->len - input->pos; | |
756 | ||
757 | /* truncate to the width, if specified */ | |
758 | if(info->fWidth != -1) | |
759 | len = ufmt_min(len, info->fWidth); | |
760 | ||
761 | /* get the formatter */ | |
762 | format = u_locbund_getCurrencyFormat(input->fBundle); | |
763 | ||
764 | /* handle error */ | |
765 | if(format == 0) | |
766 | return 0; | |
767 | ||
768 | /* parse the number */ | |
769 | *num = unum_parseDouble(format, &(input->str[input->pos]), len, &parsePos, &status); | |
770 | ||
771 | /* mask off any necessary bits */ | |
772 | /* if(! info->fIsLong_double) | |
773 | num &= DBL_MAX;*/ | |
774 | ||
775 | /* update the stream's position to reflect consumed data */ | |
776 | input->pos += parsePos; | |
777 | ||
778 | /* we converted 1 arg */ | |
779 | return 1; | |
780 | } | |
781 | ||
782 | int32_t | |
783 | u_sscanf_percent_handler(u_localized_string *input, | |
784 | const u_sscanf_spec_info *info, | |
785 | ufmt_args *args, | |
786 | const UChar *fmt, | |
787 | int32_t *consumed) | |
788 | { | |
789 | int32_t len; | |
790 | double *num = (double*) (args[0].ptrValue); | |
791 | UNumberFormat *format; | |
792 | int32_t parsePos = 0; | |
793 | UErrorCode status = U_ZERO_ERROR; | |
794 | ||
795 | ||
796 | /* skip all ws in the stream */ | |
797 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
798 | ||
799 | /* determine the size of the stream's buffer */ | |
800 | len = input->len - input->pos; | |
801 | ||
802 | /* truncate to the width, if specified */ | |
803 | if(info->fWidth != -1) | |
804 | len = ufmt_min(len, info->fWidth); | |
805 | ||
806 | /* get the formatter */ | |
807 | format = u_locbund_getPercentFormat(input->fBundle); | |
808 | ||
809 | /* handle error */ | |
810 | if(format == 0) | |
811 | return 0; | |
812 | ||
813 | /* parse the number */ | |
814 | *num = unum_parseDouble(format, &(input->str[input->pos]), len, &parsePos, &status); | |
815 | ||
816 | /* mask off any necessary bits */ | |
817 | /* if(! info->fIsLong_double) | |
818 | num &= DBL_MAX;*/ | |
819 | ||
820 | /* update the stream's position to reflect consumed data */ | |
821 | input->pos += parsePos; | |
822 | ||
823 | /* we converted 1 arg */ | |
824 | return 1; | |
825 | } | |
826 | ||
827 | int32_t | |
828 | u_sscanf_date_handler(u_localized_string *input, | |
829 | const u_sscanf_spec_info *info, | |
830 | ufmt_args *args, | |
831 | const UChar *fmt, | |
832 | int32_t *consumed) | |
833 | { | |
834 | int32_t len; | |
835 | UDate *date = (UDate*) (args[0].ptrValue); | |
836 | UDateFormat *format; | |
837 | int32_t parsePos = 0; | |
838 | UErrorCode status = U_ZERO_ERROR; | |
839 | ||
840 | ||
841 | /* skip all ws in the stream */ | |
842 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
843 | ||
844 | /* determine the size of the stream's buffer */ | |
845 | len = input->len - input->pos; | |
846 | ||
847 | /* truncate to the width, if specified */ | |
848 | if(info->fWidth != -1) | |
849 | len = ufmt_min(len, info->fWidth); | |
850 | ||
851 | /* get the formatter */ | |
852 | format = u_locbund_getDateFormat(input->fBundle); | |
853 | ||
854 | /* handle error */ | |
855 | if(format == 0) | |
856 | return 0; | |
857 | ||
858 | /* parse the number */ | |
859 | *date = udat_parse(format, &(input->str[input->pos]), len, &parsePos, &status); | |
860 | ||
861 | /* update the stream's position to reflect consumed data */ | |
862 | input->pos += parsePos; | |
863 | ||
864 | /* we converted 1 arg */ | |
865 | return 1; | |
866 | } | |
867 | ||
868 | int32_t | |
869 | u_sscanf_time_handler(u_localized_string *input, | |
870 | const u_sscanf_spec_info *info, | |
871 | ufmt_args *args, | |
872 | const UChar *fmt, | |
873 | int32_t *consumed) | |
874 | { | |
875 | int32_t len; | |
876 | UDate *time = (UDate*) (args[0].ptrValue); | |
877 | UDateFormat *format; | |
878 | int32_t parsePos = 0; | |
879 | UErrorCode status = U_ZERO_ERROR; | |
880 | ||
881 | ||
882 | /* skip all ws in the stream */ | |
883 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
884 | ||
885 | /* determine the size of the stream's buffer */ | |
886 | len = input->len - input->pos; | |
887 | ||
888 | /* truncate to the width, if specified */ | |
889 | if(info->fWidth != -1) | |
890 | len = ufmt_min(len, info->fWidth); | |
891 | ||
892 | /* get the formatter */ | |
893 | format = u_locbund_getTimeFormat(input->fBundle); | |
894 | ||
895 | /* handle error */ | |
896 | if(format == 0) | |
897 | return 0; | |
898 | ||
899 | /* parse the number */ | |
900 | *time = udat_parse(format, &(input->str[input->pos]), len, &parsePos, &status); | |
901 | ||
902 | /* update the stream's position to reflect consumed data */ | |
903 | input->pos += parsePos; | |
904 | ||
905 | /* we converted 1 arg */ | |
906 | return 1; | |
907 | } | |
908 | ||
909 | int32_t | |
910 | u_sscanf_char_handler(u_localized_string *input, | |
911 | const u_sscanf_spec_info *info, | |
912 | ufmt_args *args, | |
913 | const UChar *fmt, | |
914 | int32_t *consumed) | |
915 | { | |
916 | UChar uc = 0; | |
917 | char *result; | |
918 | char *c = (char*)(args[0].ptrValue); | |
919 | ||
920 | /* skip all ws in the stream */ | |
921 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
922 | ||
923 | /* get the character from the stream, truncating to the width */ | |
924 | if(info->fWidth == -1 || info->fWidth > 1) | |
925 | uc = input->str[input->pos++]; | |
926 | ||
927 | /* handle EOF */ | |
928 | if(uc == U_EOF) | |
929 | return -1; | |
930 | ||
931 | /* convert the character to the default codepage */ | |
932 | result = ufmt_unicodeToDefaultCP(&uc, 1); | |
933 | *c = result[0]; | |
934 | ||
935 | /* clean up */ | |
936 | uprv_free(result); | |
937 | ||
938 | /* we converted 1 arg */ | |
939 | return 1; | |
940 | } | |
941 | ||
942 | int32_t | |
943 | u_sscanf_uchar_handler(u_localized_string *input, | |
944 | const u_sscanf_spec_info *info, | |
945 | ufmt_args *args, | |
946 | const UChar *fmt, | |
947 | int32_t *consumed) | |
948 | { | |
949 | UChar *c = (UChar*)(args[0].ptrValue); | |
950 | ||
951 | /* skip all ws in the stream */ | |
952 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
953 | ||
954 | /* get the character from the stream, truncating to the width */ | |
955 | if(info->fWidth == -1 || info->fWidth > 1) | |
956 | *c = input->str[input->pos]; | |
957 | ||
958 | /* handle EOF */ | |
959 | if(*c == U_EOF) | |
960 | return -1; | |
961 | ||
962 | /* we converted 1 arg */ | |
963 | return 1; | |
964 | } | |
965 | ||
966 | int32_t | |
967 | u_sscanf_spellout_handler(u_localized_string *input, | |
968 | const u_sscanf_spec_info *info, | |
969 | ufmt_args *args, | |
970 | const UChar *fmt, | |
971 | int32_t *consumed) | |
972 | { | |
973 | int32_t len; | |
974 | double *num = (double*) (args[0].ptrValue); | |
975 | UNumberFormat *format; | |
976 | int32_t parsePos = 0; | |
977 | UErrorCode status = U_ZERO_ERROR; | |
978 | ||
979 | ||
980 | /* skip all ws in the stream */ | |
981 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
982 | ||
983 | /* determine the size of the stream's buffer */ | |
984 | len = input->len - input->pos; | |
985 | ||
986 | /* truncate to the width, if specified */ | |
987 | if(info->fWidth != -1) | |
988 | len = ufmt_min(len, info->fWidth); | |
989 | ||
990 | /* get the formatter */ | |
991 | format = u_locbund_getSpelloutFormat(input->fBundle); | |
992 | ||
993 | /* handle error */ | |
994 | if(format == 0) | |
995 | return 0; | |
996 | ||
997 | /* parse the number */ | |
998 | *num = unum_parseDouble(format, &(input->str[input->pos]), len, &parsePos, &status); | |
999 | ||
1000 | /* mask off any necessary bits */ | |
1001 | /* if(! info->fIsLong_double) | |
1002 | num &= DBL_MAX;*/ | |
1003 | ||
1004 | /* update the stream's position to reflect consumed data */ | |
1005 | input->pos += parsePos; | |
1006 | ||
1007 | /* we converted 1 arg */ | |
1008 | return 1; | |
1009 | } | |
1010 | ||
1011 | int32_t | |
1012 | u_sscanf_hex_handler(u_localized_string *input, | |
1013 | const u_sscanf_spec_info *info, | |
1014 | ufmt_args *args, | |
1015 | const UChar *fmt, | |
1016 | int32_t *consumed) | |
1017 | { | |
1018 | int32_t len; | |
1019 | long *num = (long*) (args[0].ptrValue); | |
1020 | ||
1021 | ||
1022 | /* skip all ws in the stream */ | |
1023 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
1024 | ||
1025 | /* determine the size of the stream's buffer */ | |
1026 | len = input->len - input->pos; | |
1027 | ||
1028 | /* truncate to the width, if specified */ | |
1029 | if(info->fWidth != -1) | |
1030 | len = ufmt_min(len, info->fWidth); | |
1031 | ||
1032 | /* check for alternate form */ | |
1033 | if( input->str[input->pos] == 0x0030 && | |
1034 | (input->str[input->pos + 1] == 0x0078 || input->str[input->pos + 1] == 0x0058) ) { | |
1035 | ||
1036 | /* skip the '0' and 'x' or 'X' if present */ | |
1037 | input->pos += 2; | |
1038 | len -= 2; | |
1039 | } | |
1040 | ||
1041 | /* parse the number */ | |
1042 | *num = ufmt_utol(&(input->str[input->pos]), &len, 16); | |
1043 | ||
1044 | /* update the stream's position to reflect consumed data */ | |
1045 | input->pos += len; | |
1046 | ||
1047 | /* mask off any necessary bits */ | |
1048 | if(info->fIsShort) | |
1049 | *num &= UINT16_MAX; | |
1050 | else if(! info->fIsLong || ! info->fIsLongLong) | |
1051 | *num &= UINT32_MAX; | |
1052 | ||
1053 | /* we converted 1 arg */ | |
1054 | return 1; | |
1055 | } | |
1056 | ||
1057 | int32_t | |
1058 | u_sscanf_octal_handler(u_localized_string *input, | |
1059 | const u_sscanf_spec_info *info, | |
1060 | ufmt_args *args, | |
1061 | const UChar *fmt, | |
1062 | int32_t *consumed) | |
1063 | { | |
1064 | int32_t len; | |
1065 | long *num = (long*) (args[0].ptrValue); | |
1066 | ||
1067 | ||
1068 | /* skip all ws in the stream */ | |
1069 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
1070 | ||
1071 | /* determine the size of the stream's buffer */ | |
1072 | len = input->len - input->pos; | |
1073 | ||
1074 | /* truncate to the width, if specified */ | |
1075 | if(info->fWidth != -1) | |
1076 | len = ufmt_min(len, info->fWidth); | |
1077 | ||
1078 | /* parse the number */ | |
1079 | *num = ufmt_utol(&(input->str[input->pos]), &len, 8); | |
1080 | ||
1081 | /* update the stream's position to reflect consumed data */ | |
1082 | input->pos += len; | |
1083 | ||
1084 | /* mask off any necessary bits */ | |
1085 | if(info->fIsShort) | |
1086 | *num &= UINT16_MAX; | |
1087 | else if(! info->fIsLong || ! info->fIsLongLong) | |
1088 | *num &= UINT32_MAX; | |
1089 | ||
1090 | /* we converted 1 arg */ | |
1091 | return 1; | |
1092 | } | |
1093 | ||
1094 | int32_t | |
1095 | u_sscanf_pointer_handler(u_localized_string *input, | |
1096 | const u_sscanf_spec_info *info, | |
1097 | ufmt_args *args, | |
1098 | const UChar *fmt, | |
1099 | int32_t *consumed) | |
1100 | { | |
1101 | int32_t len; | |
1102 | void *p = (void*)(args[0].ptrValue); | |
1103 | ||
1104 | ||
1105 | /* skip all ws in the stream */ | |
1106 | u_sscanf_skip_leading_ws(input, info->fPadChar); | |
1107 | ||
1108 | /* determine the size of the stream's buffer */ | |
1109 | len = input->len - input->pos; | |
1110 | ||
1111 | /* truncate to the width, if specified */ | |
1112 | if(info->fWidth != -1) | |
1113 | len = ufmt_min(len, info->fWidth); | |
1114 | ||
1115 | /* parse the pointer - cast to void** to assign to *p */ | |
1116 | *(void**)p = (void*) ufmt_utol(&(input->str[input->pos]), &len, 16); | |
1117 | ||
1118 | /* update the stream's position to reflect consumed data */ | |
1119 | input->pos += len; | |
1120 | ||
1121 | /* we converted 1 arg */ | |
1122 | return 1; | |
1123 | } | |
1124 | ||
1125 | int32_t | |
1126 | u_sscanf_scanset_handler(u_localized_string *input, | |
1127 | const u_sscanf_spec_info *info, | |
1128 | ufmt_args *args, | |
1129 | const UChar *fmt, | |
1130 | int32_t *consumed) | |
1131 | { | |
1132 | u_scanf_scanset scanset; | |
1133 | int32_t len; | |
1134 | UBool success; | |
1135 | UChar c; | |
1136 | UChar *s = (UChar*) (args[0].ptrValue); | |
1137 | UChar *alias, *limit; | |
1138 | ||
1139 | ||
1140 | /* determine the size of the stream's buffer */ | |
1141 | len = input->len - input->pos; | |
1142 | ||
1143 | /* truncate to the width, if specified */ | |
1144 | if(info->fWidth != -1) | |
1145 | len = ufmt_min(len, info->fWidth); | |
1146 | ||
1147 | /* alias the target */ | |
1148 | alias = s; | |
1149 | limit = alias + len; | |
1150 | ||
1151 | /* parse the scanset from the fmt string */ | |
1152 | *consumed = u_strlen(fmt); | |
1153 | success = u_scanf_scanset_init(&scanset, fmt, consumed); | |
1154 | ||
1155 | /* increment consumed by one to eat the final ']' */ | |
1156 | ++(*consumed); | |
1157 | ||
1158 | /* verify that the parse was successful and the converter opened */ | |
1159 | if(! success) | |
1160 | return -1; | |
1161 | ||
1162 | /* grab characters one at a time and make sure they are in the scanset */ | |
1163 | while( (c = input->str[input->pos++]) != U_EOF && alias < limit) { | |
1164 | if(u_scanf_scanset_in(&scanset, c)) { | |
1165 | *(alias++) = c; | |
1166 | } | |
1167 | else { | |
1168 | /* if the character's not in the scanset, break out */ | |
1169 | break; | |
1170 | } | |
1171 | } | |
1172 | ||
1173 | /* put the final character we read back on the stream */ | |
1174 | if(c != U_EOF) | |
1175 | input->pos--; | |
1176 | ||
1177 | /* if we didn't match at least 1 character, fail */ | |
1178 | if(alias == s) | |
1179 | return -1; | |
1180 | /* otherwise, add the terminator */ | |
1181 | else | |
1182 | *alias = 0x00; | |
1183 | ||
1184 | /* we converted 1 arg */ | |
1185 | return 1; | |
1186 | } | |
1187 | ||
1188 | ||
1189 | #define UP_PERCENT 0x0025 | |
1190 | ||
1191 | U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */ | |
1192 | u_vsscanf_u(const UChar *buffer, | |
1193 | const char *locale, | |
1194 | const UChar *patternSpecification, | |
1195 | va_list ap) | |
1196 | { | |
1197 | const UChar *alias; | |
1198 | int32_t count, converted, temp; | |
1199 | uint16_t handlerNum; | |
1200 | ||
1201 | ufmt_args args; | |
1202 | u_localized_string inStr; | |
1203 | u_sscanf_spec spec; | |
1204 | ufmt_type_info info; | |
1205 | u_sscanf_handler handler; | |
1206 | ||
1207 | /* alias the pattern */ | |
1208 | alias = patternSpecification; | |
1209 | ||
1210 | inStr.str = (UChar *)buffer; | |
1211 | inStr.len = u_strlen(buffer); | |
1212 | inStr.pos = 0; | |
1213 | ||
1214 | /* haven't converted anything yet */ | |
1215 | converted = 0; | |
1216 | ||
1217 | /* if locale is 0, use the default */ | |
1218 | if(locale == 0) { | |
1219 | locale = uloc_getDefault(); | |
1220 | } | |
1221 | inStr.fBundle = u_loccache_get(locale); | |
1222 | ||
1223 | if(inStr.fBundle == 0) { | |
1224 | return 0; | |
1225 | } | |
1226 | inStr.fOwnBundle = FALSE; | |
1227 | ||
1228 | /* iterate through the pattern */ | |
1229 | for(;;) { | |
1230 | ||
1231 | /* match any characters up to the next '%' */ | |
1232 | while(*alias != UP_PERCENT && *alias != 0x0000 && inStr.str[inStr.pos++] == *alias) { | |
1233 | alias++; | |
1234 | } | |
1235 | ||
1236 | /* if we aren't at a '%', or if we're at end of string, break*/ | |
1237 | if(*alias != UP_PERCENT || *alias == 0x0000) | |
1238 | break; | |
1239 | ||
1240 | /* parse the specifier */ | |
1241 | count = u_sscanf_parse_spec(alias, &spec); | |
1242 | ||
1243 | /* update the pointer in pattern */ | |
1244 | alias += count; | |
1245 | ||
1246 | /* skip the argument, if necessary */ | |
1247 | if(spec.fSkipArg) | |
1248 | args.ptrValue = va_arg(ap, int*); | |
1249 | ||
1250 | handlerNum = (uint16_t)(spec.fInfo.fSpec - USCANF_BASE_FMT_HANDLERS); | |
1251 | if (handlerNum < USCANF_NUM_FMT_HANDLERS) { | |
1252 | /* query the info function for argument information */ | |
1253 | info = g_u_sscanf_infos[ handlerNum ].info; | |
1254 | if(info > ufmt_simple_percent) { | |
1255 | switch(info) { | |
1256 | ||
1257 | case ufmt_count: | |
1258 | args.intValue = va_arg(ap, int); | |
1259 | /* set the spec's width to the # of items converted */ | |
1260 | spec.fInfo.fWidth = converted; | |
1261 | break; | |
1262 | ||
1263 | case ufmt_char: | |
1264 | case ufmt_uchar: | |
1265 | case ufmt_int: | |
1266 | args.ptrValue = va_arg(ap, int*); | |
1267 | break; | |
1268 | ||
1269 | case ufmt_wchar: | |
1270 | args.ptrValue = va_arg(ap, wchar_t*); | |
1271 | break; | |
1272 | ||
1273 | case ufmt_string: | |
1274 | args.ptrValue = va_arg(ap, char*); | |
1275 | break; | |
1276 | ||
1277 | case ufmt_wstring: | |
1278 | args.ptrValue = va_arg(ap, wchar_t*); | |
1279 | break; | |
1280 | ||
1281 | case ufmt_pointer: | |
1282 | args.ptrValue = va_arg(ap, void*); | |
1283 | break; | |
1284 | ||
1285 | case ufmt_float: | |
1286 | args.ptrValue = va_arg(ap, float*); | |
1287 | break; | |
1288 | ||
1289 | case ufmt_double: | |
1290 | args.ptrValue = va_arg(ap, double*); | |
1291 | break; | |
1292 | ||
1293 | case ufmt_date: | |
1294 | args.ptrValue = va_arg(ap, UDate*); | |
1295 | break; | |
1296 | ||
1297 | case ufmt_ustring: | |
1298 | args.ptrValue = va_arg(ap, UChar*); | |
1299 | break; | |
1300 | ||
1301 | default: | |
1302 | break; /* Should never get here */ | |
1303 | } | |
1304 | } | |
1305 | /* call the handler function */ | |
1306 | handler = g_u_sscanf_infos[ handlerNum ].handler; | |
1307 | if(handler != 0) { | |
1308 | ||
1309 | /* reset count */ | |
1310 | count = 0; | |
1311 | ||
1312 | temp = (*handler)(&inStr, &spec.fInfo, &args, alias, &count); | |
1313 | ||
1314 | /* if the handler encountered an error condition, break */ | |
1315 | if(temp == -1) | |
1316 | break; | |
1317 | ||
1318 | /* add to the # of items converted */ | |
1319 | converted += temp; | |
1320 | ||
1321 | /* update the pointer in pattern */ | |
1322 | alias += count; | |
1323 | } | |
1324 | /* else do nothing */ | |
1325 | } | |
1326 | /* else do nothing */ | |
1327 | ||
1328 | /* just ignore unknown tags */ | |
1329 | } | |
1330 | ||
1331 | /* return # of items converted */ | |
1332 | return converted; | |
1333 | } | |
1334 | ||
1335 | #endif /* #if !UCONFIG_NO_FORMATTING */ |