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