2 ******************************************************************************
4 * Copyright (C) 2000-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 02/08/00 george Creation. Copied from uscanf.c
15 ******************************************************************************
18 #include "unicode/utypes.h"
20 #if !UCONFIG_NO_FORMATTING
22 #include "unicode/uchar.h"
27 #include "unicode/ustdio.h"
28 #include "unicode/ustring.h"
31 #include "unicode/unum.h"
32 #include "unicode/udat.h"
33 #include "unicode/uloc.h"
38 /* --- Prototypes ---------------------------- */
41 u_sscanf_simple_percent_handler(u_localized_string
*input
,
42 const u_sscanf_spec_info
*info
,
48 u_sscanf_ustring_handler(u_localized_string
*input
,
49 const u_sscanf_spec_info
*info
,
55 u_sscanf_count_handler(u_localized_string
*input
,
56 const u_sscanf_spec_info
*info
,
62 u_sscanf_integer_handler(u_localized_string
*input
,
63 const u_sscanf_spec_info
*info
,
69 u_sscanf_uinteger_handler(u_localized_string
*input
,
70 const u_sscanf_spec_info
*info
,
76 u_sscanf_double_handler(u_localized_string
*input
,
77 const u_sscanf_spec_info
*info
,
83 u_sscanf_scientific_handler(u_localized_string
*input
,
84 const u_sscanf_spec_info
*info
,
90 u_sscanf_scidbl_handler(u_localized_string
*input
,
91 const u_sscanf_spec_info
*info
,
97 u_sscanf_currency_handler(u_localized_string
*input
,
98 const u_sscanf_spec_info
*info
,
104 u_sscanf_percent_handler(u_localized_string
*input
,
105 const u_sscanf_spec_info
*info
,
111 u_sscanf_date_handler(u_localized_string
*input
,
112 const u_sscanf_spec_info
*info
,
118 u_sscanf_time_handler(u_localized_string
*input
,
119 const u_sscanf_spec_info
*info
,
125 u_sscanf_char_handler(u_localized_string
*input
,
126 const u_sscanf_spec_info
*info
,
132 u_sscanf_uchar_handler(u_localized_string
*input
,
133 const u_sscanf_spec_info
*info
,
139 u_sscanf_spellout_handler(u_localized_string
*input
,
140 const u_sscanf_spec_info
*info
,
146 u_sscanf_hex_handler(u_localized_string
*input
,
147 const u_sscanf_spec_info
*info
,
153 u_sscanf_octal_handler(u_localized_string
*input
,
154 const u_sscanf_spec_info
*info
,
160 u_sscanf_pointer_handler(u_localized_string
*input
,
161 const u_sscanf_spec_info
*info
,
167 u_sscanf_string_handler(u_localized_string
*input
,
168 const u_sscanf_spec_info
*info
,
174 u_sscanf_scanset_handler(u_localized_string
*input
,
175 const u_sscanf_spec_info
*info
,
180 /* ANSI style formatting */
181 /* Use US-ASCII characters only for formatting */
184 #define UFMT_SIMPLE_PERCENT {ufmt_simple_percent, u_sscanf_simple_percent_handler}
186 #define UFMT_STRING {ufmt_string, u_sscanf_string_handler}
188 #define UFMT_CHAR {ufmt_string, u_sscanf_char_handler}
190 #define UFMT_INT {ufmt_int, u_sscanf_integer_handler}
192 #define UFMT_UINT {ufmt_int, u_sscanf_uinteger_handler}
194 #define UFMT_OCTAL {ufmt_int, u_sscanf_octal_handler}
196 #define UFMT_HEX {ufmt_int, u_sscanf_hex_handler}
198 #define UFMT_DOUBLE {ufmt_double, u_sscanf_double_handler}
200 #define UFMT_SCIENTIFIC {ufmt_double, u_sscanf_scientific_handler}
202 #define UFMT_SCIDBL {ufmt_double, u_sscanf_scidbl_handler}
204 #define UFMT_COUNT {ufmt_count, u_sscanf_count_handler}
206 #define UFMT_SCANSET {ufmt_string, u_sscanf_scanset_handler} /* TODO: Is this also suppose to be ufmt_ustring */
208 /* non-ANSI extensions */
209 /* Use US-ASCII characters only for formatting */
212 #define UFMT_POINTER {ufmt_pointer, u_sscanf_pointer_handler}
214 #define UFMT_DATE {ufmt_date, u_sscanf_date_handler}
216 #define UFMT_TIME {ufmt_date, u_sscanf_time_handler}
218 #define UFMT_SPELLOUT {ufmt_double, u_sscanf_spellout_handler}
220 #define UFMT_PERCENT {ufmt_double, u_sscanf_percent_handler}
222 #define UFMT_CURRENCY {ufmt_double, u_sscanf_currency_handler}
224 #define UFMT_UCHAR {ufmt_uchar, u_sscanf_uchar_handler}
226 #define UFMT_USTRING {ufmt_ustring, u_sscanf_ustring_handler}
229 #define UFMT_EMPTY {ufmt_empty, NULL}
231 struct u_sscanf_info
{
232 enum ufmt_type_info info
;
233 u_sscanf_handler handler
;
235 typedef struct u_sscanf_info u_sscanf_info
;
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] = {
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
,
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
,
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
,
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
,
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
,
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
,
279 #define USCANF_NUM_FMT_HANDLERS sizeof(g_u_sscanf_infos)
281 /* We do not use handlers for 0-0x1f */
282 #define USCANF_BASE_FMT_HANDLERS 0x20
285 u_sscanf(const UChar
*buffer
,
287 const char *patternSpecification
,
293 va_start(ap
, patternSpecification
);
294 converted
= u_vsscanf(buffer
, locale
, patternSpecification
, ap
);
301 u_sscanf_u(const UChar
*buffer
,
303 const UChar
*patternSpecification
,
309 va_start(ap
, patternSpecification
);
310 converted
= u_vsscanf_u(buffer
, locale
, patternSpecification
, ap
);
316 U_CAPI
int32_t U_EXPORT2
/* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
317 u_vsscanf(const UChar
*buffer
,
319 const char *patternSpecification
,
324 UChar patBuffer
[UFMT_DEFAULT_BUFFER_SIZE
];
325 int32_t size
= (int32_t)strlen(patternSpecification
) + 1;
327 /* convert from the default codepage to Unicode */
328 if (size
>= MAX_UCHAR_BUFFER_SIZE(patBuffer
)) {
329 pattern
= (UChar
*)uprv_malloc(size
* sizeof(UChar
));
337 ufmt_defaultCPToUnicode(patternSpecification
, size
, pattern
, size
);
340 converted
= u_vsscanf_u(buffer
, locale
, pattern
, ap
);
343 if (pattern
!= patBuffer
) {
351 u_sscanf_skip_leading_ws(u_localized_string
*input
,
355 int32_t count
= input
->pos
;
358 /* skip all leading ws in the stream */
359 while( ((c
= input
->str
[count
]) != U_EOF
) && (c
== pad
|| u_isWhitespace(c
)) )
365 skipped
= count
- input
->pos
;
371 u_sscanf_simple_percent_handler(u_localized_string
*input
,
372 const u_sscanf_spec_info
*info
,
377 /* make sure the next character in the stream is a percent */
378 if(input
->str
[input
->pos
++] != 0x0025) {
386 u_sscanf_string_handler(u_localized_string
*input
,
387 const u_sscanf_spec_info
*info
,
396 UErrorCode status
= U_ZERO_ERROR
;
397 char *arg
= (char*)(args
[0].ptrValue
);
401 /* skip all ws in the stream */
402 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
404 /* get the string one character at a time, truncating to the width */
407 /* open the default converter */
408 conv
= u_getDefaultConverter(&status
);
410 if(U_FAILURE(status
))
413 while( ((c
= input
->str
[input
->pos
++]) != U_EOF
)
414 && (c
!= info
->fPadChar
&& !u_isWhitespace(c
))
415 && (info
->fWidth
== -1 || count
< info
->fWidth
) )
418 /* put the character from the stream onto the target */
420 /* Since we do this one character at a time, do it this way. */
421 limit
= alias
+ ucnv_getMaxCharSize(conv
);
423 /* convert the character to the default codepage */
424 ucnv_fromUnicode(conv
, &alias
, limit
, &source
, source
+ 1,
425 NULL
, TRUE
, &status
);
427 if(U_FAILURE(status
)) {
429 u_releaseDefaultConverter(conv
);
433 /* increment the count */
438 u_releaseDefaultConverter(conv
);
440 /* put the final character we read back on the stream */
444 /* add the terminator */
447 /* we converted 1 arg */
452 u_sscanf_ustring_handler(u_localized_string
*input
,
453 const u_sscanf_spec_info
*info
,
460 UChar
*arg
= (UChar
*)(args
[0].ptrValue
);
463 /* skip all ws in the stream */
464 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
466 /* get the string one character at a time, truncating to the width */
469 while( ((c
= input
->str
[input
->pos
++]) != U_EOF
)
470 && (c
!= info
->fPadChar
&& ! u_isWhitespace(c
))
471 && (info
->fWidth
== -1 || count
< info
->fWidth
) )
474 /* put the character from the stream onto the target */
477 /* increment the count */
481 /* put the final character we read back on the stream */
485 /* add the terminator */
488 /* we converted 1 arg */
493 u_sscanf_count_handler(u_localized_string
*input
,
494 const u_sscanf_spec_info
*info
,
499 int *converted
= (int*)(args
[0].ptrValue
);
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
;
505 /* we converted 0 args */
510 u_sscanf_integer_handler(u_localized_string
*input
,
511 const u_sscanf_spec_info
*info
,
517 long *num
= (long*) (args
[0].ptrValue
);
518 UNumberFormat
*format
;
519 int32_t parsePos
= 0;
520 UErrorCode status
= U_ZERO_ERROR
;
523 /* skip all ws in the stream */
524 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
526 /* determine the size of the stream's buffer */
527 len
= input
->len
- input
->pos
;
529 /* truncate to the width, if specified */
530 if(info
->fWidth
!= -1)
531 len
= ufmt_min(len
, info
->fWidth
);
533 /* get the formatter */
534 format
= u_locbund_getNumberFormat(input
->fBundle
);
540 /* parse the number */
541 *num
= unum_parse(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
543 /* mask off any necessary bits */
546 else if(! info
->fIsLong
|| ! info
->fIsLongLong
)
549 /* update the stream's position to reflect consumed data */
550 input
->pos
+= parsePos
;
552 /* we converted 1 arg */
557 u_sscanf_uinteger_handler(u_localized_string
*input
,
558 const u_sscanf_spec_info
*info
,
564 int32_t converted_args
;
565 uint32_t *num
= (uint32_t*) (args
[0].ptrValue
);
568 uint_args
.ptrValue
= &currDouble
;
569 converted_args
= u_sscanf_double_handler(input
, info
, &uint_args
, fmt
, consumed
);
571 *num
= (uint32_t)currDouble
;
573 return converted_args
;
577 u_sscanf_double_handler(u_localized_string
*input
,
578 const u_sscanf_spec_info
*info
,
584 double *num
= (double*) (args
[0].ptrValue
);
585 UNumberFormat
*format
;
586 int32_t parsePos
= 0;
587 UErrorCode status
= U_ZERO_ERROR
;
590 /* skip all ws in the stream */
591 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
593 /* determine the size of the stream's buffer */
594 len
= input
->len
- input
->pos
;
596 /* truncate to the width, if specified */
597 if(info
->fWidth
!= -1)
598 len
= ufmt_min(len
, info
->fWidth
);
600 /* get the formatter */
601 format
= u_locbund_getNumberFormat(input
->fBundle
);
607 /* parse the number */
608 *num
= unum_parseDouble(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
610 /* mask off any necessary bits */
611 /* if(! info->fIsLong_double)
614 /* update the stream's position to reflect consumed data */
615 input
->pos
+= parsePos
;
617 /* we converted 1 arg */
622 u_sscanf_scientific_handler(u_localized_string
*input
,
623 const u_sscanf_spec_info
*info
,
629 double *num
= (double*) (args
[0].ptrValue
);
630 UNumberFormat
*format
;
631 int32_t parsePos
= 0;
632 UErrorCode status
= U_ZERO_ERROR
;
635 /* skip all ws in the stream */
636 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
638 /* determine the size of the stream's buffer */
639 len
= input
->len
- input
->pos
;
641 /* truncate to the width, if specified */
642 if(info
->fWidth
!= -1)
643 len
= ufmt_min(len
, info
->fWidth
);
645 /* get the formatter */
646 format
= u_locbund_getScientificFormat(input
->fBundle
);
652 /* parse the number */
653 *num
= unum_parseDouble(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
655 /* mask off any necessary bits */
656 /* if(! info->fIsLong_double)
659 /* update the stream's position to reflect consumed data */
660 input
->pos
+= parsePos
;
662 /* we converted 1 arg */
667 u_sscanf_scidbl_handler(u_localized_string
*input
,
668 const u_sscanf_spec_info
*info
,
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
;
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 */
689 /* skip all ws in the stream */
690 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
692 /* determine the size of the stream's buffer */
693 len
= input
->len
- input
->pos
;
695 /* truncate to the width, if specified */
696 if(info
->fWidth
!= -1)
697 len
= ufmt_min(len
, info
->fWidth
);
699 /* get the formatters */
700 scientificFormat
= u_locbund_getScientificFormat(input
->fBundle
);
701 genericFormat
= u_locbund_getNumberFormat(input
->fBundle
);
704 if(scientificFormat
== 0 || genericFormat
== 0)
707 /* parse the number using each format*/
709 scientificResult
= unum_parseDouble(scientificFormat
, &(input
->str
[input
->pos
]), len
,
710 &scientificParsePos
, &scientificStatus
);
712 genericResult
= unum_parseDouble(genericFormat
, &(input
->str
[input
->pos
]), len
,
713 &genericParsePos
, &genericStatus
);
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
;
723 /* stash the result in num */
724 *num
= genericResult
;
725 /* update the stream's position to reflect consumed data */
726 input
->pos
+= genericParsePos
;
729 /* mask off any necessary bits */
730 /* if(! info->fIsLong_double)
733 /* we converted 1 arg */
738 u_sscanf_currency_handler(u_localized_string
*input
,
739 const u_sscanf_spec_info
*info
,
745 double *num
= (double*) (args
[0].ptrValue
);
746 UNumberFormat
*format
;
747 int32_t parsePos
= 0;
748 UErrorCode status
= U_ZERO_ERROR
;
751 /* skip all ws in the stream */
752 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
754 /* determine the size of the stream's buffer */
755 len
= input
->len
- input
->pos
;
757 /* truncate to the width, if specified */
758 if(info
->fWidth
!= -1)
759 len
= ufmt_min(len
, info
->fWidth
);
761 /* get the formatter */
762 format
= u_locbund_getCurrencyFormat(input
->fBundle
);
768 /* parse the number */
769 *num
= unum_parseDouble(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
771 /* mask off any necessary bits */
772 /* if(! info->fIsLong_double)
775 /* update the stream's position to reflect consumed data */
776 input
->pos
+= parsePos
;
778 /* we converted 1 arg */
783 u_sscanf_percent_handler(u_localized_string
*input
,
784 const u_sscanf_spec_info
*info
,
790 double *num
= (double*) (args
[0].ptrValue
);
791 UNumberFormat
*format
;
792 int32_t parsePos
= 0;
793 UErrorCode status
= U_ZERO_ERROR
;
796 /* skip all ws in the stream */
797 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
799 /* determine the size of the stream's buffer */
800 len
= input
->len
- input
->pos
;
802 /* truncate to the width, if specified */
803 if(info
->fWidth
!= -1)
804 len
= ufmt_min(len
, info
->fWidth
);
806 /* get the formatter */
807 format
= u_locbund_getPercentFormat(input
->fBundle
);
813 /* parse the number */
814 *num
= unum_parseDouble(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
816 /* mask off any necessary bits */
817 /* if(! info->fIsLong_double)
820 /* update the stream's position to reflect consumed data */
821 input
->pos
+= parsePos
;
823 /* we converted 1 arg */
828 u_sscanf_date_handler(u_localized_string
*input
,
829 const u_sscanf_spec_info
*info
,
835 UDate
*date
= (UDate
*) (args
[0].ptrValue
);
837 int32_t parsePos
= 0;
838 UErrorCode status
= U_ZERO_ERROR
;
841 /* skip all ws in the stream */
842 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
844 /* determine the size of the stream's buffer */
845 len
= input
->len
- input
->pos
;
847 /* truncate to the width, if specified */
848 if(info
->fWidth
!= -1)
849 len
= ufmt_min(len
, info
->fWidth
);
851 /* get the formatter */
852 format
= u_locbund_getDateFormat(input
->fBundle
);
858 /* parse the number */
859 *date
= udat_parse(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
861 /* update the stream's position to reflect consumed data */
862 input
->pos
+= parsePos
;
864 /* we converted 1 arg */
869 u_sscanf_time_handler(u_localized_string
*input
,
870 const u_sscanf_spec_info
*info
,
876 UDate
*time
= (UDate
*) (args
[0].ptrValue
);
878 int32_t parsePos
= 0;
879 UErrorCode status
= U_ZERO_ERROR
;
882 /* skip all ws in the stream */
883 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
885 /* determine the size of the stream's buffer */
886 len
= input
->len
- input
->pos
;
888 /* truncate to the width, if specified */
889 if(info
->fWidth
!= -1)
890 len
= ufmt_min(len
, info
->fWidth
);
892 /* get the formatter */
893 format
= u_locbund_getTimeFormat(input
->fBundle
);
899 /* parse the number */
900 *time
= udat_parse(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
902 /* update the stream's position to reflect consumed data */
903 input
->pos
+= parsePos
;
905 /* we converted 1 arg */
910 u_sscanf_char_handler(u_localized_string
*input
,
911 const u_sscanf_spec_info
*info
,
918 char *c
= (char*)(args
[0].ptrValue
);
920 /* skip all ws in the stream */
921 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
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
++];
931 /* convert the character to the default codepage */
932 result
= ufmt_unicodeToDefaultCP(&uc
, 1);
938 /* we converted 1 arg */
943 u_sscanf_uchar_handler(u_localized_string
*input
,
944 const u_sscanf_spec_info
*info
,
949 UChar
*c
= (UChar
*)(args
[0].ptrValue
);
951 /* skip all ws in the stream */
952 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
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
];
962 /* we converted 1 arg */
967 u_sscanf_spellout_handler(u_localized_string
*input
,
968 const u_sscanf_spec_info
*info
,
974 double *num
= (double*) (args
[0].ptrValue
);
975 UNumberFormat
*format
;
976 int32_t parsePos
= 0;
977 UErrorCode status
= U_ZERO_ERROR
;
980 /* skip all ws in the stream */
981 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
983 /* determine the size of the stream's buffer */
984 len
= input
->len
- input
->pos
;
986 /* truncate to the width, if specified */
987 if(info
->fWidth
!= -1)
988 len
= ufmt_min(len
, info
->fWidth
);
990 /* get the formatter */
991 format
= u_locbund_getSpelloutFormat(input
->fBundle
);
997 /* parse the number */
998 *num
= unum_parseDouble(format
, &(input
->str
[input
->pos
]), len
, &parsePos
, &status
);
1000 /* mask off any necessary bits */
1001 /* if(! info->fIsLong_double)
1004 /* update the stream's position to reflect consumed data */
1005 input
->pos
+= parsePos
;
1007 /* we converted 1 arg */
1012 u_sscanf_hex_handler(u_localized_string
*input
,
1013 const u_sscanf_spec_info
*info
,
1019 long *num
= (long*) (args
[0].ptrValue
);
1022 /* skip all ws in the stream */
1023 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
1025 /* determine the size of the stream's buffer */
1026 len
= input
->len
- input
->pos
;
1028 /* truncate to the width, if specified */
1029 if(info
->fWidth
!= -1)
1030 len
= ufmt_min(len
, info
->fWidth
);
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) ) {
1036 /* skip the '0' and 'x' or 'X' if present */
1041 /* parse the number */
1042 *num
= ufmt_utol(&(input
->str
[input
->pos
]), &len
, 16);
1044 /* update the stream's position to reflect consumed data */
1047 /* mask off any necessary bits */
1050 else if(! info
->fIsLong
|| ! info
->fIsLongLong
)
1053 /* we converted 1 arg */
1058 u_sscanf_octal_handler(u_localized_string
*input
,
1059 const u_sscanf_spec_info
*info
,
1065 long *num
= (long*) (args
[0].ptrValue
);
1068 /* skip all ws in the stream */
1069 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
1071 /* determine the size of the stream's buffer */
1072 len
= input
->len
- input
->pos
;
1074 /* truncate to the width, if specified */
1075 if(info
->fWidth
!= -1)
1076 len
= ufmt_min(len
, info
->fWidth
);
1078 /* parse the number */
1079 *num
= ufmt_utol(&(input
->str
[input
->pos
]), &len
, 8);
1081 /* update the stream's position to reflect consumed data */
1084 /* mask off any necessary bits */
1087 else if(! info
->fIsLong
|| ! info
->fIsLongLong
)
1090 /* we converted 1 arg */
1095 u_sscanf_pointer_handler(u_localized_string
*input
,
1096 const u_sscanf_spec_info
*info
,
1102 void *p
= (void*)(args
[0].ptrValue
);
1105 /* skip all ws in the stream */
1106 u_sscanf_skip_leading_ws(input
, info
->fPadChar
);
1108 /* determine the size of the stream's buffer */
1109 len
= input
->len
- input
->pos
;
1111 /* truncate to the width, if specified */
1112 if(info
->fWidth
!= -1)
1113 len
= ufmt_min(len
, info
->fWidth
);
1115 /* parse the pointer - cast to void** to assign to *p */
1116 *(void**)p
= (void*) ufmt_utol(&(input
->str
[input
->pos
]), &len
, 16);
1118 /* update the stream's position to reflect consumed data */
1121 /* we converted 1 arg */
1126 u_sscanf_scanset_handler(u_localized_string
*input
,
1127 const u_sscanf_spec_info
*info
,
1132 u_scanf_scanset scanset
;
1136 UChar
*s
= (UChar
*) (args
[0].ptrValue
);
1137 UChar
*alias
, *limit
;
1140 /* determine the size of the stream's buffer */
1141 len
= input
->len
- input
->pos
;
1143 /* truncate to the width, if specified */
1144 if(info
->fWidth
!= -1)
1145 len
= ufmt_min(len
, info
->fWidth
);
1147 /* alias the target */
1149 limit
= alias
+ len
;
1151 /* parse the scanset from the fmt string */
1152 *consumed
= u_strlen(fmt
);
1153 success
= u_scanf_scanset_init(&scanset
, fmt
, consumed
);
1155 /* increment consumed by one to eat the final ']' */
1158 /* verify that the parse was successful and the converter opened */
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
)) {
1168 /* if the character's not in the scanset, break out */
1173 /* put the final character we read back on the stream */
1177 /* if we didn't match at least 1 character, fail */
1180 /* otherwise, add the terminator */
1184 /* we converted 1 arg */
1189 #define UP_PERCENT 0x0025
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
,
1194 const UChar
*patternSpecification
,
1198 int32_t count
, converted
, temp
;
1199 uint16_t handlerNum
;
1202 u_localized_string inStr
;
1204 ufmt_type_info info
;
1205 u_sscanf_handler handler
;
1207 /* alias the pattern */
1208 alias
= patternSpecification
;
1210 inStr
.str
= (UChar
*)buffer
;
1211 inStr
.len
= u_strlen(buffer
);
1214 /* haven't converted anything yet */
1217 /* if locale is 0, use the default */
1219 locale
= uloc_getDefault();
1221 inStr
.fBundle
= u_loccache_get(locale
);
1223 if(inStr
.fBundle
== 0) {
1226 inStr
.fOwnBundle
= FALSE
;
1228 /* iterate through the pattern */
1231 /* match any characters up to the next '%' */
1232 while(*alias
!= UP_PERCENT
&& *alias
!= 0x0000 && inStr
.str
[inStr
.pos
++] == *alias
) {
1236 /* if we aren't at a '%', or if we're at end of string, break*/
1237 if(*alias
!= UP_PERCENT
|| *alias
== 0x0000)
1240 /* parse the specifier */
1241 count
= u_sscanf_parse_spec(alias
, &spec
);
1243 /* update the pointer in pattern */
1246 /* skip the argument, if necessary */
1248 args
.ptrValue
= va_arg(ap
, int*);
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
) {
1258 args
.intValue
= va_arg(ap
, int);
1259 /* set the spec's width to the # of items converted */
1260 spec
.fInfo
.fWidth
= converted
;
1266 args
.ptrValue
= va_arg(ap
, int*);
1270 args
.ptrValue
= va_arg(ap
, wchar_t*);
1274 args
.ptrValue
= va_arg(ap
, char*);
1278 args
.ptrValue
= va_arg(ap
, wchar_t*);
1282 args
.ptrValue
= va_arg(ap
, void*);
1286 args
.ptrValue
= va_arg(ap
, float*);
1290 args
.ptrValue
= va_arg(ap
, double*);
1294 args
.ptrValue
= va_arg(ap
, UDate
*);
1298 args
.ptrValue
= va_arg(ap
, UChar
*);
1302 break; /* Should never get here */
1305 /* call the handler function */
1306 handler
= g_u_sscanf_infos
[ handlerNum
].handler
;
1312 temp
= (*handler
)(&inStr
, &spec
.fInfo
, &args
, alias
, &count
);
1314 /* if the handler encountered an error condition, break */
1318 /* add to the # of items converted */
1321 /* update the pointer in pattern */
1324 /* else do nothing */
1326 /* else do nothing */
1328 /* just ignore unknown tags */
1331 /* return # of items converted */
1335 #endif /* #if !UCONFIG_NO_FORMATTING */