127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt/*
227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * Copyright 2016 Google Inc.
327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt *
427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * Use of this source code is governed by a BSD-style license that can be
527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * found in the LICENSE file.
627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt */
727a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#include "GrAuditTrail.h"
927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
10adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualittvoid GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const FrameArray& array,
11adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt                                 bool addComma) {
1287a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt    if (array.count()) {
13adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt        if (addComma) {
14adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt            json->appendf(",");
15adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt        }
1687a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt        json->appendf("\"%s\": [", name);
1787a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt        for (int i = 0; i < array.count(); i++) {
1811fae87d39811882e3e99b4abc72c9713a38da55joshualitt            json->append(array[i]->toJson());
1987a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt            if (i < array.count() - 1) {
2087a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt                json->append(",");
2187a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt            }
2227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt        }
2387a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt        json->append("]");
2427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt    }
25086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt}
26086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
27086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt// This will pretty print a very small subset of json
28086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt// The parsing rules are straightforward, aside from the fact that we do not want an extra newline
29086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt// before ',' and after '}', so we have a comma exception rule.
30086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualittclass PrettyPrintJson {
31086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualittpublic:
32086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    SkString prettify(const SkString& json) {
33086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fPrettyJson.reset();
34086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fTabCount = 0;
35086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fFreshLine = false;
36086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fCommaException = false;
37086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        for (size_t i = 0; i < json.size(); i++) {
38086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            if ('[' == json[i] || '{' == json[i]) {
39086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->newline();
40086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->appendChar(json[i]);
41086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                fTabCount++;
42086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->newline();
43086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            } else if (']' == json[i] || '}' == json[i]) {
44086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                fTabCount--;
45086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->newline();
46086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->appendChar(json[i]);
47086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                fCommaException = true;
48086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            } else if (',' == json[i]) {
49086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->appendChar(json[i]);
50086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->newline();
51086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            } else {
52086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                this->appendChar(json[i]);
53086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            }
54086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        }
55086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        return fPrettyJson;
56086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    }
57086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualittprivate:
58086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    void appendChar(char appendee) {
59086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        if (fCommaException && ',' != appendee) {
60086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            this->newline();
61086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        }
62086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        this->tab();
63086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fPrettyJson += appendee;
64086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fFreshLine = false;
65086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        fCommaException = false;
66086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    }
67086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
68086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    void tab() {
69086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        if (fFreshLine) {
70086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            for (int i = 0; i < fTabCount; i++) {
71086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt                fPrettyJson += '\t';
72086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            }
73086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        }
74086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    }
75086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
76086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    void newline() {
77086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        if (!fFreshLine) {
78086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            fFreshLine = true;
79086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt            fPrettyJson += '\n';
80086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt        }
81086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    }
82086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
83086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    SkString fPrettyJson;
84086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    int fTabCount;
85086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    bool fFreshLine;
86086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    bool fCommaException;
87086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt};
88086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
89086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualittstatic SkString pretty_print_json(SkString json) {
90086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    class PrettyPrintJson prettyPrintJson;
91086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    return prettyPrintJson.prettify(json);
92086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt}
93086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
946b3cf73af525fdbf6fd093304db840bb998e3dd6joshualittSkString GrAuditTrail::toJson(bool prettyPrint) const {
95086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    SkString json;
96086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("{");
97adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt    JsonifyTArray(&json, "Stacks", fFrames, false);
98086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("}");
99086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt
1006b3cf73af525fdbf6fd093304db840bb998e3dd6joshualitt    if (prettyPrint) {
1016b3cf73af525fdbf6fd093304db840bb998e3dd6joshualitt        return pretty_print_json(json);
1026b3cf73af525fdbf6fd093304db840bb998e3dd6joshualitt    } else {
1036b3cf73af525fdbf6fd093304db840bb998e3dd6joshualitt        return json;
1046b3cf73af525fdbf6fd093304db840bb998e3dd6joshualitt    }
10527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt}
10627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
10787a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualittSkString GrAuditTrail::Frame::toJson() const {
10827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt    SkString json;
109086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("{");
110adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt    json.appendf("\"Name\": \"%s\"", fName);
111adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt    JsonifyTArray(&json, "Frames", fChildren, true);
112086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("}");
11327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt    return json;
11427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt}
11527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
11611fae87d39811882e3e99b4abc72c9713a38da55joshualittSkString GrAuditTrail::Batch::toJson() const {
117086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    SkString json;
118086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("{");
11987a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt    json.appendf("\"Name\": \"%s\",", fName);
120086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("\"Bounds\": {");
121086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.appendf("\"Left\": %f,", fBounds.fLeft);
122086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.appendf("\"Right\": %f,", fBounds.fRight);
123086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.appendf("\"Top\": %f,", fBounds.fTop);
124086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.appendf("\"Bottom\": %f", fBounds.fBottom);
125086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("}");
126086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    json.append("}");
127086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt    return json;
128086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt}
129