| 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 |