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 12 static inline bool is_between(int c, int min, int max) 13 { 14 return (unsigned)(c - min) <= (unsigned)(max - min); 15 } 16 17 static inline bool is_ws(int c) 18 { 19 return is_between(c, 1, 32); 20 } 21 22 static inline bool is_digit(int c) 23 { 24 return is_between(c, '0', '9'); 25 } 26 27 static inline bool is_sep(int c) 28 { 29 return is_ws(c) || c == ',' || c == ';'; 30 } 31 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 44 static inline bool is_hex(int c) 45 { 46 return to_hex(c) >= 0; 47 } 48 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 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 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 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 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 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 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 201 const char* SkParse::FindScalar(const char str[], SkScalar* value) { 202 SkASSERT(str); 203 str = skip_ws(str); 204 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 } 215 216 const char* SkParse::FindScalars(const char str[], SkScalar value[], int count) 217 { 218 SkASSERT(count >= 0); 219 220 if (count > 0) 221 { 222 for (;;) 223 { 224 str = SkParse::FindScalar(str, value); 225 if (--count == 0 || str == NULL) 226 break; 227 228 // keep going 229 str = skip_sep(str); 230 if (value) 231 value += 1; 232 } 233 } 234 return str; 235 } 236 237 static bool lookup_str(const char str[], const char** table, int count) 238 { 239 while (--count >= 0) 240 if (!strcmp(str, table[count])) 241 return true; 242 return false; 243 } 244 245 bool SkParse::FindBool(const char str[], bool* value) 246 { 247 static const char* gYes[] = { "yes", "1", "true" }; 248 static const char* gNo[] = { "no", "0", "false" }; 249 250 if (lookup_str(str, gYes, SK_ARRAY_COUNT(gYes))) 251 { 252 if (value) *value = true; 253 return true; 254 } 255 else if (lookup_str(str, gNo, SK_ARRAY_COUNT(gNo))) 256 { 257 if (value) *value = false; 258 return true; 259 } 260 return false; 261 } 262 263 int SkParse::FindList(const char target[], const char list[]) 264 { 265 size_t len = strlen(target); 266 int index = 0; 267 268 for (;;) 269 { 270 const char* end = strchr(list, ','); 271 size_t entryLen; 272 273 if (end == NULL) // last entry 274 entryLen = strlen(list); 275 else 276 entryLen = end - list; 277 278 if (entryLen == len && memcmp(target, list, len) == 0) 279 return index; 280 if (end == NULL) 281 break; 282 283 list = end + 1; // skip the ',' 284 index += 1; 285 } 286 return -1; 287 } 288 289 #ifdef SK_SUPPORT_UNITTEST 290 void SkParse::UnitTest() 291 { 292 // !!! additional parse tests go here 293 SkParse::TestColor(); 294 } 295 #endif 296