]> git.saurik.com Git - apple/icu.git/blob - icuSources/extra/ustdio/sscanf_p.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / extra / ustdio / sscanf_p.c
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 2000-2001, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 ******************************************************************************
8 *
9 * File sscnnf_p.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 02/08/00 george Creation. Copied from uscnnf_p.h
15 ******************************************************************************
16 */
17
18 #include "unicode/utypes.h"
19
20 #if !UCONFIG_NO_FORMATTING
21
22 #include "sscanf_p.h"
23 #include "ufmt_cmn.h"
24
25 /* flag characters for u_scanf */
26 #define FLAG_ASTERISK 0x002A
27 #define FLAG_PAREN 0x0028
28
29 #define ISFLAG(s) (s) == FLAG_ASTERISK || \
30 (s) == FLAG_PAREN
31
32 /* special characters for u_scanf */
33 #define SPEC_DOLLARSIGN 0x0024
34
35 /* unicode digits */
36 #define DIGIT_ZERO 0x0030
37 #define DIGIT_ONE 0x0031
38 #define DIGIT_TWO 0x0032
39 #define DIGIT_THREE 0x0033
40 #define DIGIT_FOUR 0x0034
41 #define DIGIT_FIVE 0x0035
42 #define DIGIT_SIX 0x0036
43 #define DIGIT_SEVEN 0x0037
44 #define DIGIT_EIGHT 0x0038
45 #define DIGIT_NINE 0x0039
46
47 #define ISDIGIT(s) (s) == DIGIT_ZERO || \
48 (s) == DIGIT_ONE || \
49 (s) == DIGIT_TWO || \
50 (s) == DIGIT_THREE || \
51 (s) == DIGIT_FOUR || \
52 (s) == DIGIT_FIVE || \
53 (s) == DIGIT_SIX || \
54 (s) == DIGIT_SEVEN || \
55 (s) == DIGIT_EIGHT || \
56 (s) == DIGIT_NINE
57
58 /* u_scanf modifiers */
59 #define MOD_H 0x0068
60 #define MOD_LOWERL 0x006C
61 #define MOD_L 0x004C
62
63 #define ISMOD(s) (s) == MOD_H || \
64 (s) == MOD_LOWERL || \
65 (s) == MOD_L
66
67 /* We parse the argument list in Unicode */
68 int32_t
69 u_sscanf_parse_spec (const UChar *fmt,
70 u_sscanf_spec *spec)
71 {
72 const UChar *s = fmt;
73 const UChar *backup;
74 u_sscanf_spec_info *info = &(spec->fInfo);
75
76 /* initialize spec to default values */
77 spec->fArgPos = -1;
78 spec->fSkipArg = FALSE;
79
80 info->fSpec = 0x0000;
81 info->fWidth = -1;
82 info->fPadChar = 0x0020;
83 info->fIsLongDouble = FALSE;
84 info->fIsShort = FALSE;
85 info->fIsLong = FALSE;
86 info->fIsLongLong = FALSE;
87
88
89 /* skip over the initial '%' */
90 s++;
91
92 /* Check for positional argument */
93 if(ISDIGIT(*s)) {
94
95 /* Save the current position */
96 backup = s;
97
98 /* handle positional parameters */
99 if(ISDIGIT(*s)) {
100 spec->fArgPos = (int) (*s++ - DIGIT_ZERO);
101
102 while(ISDIGIT(*s)) {
103 spec->fArgPos *= 10;
104 spec->fArgPos += (int) (*s++ - DIGIT_ZERO);
105 }
106 }
107
108 /* if there is no '$', don't read anything */
109 if(*s != SPEC_DOLLARSIGN) {
110 spec->fArgPos = -1;
111 s = backup;
112 }
113 /* munge the '$' */
114 else
115 s++;
116 }
117
118 /* Get any format flags */
119 while(ISFLAG(*s)) {
120 switch(*s++) {
121
122 /* skip argument */
123 case FLAG_ASTERISK:
124 spec->fSkipArg = TRUE;
125 break;
126
127 /* pad character specified */
128 case FLAG_PAREN:
129
130 /* first four characters are hex values for pad char */
131 info->fPadChar = (UChar)ufmt_digitvalue(*s++);
132 info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
133 info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
134 info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
135
136 /* final character is ignored */
137 s++;
138
139 break;
140 }
141 }
142
143 /* Get the width */
144 if(ISDIGIT(*s)){
145 info->fWidth = (int) (*s++ - DIGIT_ZERO);
146
147 while(ISDIGIT(*s)) {
148 info->fWidth *= 10;
149 info->fWidth += (int) (*s++ - DIGIT_ZERO);
150 }
151 }
152
153 /* Get any modifiers */
154 if(ISMOD(*s)) {
155 switch(*s++) {
156
157 /* short */
158 case MOD_H:
159 info->fIsShort = TRUE;
160 break;
161
162 /* long or long long */
163 case MOD_LOWERL:
164 if(*s == MOD_LOWERL) {
165 info->fIsLongLong = TRUE;
166 /* skip over the next 'l' */
167 s++;
168 }
169 else
170 info->fIsLong = TRUE;
171 break;
172
173 /* long double */
174 case MOD_L:
175 info->fIsLongDouble = TRUE;
176 break;
177 }
178 }
179
180 /* finally, get the specifier letter */
181 info->fSpec = *s++;
182
183 /* return # of characters in this specifier */
184 return (int32_t)(s - fmt);
185 }
186
187 #endif /* #if !UCONFIG_NO_FORMATTING */