1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkSVGAttributeParser_DEFINED
9#define SkSVGAttributeParser_DEFINED
10
11#include <vector>
12
13#include "include/private/SkNoncopyable.h"
14#include "modules/svg/include/SkSVGTypes.h"
15#include "src/core/SkTLazy.h"
16
17class SkSVGAttributeParser : public SkNoncopyable {
18public:
19    SkSVGAttributeParser(const char[]);
20
21    bool parseInteger(SkSVGIntegerType*);
22    bool parseViewBox(SkSVGViewBoxType*);
23    bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio*);
24
25    // TODO: Migrate all parse*() functions to this style (and delete the old version)
26    //      so they can be used by parse<T>():
27    bool parse(SkSVGIntegerType* v) { return parseInteger(v); }
28
29    template <typename T> using ParseResult = SkTLazy<T>;
30
31    template <typename T> static ParseResult<T> parse(const char* value) {
32        ParseResult<T> result;
33        T parsedValue;
34        if (SkSVGAttributeParser(value).parse(&parsedValue)) {
35            result.set(std::move(parsedValue));
36        }
37        return result;
38    }
39
40    template <typename T>
41    static ParseResult<T> parse(const char* expectedName,
42                                const char* name,
43                                const char* value) {
44        if (!strcmp(name, expectedName)) {
45            return parse<T>(value);
46        }
47
48        return ParseResult<T>();
49    }
50
51    template <typename PropertyT>
52    static ParseResult<PropertyT> parseProperty(const char* expectedName,
53                                                const char* name,
54                                                const char* value) {
55        if (strcmp(name, expectedName) != 0) {
56            return ParseResult<PropertyT>();
57        }
58
59        if (!strcmp(value, "inherit")) {
60            PropertyT result(SkSVGPropertyState::kInherit);
61            return ParseResult<PropertyT>(&result);
62        }
63
64        auto pr = parse<typename PropertyT::ValueT>(value);
65        if (pr.isValid()) {
66            PropertyT result(*pr);
67            return ParseResult<PropertyT>(&result);
68        }
69
70        return ParseResult<PropertyT>();
71    }
72
73private:
74    // Stack-only
75    void* operator new(size_t) = delete;
76    void* operator new(size_t, void*) = delete;
77
78    template <typename T>
79    bool parse(T*);
80
81    template <typename F>
82    bool advanceWhile(F func);
83
84    bool matchStringToken(const char* token, const char** newPos = nullptr) const;
85
86    bool parseWSToken();
87    bool parseEOSToken();
88    bool parseSepToken();
89    bool parseCommaWspToken();
90    bool parseExpectedStringToken(const char*);
91    bool parseScalarToken(SkScalar*);
92    bool parseInt32Token(int32_t*);
93    bool parseHexToken(uint32_t*);
94    bool parseLengthUnitToken(SkSVGLength::Unit*);
95    bool parseNamedColorToken(SkColor*);
96    bool parseHexColorToken(SkColor*);
97    bool parseColorComponentToken(int32_t*);
98    bool parseRGBColorToken(SkColor*);
99    bool parseFuncIRI(SkSVGFuncIRI*);
100
101    // Transform helpers
102    bool parseMatrixToken(SkMatrix*);
103    bool parseTranslateToken(SkMatrix*);
104    bool parseScaleToken(SkMatrix*);
105    bool parseRotateToken(SkMatrix*);
106    bool parseSkewXToken(SkMatrix*);
107    bool parseSkewYToken(SkMatrix*);
108
109    // Parses a sequence of 'WS* <prefix> WS* (<nested>)', where the nested sequence
110    // is handled by the passed functor.
111    template <typename Func, typename T>
112    bool parseParenthesized(const char* prefix, Func, T* result);
113
114    template <typename T>
115    bool parseList(std::vector<T>*);
116
117    template <typename T, typename TArray>
118    bool parseEnumMap(const TArray& arr, T* result) {
119        for (size_t i = 0; i < SK_ARRAY_COUNT(arr); ++i) {
120            if (this->parseExpectedStringToken(std::get<0>(arr[i]))) {
121                *result = std::get<1>(arr[i]);
122                return true;
123            }
124        }
125        return false;
126    }
127
128    // The current position in the input string.
129    const char* fCurPos;
130
131    using INHERITED = SkNoncopyable;
132};
133
134#endif // SkSVGAttributeParser_DEFINED
135