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 #include "GrAuditTrail.h" 9 10 void GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const FrameArray& array, 11 bool addComma) { 12 if (array.count()) { 13 if (addComma) { 14 json->appendf(","); 15 } 16 json->appendf("\"%s\": [", name); 17 for (int i = 0; i < array.count(); i++) { 18 json->append(array[i]->toJson()); 19 if (i < array.count() - 1) { 20 json->append(","); 21 } 22 } 23 json->append("]"); 24 } 25 } 26 27 // This will pretty print a very small subset of json 28 // The parsing rules are straightforward, aside from the fact that we do not want an extra newline 29 // before ',' and after '}', so we have a comma exception rule. 30 class PrettyPrintJson { 31 public: 32 SkString prettify(const SkString& json) { 33 fPrettyJson.reset(); 34 fTabCount = 0; 35 fFreshLine = false; 36 fCommaException = false; 37 for (size_t i = 0; i < json.size(); i++) { 38 if ('[' == json[i] || '{' == json[i]) { 39 this->newline(); 40 this->appendChar(json[i]); 41 fTabCount++; 42 this->newline(); 43 } else if (']' == json[i] || '}' == json[i]) { 44 fTabCount--; 45 this->newline(); 46 this->appendChar(json[i]); 47 fCommaException = true; 48 } else if (',' == json[i]) { 49 this->appendChar(json[i]); 50 this->newline(); 51 } else { 52 this->appendChar(json[i]); 53 } 54 } 55 return fPrettyJson; 56 } 57 private: 58 void appendChar(char appendee) { 59 if (fCommaException && ',' != appendee) { 60 this->newline(); 61 } 62 this->tab(); 63 fPrettyJson += appendee; 64 fFreshLine = false; 65 fCommaException = false; 66 } 67 68 void tab() { 69 if (fFreshLine) { 70 for (int i = 0; i < fTabCount; i++) { 71 fPrettyJson += '\t'; 72 } 73 } 74 } 75 76 void newline() { 77 if (!fFreshLine) { 78 fFreshLine = true; 79 fPrettyJson += '\n'; 80 } 81 } 82 83 SkString fPrettyJson; 84 int fTabCount; 85 bool fFreshLine; 86 bool fCommaException; 87 }; 88 89 static SkString pretty_print_json(SkString json) { 90 class PrettyPrintJson prettyPrintJson; 91 return prettyPrintJson.prettify(json); 92 } 93 94 SkString GrAuditTrail::toJson(bool prettyPrint) const { 95 SkString json; 96 json.append("{"); 97 JsonifyTArray(&json, "Stacks", fFrames, false); 98 json.append("}"); 99 100 if (prettyPrint) { 101 return pretty_print_json(json); 102 } else { 103 return json; 104 } 105 } 106 107 SkString GrAuditTrail::Frame::toJson() const { 108 SkString json; 109 json.append("{"); 110 json.appendf("\"Name\": \"%s\"", fName); 111 JsonifyTArray(&json, "Frames", fChildren, true); 112 json.append("}"); 113 return json; 114 } 115 116 SkString GrAuditTrail::Batch::toJson() const { 117 SkString json; 118 json.append("{"); 119 json.appendf("\"Name\": \"%s\",", fName); 120 json.append("\"Bounds\": {"); 121 json.appendf("\"Left\": %f,", fBounds.fLeft); 122 json.appendf("\"Right\": %f,", fBounds.fRight); 123 json.appendf("\"Top\": %f,", fBounds.fTop); 124 json.appendf("\"Bottom\": %f", fBounds.fBottom); 125 json.append("}"); 126 json.append("}"); 127 return json; 128 } 129