9d524f22bf
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1842753002 Review URL: https://codereview.chromium.org/1842753002
297 lines
5.4 KiB
C++
297 lines
5.4 KiB
C++
/*
|
|
* Copyright 2006 The Android Open Source Project
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
#include "SkParse.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
static inline bool is_between(int c, int min, int max)
|
|
{
|
|
return (unsigned)(c - min) <= (unsigned)(max - min);
|
|
}
|
|
|
|
static inline bool is_ws(int c)
|
|
{
|
|
return is_between(c, 1, 32);
|
|
}
|
|
|
|
static inline bool is_digit(int c)
|
|
{
|
|
return is_between(c, '0', '9');
|
|
}
|
|
|
|
static inline bool is_sep(int c)
|
|
{
|
|
return is_ws(c) || c == ',' || c == ';';
|
|
}
|
|
|
|
static int to_hex(int c)
|
|
{
|
|
if (is_digit(c))
|
|
return c - '0';
|
|
|
|
c |= 0x20; // make us lower-case
|
|
if (is_between(c, 'a', 'f'))
|
|
return c + 10 - 'a';
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static inline bool is_hex(int c)
|
|
{
|
|
return to_hex(c) >= 0;
|
|
}
|
|
|
|
static const char* skip_ws(const char str[])
|
|
{
|
|
SkASSERT(str);
|
|
while (is_ws(*str))
|
|
str++;
|
|
return str;
|
|
}
|
|
|
|
static const char* skip_sep(const char str[])
|
|
{
|
|
SkASSERT(str);
|
|
while (is_sep(*str))
|
|
str++;
|
|
return str;
|
|
}
|
|
|
|
int SkParse::Count(const char str[])
|
|
{
|
|
char c;
|
|
int count = 0;
|
|
goto skipLeading;
|
|
do {
|
|
count++;
|
|
do {
|
|
if ((c = *str++) == '\0')
|
|
goto goHome;
|
|
} while (is_sep(c) == false);
|
|
skipLeading:
|
|
do {
|
|
if ((c = *str++) == '\0')
|
|
goto goHome;
|
|
} while (is_sep(c));
|
|
} while (true);
|
|
goHome:
|
|
return count;
|
|
}
|
|
|
|
int SkParse::Count(const char str[], char separator)
|
|
{
|
|
char c;
|
|
int count = 0;
|
|
goto skipLeading;
|
|
do {
|
|
count++;
|
|
do {
|
|
if ((c = *str++) == '\0')
|
|
goto goHome;
|
|
} while (c != separator);
|
|
skipLeading:
|
|
do {
|
|
if ((c = *str++) == '\0')
|
|
goto goHome;
|
|
} while (c == separator);
|
|
} while (true);
|
|
goHome:
|
|
return count;
|
|
}
|
|
|
|
const char* SkParse::FindHex(const char str[], uint32_t* value)
|
|
{
|
|
SkASSERT(str);
|
|
str = skip_ws(str);
|
|
|
|
if (!is_hex(*str))
|
|
return nullptr;
|
|
|
|
uint32_t n = 0;
|
|
int max_digits = 8;
|
|
int digit;
|
|
|
|
while ((digit = to_hex(*str)) >= 0)
|
|
{
|
|
if (--max_digits < 0)
|
|
return nullptr;
|
|
n = (n << 4) | digit;
|
|
str += 1;
|
|
}
|
|
|
|
if (*str == 0 || is_ws(*str))
|
|
{
|
|
if (value)
|
|
*value = n;
|
|
return str;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const char* SkParse::FindS32(const char str[], int32_t* value)
|
|
{
|
|
SkASSERT(str);
|
|
str = skip_ws(str);
|
|
|
|
int sign = 0;
|
|
if (*str == '-')
|
|
{
|
|
sign = -1;
|
|
str += 1;
|
|
}
|
|
|
|
if (!is_digit(*str))
|
|
return nullptr;
|
|
|
|
int n = 0;
|
|
while (is_digit(*str))
|
|
{
|
|
n = 10*n + *str - '0';
|
|
str += 1;
|
|
}
|
|
if (value)
|
|
*value = (n ^ sign) - sign;
|
|
return str;
|
|
}
|
|
|
|
const char* SkParse::FindMSec(const char str[], SkMSec* value)
|
|
{
|
|
SkASSERT(str);
|
|
str = skip_ws(str);
|
|
|
|
int sign = 0;
|
|
if (*str == '-')
|
|
{
|
|
sign = -1;
|
|
str += 1;
|
|
}
|
|
|
|
if (!is_digit(*str))
|
|
return nullptr;
|
|
|
|
int n = 0;
|
|
while (is_digit(*str))
|
|
{
|
|
n = 10*n + *str - '0';
|
|
str += 1;
|
|
}
|
|
int remaining10s = 3;
|
|
if (*str == '.') {
|
|
str++;
|
|
while (is_digit(*str))
|
|
{
|
|
n = 10*n + *str - '0';
|
|
str += 1;
|
|
if (--remaining10s == 0)
|
|
break;
|
|
}
|
|
}
|
|
while (--remaining10s >= 0)
|
|
n *= 10;
|
|
if (value)
|
|
*value = (n ^ sign) - sign;
|
|
return str;
|
|
}
|
|
|
|
const char* SkParse::FindScalar(const char str[], SkScalar* value) {
|
|
SkASSERT(str);
|
|
str = skip_ws(str);
|
|
|
|
char* stop;
|
|
float v = (float)strtod(str, &stop);
|
|
if (str == stop) {
|
|
return nullptr;
|
|
}
|
|
if (value) {
|
|
*value = v;
|
|
}
|
|
return stop;
|
|
}
|
|
|
|
const char* SkParse::FindScalars(const char str[], SkScalar value[], int count)
|
|
{
|
|
SkASSERT(count >= 0);
|
|
|
|
if (count > 0)
|
|
{
|
|
for (;;)
|
|
{
|
|
str = SkParse::FindScalar(str, value);
|
|
if (--count == 0 || str == nullptr)
|
|
break;
|
|
|
|
// keep going
|
|
str = skip_sep(str);
|
|
if (value)
|
|
value += 1;
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
static bool lookup_str(const char str[], const char** table, int count)
|
|
{
|
|
while (--count >= 0)
|
|
if (!strcmp(str, table[count]))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool SkParse::FindBool(const char str[], bool* value)
|
|
{
|
|
static const char* gYes[] = { "yes", "1", "true" };
|
|
static const char* gNo[] = { "no", "0", "false" };
|
|
|
|
if (lookup_str(str, gYes, SK_ARRAY_COUNT(gYes)))
|
|
{
|
|
if (value) *value = true;
|
|
return true;
|
|
}
|
|
else if (lookup_str(str, gNo, SK_ARRAY_COUNT(gNo)))
|
|
{
|
|
if (value) *value = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int SkParse::FindList(const char target[], const char list[])
|
|
{
|
|
size_t len = strlen(target);
|
|
int index = 0;
|
|
|
|
for (;;)
|
|
{
|
|
const char* end = strchr(list, ',');
|
|
size_t entryLen;
|
|
|
|
if (end == nullptr) // last entry
|
|
entryLen = strlen(list);
|
|
else
|
|
entryLen = end - list;
|
|
|
|
if (entryLen == len && memcmp(target, list, len) == 0)
|
|
return index;
|
|
if (end == nullptr)
|
|
break;
|
|
|
|
list = end + 1; // skip the ','
|
|
index += 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#ifdef SK_SUPPORT_UNITTEST
|
|
void SkParse::UnitTest()
|
|
{
|
|
// !!! additional parse tests go here
|
|
SkParse::TestColor();
|
|
}
|
|
#endif
|