180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkParse.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_between(int c, int min, int max)
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (unsigned)(c - min) <= (unsigned)(max - min);
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_ws(int c)
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return is_between(c, 1, 32);
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_digit(int c)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return is_between(c, '0', '9');
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_sep(int c)
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return is_ws(c) || c == ',' || c == ';';
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int to_hex(int c)
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (is_digit(c))
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return c - '0';
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    c |= 0x20;  // make us lower-case
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (is_between(c, 'a', 'f'))
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return c + 10 - 'a';
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return -1;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_hex(int c)
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return to_hex(c) >= 0;
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* skip_ws(const char str[])
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_ws(*str))
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str++;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* skip_sep(const char str[])
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_sep(*str))
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str++;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkParse::Count(const char str[])
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char c;
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = 0;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    goto skipLeading;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count++;
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((c = *str++) == '\0')
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto goHome;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (is_sep(c) == false);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruskipLeading:
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((c = *str++) == '\0')
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto goHome;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (is_sep(c));
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (true);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerugoHome:
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return count;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkParse::Count(const char str[], char separator)
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char c;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = 0;
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    goto skipLeading;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count++;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((c = *str++) == '\0')
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto goHome;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (c != separator);
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruskipLeading:
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((c = *str++) == '\0')
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto goHome;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (c == separator);
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (true);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerugoHome:
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return count;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkParse::FindHex(const char str[], uint32_t* value)
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str = skip_ws(str);
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!is_hex(*str))
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t n = 0;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int max_digits = 8;
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int digit;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while ((digit = to_hex(*str)) >= 0)
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (--max_digits < 0)
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = (n << 4) | digit;
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == 0 || is_ws(*str))
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value)
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = n;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return str;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkParse::FindS32(const char str[], int32_t* value)
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str = skip_ws(str);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sign = 0;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == '-')
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sign = -1;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!is_digit(*str))
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int n = 0;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_digit(*str))
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = 10*n + *str - '0';
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value)
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *value = (n ^ sign) - sign;
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkParse::FindMSec(const char str[], SkMSec* value)
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str = skip_ws(str);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sign = 0;
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == '-')
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sign = -1;
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!is_digit(*str))
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int n = 0;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_digit(*str))
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = 10*n + *str - '0';
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int remaining10s = 3;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == '.') {
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str++;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (is_digit(*str))
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = 10*n + *str - '0';
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            str += 1;
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (--remaining10s == 0)
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--remaining10s >= 0)
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n *= 10;
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value)
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *value = (n ^ sign) - sign;
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkParse::FindScalar(const char str[], SkScalar* value) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(str);
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str = skip_ws(str);
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* stop;
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float v = (float)strtod(str, &stop);
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (str == stop) {
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value) {
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *value = v;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return stop;
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sign = 0;
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == '-')
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sign = -1;
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!is_digit(*str) && *str != '.')
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int n = 0;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_digit(*str))
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = 10*n + *str - '0';
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (n > 0x7FFF)
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    n <<= 16;
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (*str == '.')
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static const int gFractions[] = { (1 << 24)  / 10, (1 << 24)  / 100, (1 << 24)  / 1000,
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (1 << 24)  / 10000, (1 << 24)  / 100000 };
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int d = 0;
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const int* fraction = gFractions;
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const int* end = &fraction[SK_ARRAY_COUNT(gFractions)];
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (is_digit(*str) && fraction < end)
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            d += (*str++ - '0') * *fraction++;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        d += 0x80; // round
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n += d >> 8;
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_digit(*str))
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str += 1;
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value)
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = (n ^ sign) - sign;  // apply the sign
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *value = SkFixedToScalar(n);
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkParse::FindScalars(const char str[], SkScalar value[], int count)
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(count >= 0);
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count > 0)
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (;;)
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            str = SkParse::FindScalar(str, value);
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (--count == 0 || str == NULL)
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // keep going
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            str = skip_sep(str);
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (value)
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                value += 1;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool lookup_str(const char str[], const char** table, int count)
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--count >= 0)
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!strcmp(str, table[count]))
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkParse::FindBool(const char str[], bool* value)
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char* gYes[] = { "yes", "1", "true" };
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char* gNo[] = { "no", "0", "false" };
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (lookup_str(str, gYes, SK_ARRAY_COUNT(gYes)))
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) *value = true;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (lookup_str(str, gNo, SK_ARRAY_COUNT(gNo)))
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) *value = false;
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkParse::FindList(const char target[], const char list[])
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t  len = strlen(target);
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int     index = 0;
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;)
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* end = strchr(list, ',');
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t      entryLen;
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (end == NULL) // last entry
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            entryLen = strlen(list);
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        else
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            entryLen = end - list;
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (entryLen == len && memcmp(target, list, len) == 0)
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return index;
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (end == NULL)
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        list = end + 1; // skip the ','
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        index += 1;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return -1;
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SUPPORT_UNITTEST
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkParse::UnitTest()
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // !!! additional parse tests go here
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkParse::TestColor();
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
339