OLD | NEW |
| (Empty) |
1 /* libs/graphics/xml/SkParse.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkParse.h" | |
19 | |
20 static inline bool is_between(int c, int min, int max) | |
21 { | |
22 return (unsigned)(c - min) <= (unsigned)(max - min); | |
23 } | |
24 | |
25 static inline bool is_ws(int c) | |
26 { | |
27 return is_between(c, 1, 32); | |
28 } | |
29 | |
30 static inline bool is_digit(int c) | |
31 { | |
32 return is_between(c, '0', '9'); | |
33 } | |
34 | |
35 static inline bool is_sep(int c) | |
36 { | |
37 return is_ws(c) || c == ',' || c == ';'; | |
38 } | |
39 | |
40 static int to_hex(int c) | |
41 { | |
42 if (is_digit(c)) | |
43 return c - '0'; | |
44 | |
45 c |= 0x20; // make us lower-case | |
46 if (is_between(c, 'a', 'f')) | |
47 return c + 10 - 'a'; | |
48 else | |
49 return -1; | |
50 } | |
51 | |
52 static inline bool is_hex(int c) | |
53 { | |
54 return to_hex(c) >= 0; | |
55 } | |
56 | |
57 static const char* skip_ws(const char str[]) | |
58 { | |
59 SkASSERT(str); | |
60 while (is_ws(*str)) | |
61 str++; | |
62 return str; | |
63 } | |
64 | |
65 static const char* skip_sep(const char str[]) | |
66 { | |
67 SkASSERT(str); | |
68 while (is_sep(*str)) | |
69 str++; | |
70 return str; | |
71 } | |
72 | |
73 int SkParse::Count(const char str[]) | |
74 { | |
75 char c; | |
76 int count = 0; | |
77 goto skipLeading; | |
78 do { | |
79 count++; | |
80 do { | |
81 if ((c = *str++) == '\0') | |
82 goto goHome; | |
83 } while (is_sep(c) == false); | |
84 skipLeading: | |
85 do { | |
86 if ((c = *str++) == '\0') | |
87 goto goHome; | |
88 } while (is_sep(c)); | |
89 } while (true); | |
90 goHome: | |
91 return count; | |
92 } | |
93 | |
94 int SkParse::Count(const char str[], char separator) | |
95 { | |
96 char c; | |
97 int count = 0; | |
98 goto skipLeading; | |
99 do { | |
100 count++; | |
101 do { | |
102 if ((c = *str++) == '\0') | |
103 goto goHome; | |
104 } while (c != separator); | |
105 skipLeading: | |
106 do { | |
107 if ((c = *str++) == '\0') | |
108 goto goHome; | |
109 } while (c == separator); | |
110 } while (true); | |
111 goHome: | |
112 return count; | |
113 } | |
114 | |
115 const char* SkParse::FindHex(const char str[], uint32_t* value) | |
116 { | |
117 SkASSERT(str); | |
118 str = skip_ws(str); | |
119 | |
120 if (!is_hex(*str)) | |
121 return NULL; | |
122 | |
123 uint32_t n = 0; | |
124 int max_digits = 8; | |
125 int digit; | |
126 | |
127 while ((digit = to_hex(*str)) >= 0) | |
128 { | |
129 if (--max_digits < 0) | |
130 return NULL; | |
131 n = (n << 4) | digit; | |
132 str += 1; | |
133 } | |
134 | |
135 if (*str == 0 || is_ws(*str)) | |
136 { | |
137 if (value) | |
138 *value = n; | |
139 return str; | |
140 } | |
141 return false; | |
142 } | |
143 | |
144 const char* SkParse::FindS32(const char str[], int32_t* value) | |
145 { | |
146 SkASSERT(str); | |
147 str = skip_ws(str); | |
148 | |
149 int sign = 0; | |
150 if (*str == '-') | |
151 { | |
152 sign = -1; | |
153 str += 1; | |
154 } | |
155 | |
156 if (!is_digit(*str)) | |
157 return NULL; | |
158 | |
159 int n = 0; | |
160 while (is_digit(*str)) | |
161 { | |
162 n = 10*n + *str - '0'; | |
163 str += 1; | |
164 } | |
165 if (value) | |
166 *value = (n ^ sign) - sign; | |
167 return str; | |
168 } | |
169 | |
170 const char* SkParse::FindMSec(const char str[], SkMSec* value) | |
171 { | |
172 SkASSERT(str); | |
173 str = skip_ws(str); | |
174 | |
175 int sign = 0; | |
176 if (*str == '-') | |
177 { | |
178 sign = -1; | |
179 str += 1; | |
180 } | |
181 | |
182 if (!is_digit(*str)) | |
183 return NULL; | |
184 | |
185 int n = 0; | |
186 while (is_digit(*str)) | |
187 { | |
188 n = 10*n + *str - '0'; | |
189 str += 1; | |
190 } | |
191 int remaining10s = 3; | |
192 if (*str == '.') { | |
193 str++; | |
194 while (is_digit(*str)) | |
195 { | |
196 n = 10*n + *str - '0'; | |
197 str += 1; | |
198 if (--remaining10s == 0) | |
199 break; | |
200 } | |
201 } | |
202 while (--remaining10s >= 0) | |
203 n *= 10; | |
204 if (value) | |
205 *value = (n ^ sign) - sign; | |
206 return str; | |
207 } | |
208 | |
209 const char* SkParse::FindScalar(const char str[], SkScalar* value) | |
210 { | |
211 SkASSERT(str); | |
212 str = skip_ws(str); | |
213 | |
214 int sign = 0; | |
215 if (*str == '-') | |
216 { | |
217 sign = -1; | |
218 str += 1; | |
219 } | |
220 | |
221 if (!is_digit(*str) && *str != '.') | |
222 return NULL; | |
223 | |
224 int n = 0; | |
225 while (is_digit(*str)) | |
226 { | |
227 n = 10*n + *str - '0'; | |
228 if (n > 0x7FFF) | |
229 return NULL; | |
230 str += 1; | |
231 } | |
232 n <<= 16; | |
233 | |
234 if (*str == '.') | |
235 { | |
236 static const int gFractions[] = { (1 << 24) / 10, (1 << 24) / 100, (1
<< 24) / 1000, | |
237 (1 << 24) / 10000, (1 << 24) / 100000 }; | |
238 str += 1; | |
239 int d = 0; | |
240 const int* fraction = gFractions; | |
241 const int* end = &fraction[SK_ARRAY_COUNT(gFractions)]; | |
242 while (is_digit(*str) && fraction < end) | |
243 d += (*str++ - '0') * *fraction++; | |
244 d += 0x80; // round | |
245 n += d >> 8; | |
246 } | |
247 while (is_digit(*str)) | |
248 str += 1; | |
249 if (value) | |
250 { | |
251 n = (n ^ sign) - sign; // apply the sign | |
252 *value = SkFixedToScalar(n); | |
253 } | |
254 return str; | |
255 } | |
256 | |
257 const char* SkParse::FindScalars(const char str[], SkScalar value[], int count) | |
258 { | |
259 SkASSERT(count >= 0); | |
260 | |
261 if (count > 0) | |
262 { | |
263 for (;;) | |
264 { | |
265 str = SkParse::FindScalar(str, value); | |
266 if (--count == 0 || str == NULL) | |
267 break; | |
268 | |
269 // keep going | |
270 str = skip_sep(str); | |
271 if (value) | |
272 value += 1; | |
273 } | |
274 } | |
275 return str; | |
276 } | |
277 | |
278 static bool lookup_str(const char str[], const char** table, int count) | |
279 { | |
280 while (--count >= 0) | |
281 if (!strcmp(str, table[count])) | |
282 return true; | |
283 return false; | |
284 } | |
285 | |
286 bool SkParse::FindBool(const char str[], bool* value) | |
287 { | |
288 static const char* gYes[] = { "yes", "1", "true" }; | |
289 static const char* gNo[] = { "no", "0", "false" }; | |
290 | |
291 if (lookup_str(str, gYes, SK_ARRAY_COUNT(gYes))) | |
292 { | |
293 if (value) *value = true; | |
294 return true; | |
295 } | |
296 else if (lookup_str(str, gNo, SK_ARRAY_COUNT(gNo))) | |
297 { | |
298 if (value) *value = false; | |
299 return true; | |
300 } | |
301 return false; | |
302 } | |
303 | |
304 int SkParse::FindList(const char target[], const char list[]) | |
305 { | |
306 size_t len = strlen(target); | |
307 int index = 0; | |
308 | |
309 for (;;) | |
310 { | |
311 const char* end = strchr(list, ','); | |
312 size_t entryLen; | |
313 | |
314 if (end == NULL) // last entry | |
315 entryLen = strlen(list); | |
316 else | |
317 entryLen = end - list; | |
318 | |
319 if (entryLen == len && memcmp(target, list, len) == 0) | |
320 return index; | |
321 if (end == NULL) | |
322 break; | |
323 | |
324 list = end + 1; // skip the ',' | |
325 index += 1; | |
326 } | |
327 return -1; | |
328 } | |
329 | |
330 #ifdef SK_SUPPORT_UNITTEST | |
331 void SkParse::UnitTest() | |
332 { | |
333 // !!! additional parse tests go here | |
334 SkParse::TestColor(); | |
335 } | |
336 #endif | |
OLD | NEW |