diff options
Diffstat (limited to 'gfx/skia/skia/src/utils/SkParse.cpp')
-rw-r--r-- | gfx/skia/skia/src/utils/SkParse.cpp | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/utils/SkParse.cpp b/gfx/skia/skia/src/utils/SkParse.cpp new file mode 100644 index 0000000000..dce251411a --- /dev/null +++ b/gfx/skia/skia/src/utils/SkParse.cpp @@ -0,0 +1,302 @@ +/* + * 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 "include/core/SkScalar.h" +#include "include/core/SkTypes.h" +#include "include/private/base/SkTo.h" +#include "include/utils/SkParse.h" + +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <limits> +#include <string> + +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 = 1; + int64_t maxAbsValue = std::numeric_limits<int>::max(); + if (*str == '-') + { + sign = -1; + maxAbsValue = -static_cast<int64_t>(std::numeric_limits<int>::min()); + str += 1; + } + + if (!is_digit(*str)) { + return nullptr; + } + + int64_t n = 0; + while (is_digit(*str)) + { + n = 10*n + *str - '0'; + if (n > maxAbsValue) { + return nullptr; + } + + str += 1; + } + if (value) { + *value = SkToS32(sign*n); + } + 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, std::size(gYes))) + { + if (value) *value = true; + return true; + } + else if (lookup_str(str, gNo, std::size(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; +} |