Line data Source code
1 : /*
2 : * Copyright 2006 The Android Open Source Project
3 : *
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 :
9 : #include "SkParse.h"
10 :
11 : #include <stdlib.h>
12 :
13 0 : static inline bool is_between(int c, int min, int max)
14 : {
15 0 : return (unsigned)(c - min) <= (unsigned)(max - min);
16 : }
17 :
18 0 : static inline bool is_ws(int c)
19 : {
20 0 : return is_between(c, 1, 32);
21 : }
22 :
23 0 : static inline bool is_digit(int c)
24 : {
25 0 : return is_between(c, '0', '9');
26 : }
27 :
28 0 : static inline bool is_sep(int c)
29 : {
30 0 : return is_ws(c) || c == ',' || c == ';';
31 : }
32 :
33 0 : static int to_hex(int c)
34 : {
35 0 : if (is_digit(c))
36 0 : return c - '0';
37 :
38 0 : c |= 0x20; // make us lower-case
39 0 : if (is_between(c, 'a', 'f'))
40 0 : return c + 10 - 'a';
41 : else
42 0 : return -1;
43 : }
44 :
45 0 : static inline bool is_hex(int c)
46 : {
47 0 : return to_hex(c) >= 0;
48 : }
49 :
50 0 : static const char* skip_ws(const char str[])
51 : {
52 0 : SkASSERT(str);
53 0 : while (is_ws(*str))
54 0 : str++;
55 0 : return str;
56 : }
57 :
58 0 : static const char* skip_sep(const char str[])
59 : {
60 0 : SkASSERT(str);
61 0 : while (is_sep(*str))
62 0 : str++;
63 0 : return str;
64 : }
65 :
66 0 : int SkParse::Count(const char str[])
67 : {
68 : char c;
69 0 : int count = 0;
70 0 : goto skipLeading;
71 : do {
72 0 : count++;
73 0 : do {
74 0 : if ((c = *str++) == '\0')
75 0 : goto goHome;
76 0 : } while (is_sep(c) == false);
77 : skipLeading:
78 0 : do {
79 0 : if ((c = *str++) == '\0')
80 0 : goto goHome;
81 0 : } while (is_sep(c));
82 : } while (true);
83 : goHome:
84 0 : return count;
85 : }
86 :
87 0 : int SkParse::Count(const char str[], char separator)
88 : {
89 : char c;
90 0 : int count = 0;
91 0 : goto skipLeading;
92 : do {
93 0 : count++;
94 0 : do {
95 0 : if ((c = *str++) == '\0')
96 0 : goto goHome;
97 0 : } while (c != separator);
98 : skipLeading:
99 0 : do {
100 0 : if ((c = *str++) == '\0')
101 0 : goto goHome;
102 0 : } while (c == separator);
103 : } while (true);
104 : goHome:
105 0 : return count;
106 : }
107 :
108 0 : const char* SkParse::FindHex(const char str[], uint32_t* value)
109 : {
110 0 : SkASSERT(str);
111 0 : str = skip_ws(str);
112 :
113 0 : if (!is_hex(*str))
114 0 : return nullptr;
115 :
116 0 : uint32_t n = 0;
117 0 : int max_digits = 8;
118 : int digit;
119 :
120 0 : while ((digit = to_hex(*str)) >= 0)
121 : {
122 0 : if (--max_digits < 0)
123 0 : return nullptr;
124 0 : n = (n << 4) | digit;
125 0 : str += 1;
126 : }
127 :
128 0 : if (*str == 0 || is_ws(*str))
129 : {
130 0 : if (value)
131 0 : *value = n;
132 0 : return str;
133 : }
134 0 : return nullptr;
135 : }
136 :
137 0 : const char* SkParse::FindS32(const char str[], int32_t* value)
138 : {
139 0 : SkASSERT(str);
140 0 : str = skip_ws(str);
141 :
142 0 : int sign = 0;
143 0 : if (*str == '-')
144 : {
145 0 : sign = -1;
146 0 : str += 1;
147 : }
148 :
149 0 : if (!is_digit(*str))
150 0 : return nullptr;
151 :
152 0 : int n = 0;
153 0 : while (is_digit(*str))
154 : {
155 0 : n = 10*n + *str - '0';
156 0 : str += 1;
157 : }
158 0 : if (value)
159 0 : *value = (n ^ sign) - sign;
160 0 : return str;
161 : }
162 :
163 0 : const char* SkParse::FindMSec(const char str[], SkMSec* value)
164 : {
165 0 : SkASSERT(str);
166 0 : str = skip_ws(str);
167 :
168 0 : int sign = 0;
169 0 : if (*str == '-')
170 : {
171 0 : sign = -1;
172 0 : str += 1;
173 : }
174 :
175 0 : if (!is_digit(*str))
176 0 : return nullptr;
177 :
178 0 : int n = 0;
179 0 : while (is_digit(*str))
180 : {
181 0 : n = 10*n + *str - '0';
182 0 : str += 1;
183 : }
184 0 : int remaining10s = 3;
185 0 : if (*str == '.') {
186 0 : str++;
187 0 : while (is_digit(*str))
188 : {
189 0 : n = 10*n + *str - '0';
190 0 : str += 1;
191 0 : if (--remaining10s == 0)
192 0 : break;
193 : }
194 : }
195 0 : while (--remaining10s >= 0)
196 0 : n *= 10;
197 0 : if (value)
198 0 : *value = (n ^ sign) - sign;
199 0 : return str;
200 : }
201 :
202 0 : const char* SkParse::FindScalar(const char str[], SkScalar* value) {
203 0 : SkASSERT(str);
204 0 : str = skip_ws(str);
205 :
206 : char* stop;
207 0 : float v = (float)strtod(str, &stop);
208 0 : if (str == stop) {
209 0 : return nullptr;
210 : }
211 0 : if (value) {
212 0 : *value = v;
213 : }
214 0 : return stop;
215 : }
216 :
217 0 : const char* SkParse::FindScalars(const char str[], SkScalar value[], int count)
218 : {
219 0 : SkASSERT(count >= 0);
220 :
221 0 : if (count > 0)
222 : {
223 : for (;;)
224 : {
225 0 : str = SkParse::FindScalar(str, value);
226 0 : if (--count == 0 || str == nullptr)
227 0 : break;
228 :
229 : // keep going
230 0 : str = skip_sep(str);
231 0 : if (value)
232 0 : value += 1;
233 : }
234 : }
235 0 : return str;
236 : }
237 :
238 0 : static bool lookup_str(const char str[], const char** table, int count)
239 : {
240 0 : while (--count >= 0)
241 0 : if (!strcmp(str, table[count]))
242 0 : return true;
243 0 : return false;
244 : }
245 :
246 0 : bool SkParse::FindBool(const char str[], bool* value)
247 : {
248 : static const char* gYes[] = { "yes", "1", "true" };
249 : static const char* gNo[] = { "no", "0", "false" };
250 :
251 0 : if (lookup_str(str, gYes, SK_ARRAY_COUNT(gYes)))
252 : {
253 0 : if (value) *value = true;
254 0 : return true;
255 : }
256 0 : else if (lookup_str(str, gNo, SK_ARRAY_COUNT(gNo)))
257 : {
258 0 : if (value) *value = false;
259 0 : return true;
260 : }
261 0 : return false;
262 : }
263 :
264 0 : int SkParse::FindList(const char target[], const char list[])
265 : {
266 0 : size_t len = strlen(target);
267 0 : int index = 0;
268 :
269 : for (;;)
270 : {
271 0 : const char* end = strchr(list, ',');
272 : size_t entryLen;
273 :
274 0 : if (end == nullptr) // last entry
275 0 : entryLen = strlen(list);
276 : else
277 0 : entryLen = end - list;
278 :
279 0 : if (entryLen == len && memcmp(target, list, len) == 0)
280 0 : return index;
281 0 : if (end == nullptr)
282 0 : break;
283 :
284 0 : list = end + 1; // skip the ','
285 0 : index += 1;
286 0 : }
287 0 : return -1;
288 : }
289 :
290 : #ifdef SK_SUPPORT_UNITTEST
291 : void SkParse::UnitTest()
292 : {
293 : // !!! additional parse tests go here
294 : SkParse::TestColor();
295 : }
296 : #endif
|