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