• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
is_between(int c,int min,int max)20 static inline bool is_between(int c, int min, int max)
21 {
22     return (unsigned)(c - min) <= (unsigned)(max - min);
23 }
24 
is_ws(int c)25 static inline bool is_ws(int c)
26 {
27     return is_between(c, 1, 32);
28 }
29 
is_digit(int c)30 static inline bool is_digit(int c)
31 {
32     return is_between(c, '0', '9');
33 }
34 
is_sep(int c)35 static inline bool is_sep(int c)
36 {
37     return is_ws(c) || c == ',' || c == ';';
38 }
39 
to_hex(int c)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 
is_hex(int c)52 static inline bool is_hex(int c)
53 {
54     return to_hex(c) >= 0;
55 }
56 
skip_ws(const char str[])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 
skip_sep(const char str[])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 
Count(const char str[])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 
Count(const char str[],char separator)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 
FindHex(const char str[],uint32_t * value)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 
FindS32(const char str[],int32_t * value)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 
FindMSec(const char str[],SkMSec * value)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 
FindScalar(const char str[],SkScalar * value)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 
FindScalars(const char str[],SkScalar value[],int count)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 
lookup_str(const char str[],const char ** table,int count)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 
FindBool(const char str[],bool * value)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 
FindList(const char target[],const char list[])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
UnitTest()331 void SkParse::UnitTest()
332 {
333     // !!! additional parse tests go here
334     SkParse::TestColor();
335 }
336 #endif
337