]> git.saurik.com Git - apple/icu.git/blob - icuSources/extra/ustdio/sscanf.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / extra / ustdio / sscanf.c
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 */