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