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