1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci* Copyright 2019 Google LLC
3cb93a386Sopenharmony_ci*
4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci* found in the LICENSE file.
6cb93a386Sopenharmony_ci*/
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef SkParticleSerialization_DEFINED
9cb93a386Sopenharmony_ci#define SkParticleSerialization_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "modules/particles/include/SkReflected.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include "include/core/SkString.h"
14cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
15cb93a386Sopenharmony_ci#include "src/utils/SkJSON.h"
16cb93a386Sopenharmony_ci#include "src/utils/SkJSONWriter.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ciclass SkToJsonVisitor : public SkFieldVisitor {
19cb93a386Sopenharmony_cipublic:
20cb93a386Sopenharmony_ci    SkToJsonVisitor(SkJSONWriter& writer) : fWriter(writer) {}
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci    // Primitives
23cb93a386Sopenharmony_ci    void visit(const char* name, float& f) override {
24cb93a386Sopenharmony_ci        fWriter.appendFloat(name, f);
25cb93a386Sopenharmony_ci    }
26cb93a386Sopenharmony_ci    void visit(const char* name, int& i) override {
27cb93a386Sopenharmony_ci        fWriter.appendS32(name, i);
28cb93a386Sopenharmony_ci    }
29cb93a386Sopenharmony_ci    void visit(const char* name, bool& b) override {
30cb93a386Sopenharmony_ci        fWriter.appendBool(name, b);
31cb93a386Sopenharmony_ci    }
32cb93a386Sopenharmony_ci    void visit(const char* name, SkString& s) override {
33cb93a386Sopenharmony_ci        if (s.contains('\n')) {
34cb93a386Sopenharmony_ci            SkTArray<SkString> lines;
35cb93a386Sopenharmony_ci            SkStrSplit(s.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
36cb93a386Sopenharmony_ci            fWriter.beginArray(name);
37cb93a386Sopenharmony_ci            for (const auto& line : lines) {
38cb93a386Sopenharmony_ci                fWriter.appendString(line.c_str());
39cb93a386Sopenharmony_ci            }
40cb93a386Sopenharmony_ci            fWriter.endArray();
41cb93a386Sopenharmony_ci        } else {
42cb93a386Sopenharmony_ci            fWriter.appendString(name, s.c_str());
43cb93a386Sopenharmony_ci        }
44cb93a386Sopenharmony_ci    }
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    // Compound types
47cb93a386Sopenharmony_ci    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
48cb93a386Sopenharmony_ci        fWriter.appendString("Type", e ? e->getType()->fName : "Null");
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    void enterObject(const char* name) override { fWriter.beginObject(name); }
52cb93a386Sopenharmony_ci    void exitObject()                  override { fWriter.endObject(); }
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    int enterArray(const char* name, int oldCount) override {
55cb93a386Sopenharmony_ci        fWriter.beginArray(name);
56cb93a386Sopenharmony_ci        return oldCount;
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci    ArrayEdit exitArray() override {
59cb93a386Sopenharmony_ci        fWriter.endArray();
60cb93a386Sopenharmony_ci        return ArrayEdit();
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ciprivate:
64cb93a386Sopenharmony_ci    SkJSONWriter& fWriter;
65cb93a386Sopenharmony_ci};
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ciclass SkFromJsonVisitor : public SkFieldVisitor {
68cb93a386Sopenharmony_cipublic:
69cb93a386Sopenharmony_ci    SkFromJsonVisitor(const skjson::Value& v) : fRoot(v) {
70cb93a386Sopenharmony_ci        fStack.push_back(&fRoot);
71cb93a386Sopenharmony_ci    }
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    void visit(const char* name, float& f) override {
74cb93a386Sopenharmony_ci        TryParse(get(name), f);
75cb93a386Sopenharmony_ci    }
76cb93a386Sopenharmony_ci    void visit(const char* name, int& i) override {
77cb93a386Sopenharmony_ci        TryParse(get(name), i);
78cb93a386Sopenharmony_ci    }
79cb93a386Sopenharmony_ci    void visit(const char* name, bool& b) override {
80cb93a386Sopenharmony_ci        TryParse(get(name), b);
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci    void visit(const char* name, SkString& s) override {
83cb93a386Sopenharmony_ci        if (const skjson::ArrayValue* lines = get(name)) {
84cb93a386Sopenharmony_ci            s.reset();
85cb93a386Sopenharmony_ci            bool first = true;
86cb93a386Sopenharmony_ci            for (const skjson::StringValue* line : *lines) {
87cb93a386Sopenharmony_ci                if (line) {
88cb93a386Sopenharmony_ci                    if (!first) {
89cb93a386Sopenharmony_ci                        s.append("\n");
90cb93a386Sopenharmony_ci                    }
91cb93a386Sopenharmony_ci                    s.append(line->begin(), line->size());
92cb93a386Sopenharmony_ci                    first = false;
93cb93a386Sopenharmony_ci                }
94cb93a386Sopenharmony_ci            }
95cb93a386Sopenharmony_ci        } else {
96cb93a386Sopenharmony_ci            TryParse(get(name), s);
97cb93a386Sopenharmony_ci        }
98cb93a386Sopenharmony_ci    }
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
101cb93a386Sopenharmony_ci        const skjson::StringValue* typeString = get("Type");
102cb93a386Sopenharmony_ci        const char* type = typeString ? typeString->begin() : "Null";
103cb93a386Sopenharmony_ci        e = SkReflected::CreateInstance(type);
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    void enterObject(const char* name) override {
107cb93a386Sopenharmony_ci        fStack.push_back((const skjson::ObjectValue*)get(name));
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci    void exitObject() override {
110cb93a386Sopenharmony_ci        fStack.pop_back();
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    int enterArray(const char* name, int oldCount) override {
114cb93a386Sopenharmony_ci        const skjson::ArrayValue* arrVal = get(name);
115cb93a386Sopenharmony_ci        fStack.push_back(arrVal);
116cb93a386Sopenharmony_ci        fArrayIndexStack.push_back(0);
117cb93a386Sopenharmony_ci        return arrVal ? arrVal->size() : 0;
118cb93a386Sopenharmony_ci    }
119cb93a386Sopenharmony_ci    ArrayEdit exitArray() override {
120cb93a386Sopenharmony_ci        fStack.pop_back();
121cb93a386Sopenharmony_ci        fArrayIndexStack.pop_back();
122cb93a386Sopenharmony_ci        return ArrayEdit();
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ciprivate:
126cb93a386Sopenharmony_ci    const skjson::Value& get(const char* name) {
127cb93a386Sopenharmony_ci        if (const skjson::Value* cur = fStack.back()) {
128cb93a386Sopenharmony_ci            if (cur->is<skjson::ArrayValue>()) {
129cb93a386Sopenharmony_ci                SkASSERT(!name);
130cb93a386Sopenharmony_ci                return cur->as<skjson::ArrayValue>()[fArrayIndexStack.back()++];
131cb93a386Sopenharmony_ci            } else if (!name) {
132cb93a386Sopenharmony_ci                return *cur;
133cb93a386Sopenharmony_ci            } else if (cur->is<skjson::ObjectValue>()) {
134cb93a386Sopenharmony_ci                return cur->as<skjson::ObjectValue>()[name];
135cb93a386Sopenharmony_ci            }
136cb93a386Sopenharmony_ci        }
137cb93a386Sopenharmony_ci        static skjson::NullValue gNull;
138cb93a386Sopenharmony_ci        return gNull;
139cb93a386Sopenharmony_ci    }
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci    static bool TryParse(const skjson::Value& v, float& f) {
142cb93a386Sopenharmony_ci        if (const skjson::NumberValue* num = v) {
143cb93a386Sopenharmony_ci            f = static_cast<float>(**num);
144cb93a386Sopenharmony_ci            return true;
145cb93a386Sopenharmony_ci        }
146cb93a386Sopenharmony_ci        return false;
147cb93a386Sopenharmony_ci    }
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    static bool TryParse(const skjson::Value& v, int& i) {
150cb93a386Sopenharmony_ci        if (const skjson::NumberValue* num = v) {
151cb93a386Sopenharmony_ci            double dbl = **num;
152cb93a386Sopenharmony_ci            i = static_cast<int>(dbl);
153cb93a386Sopenharmony_ci            return static_cast<double>(i) == dbl;
154cb93a386Sopenharmony_ci        }
155cb93a386Sopenharmony_ci        return false;
156cb93a386Sopenharmony_ci    }
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci    static bool TryParse(const skjson::Value& v, SkString& s) {
159cb93a386Sopenharmony_ci        if (const skjson::StringValue* str = v) {
160cb93a386Sopenharmony_ci            s.set(str->begin(), str->size());
161cb93a386Sopenharmony_ci            return true;
162cb93a386Sopenharmony_ci        }
163cb93a386Sopenharmony_ci        return false;
164cb93a386Sopenharmony_ci    }
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    static bool TryParse(const skjson::Value& v, bool& b) {
167cb93a386Sopenharmony_ci        switch (v.getType()) {
168cb93a386Sopenharmony_ci        case skjson::Value::Type::kNumber:
169cb93a386Sopenharmony_ci            b = SkToBool(*v.as<skjson::NumberValue>());
170cb93a386Sopenharmony_ci            return true;
171cb93a386Sopenharmony_ci        case skjson::Value::Type::kBool:
172cb93a386Sopenharmony_ci            b = *v.as<skjson::BoolValue>();
173cb93a386Sopenharmony_ci            return true;
174cb93a386Sopenharmony_ci        default:
175cb93a386Sopenharmony_ci            break;
176cb93a386Sopenharmony_ci        }
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci        return false;
179cb93a386Sopenharmony_ci    }
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci    const skjson::Value& fRoot;
182cb93a386Sopenharmony_ci    SkSTArray<16, const skjson::Value*, true> fStack;
183cb93a386Sopenharmony_ci    SkSTArray<16, size_t, true>               fArrayIndexStack;
184cb93a386Sopenharmony_ci};
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci#endif // SkParticleSerialization_DEFINED
187