blob: faf551006f75a2e66203da677d6b948a4952e797 [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001/*
2 * Copyright 2017 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 "bookmaker.h"
9
10static Definition* find_fiddle(Definition* def, const string& name) {
11 if (MarkType::kExample == def->fMarkType && name == def->fFiddle) {
12 return def;
13 }
14 for (auto& child : def->fChildren) {
15 Definition* result = find_fiddle(child, name);
16 if (result) {
17 return result;
18 }
19 }
20 return nullptr;
21}
22
Cary Clarkbef063a2017-10-31 15:44:45 -040023Definition* FiddleBase::findExample(const string& name) const {
Cary Clark8032b982017-07-28 11:04:54 -040024 for (const auto& topic : fBmhParser->fTopicMap) {
25 if (topic.second->fParent) {
26 continue;
27 }
28 Definition* def = find_fiddle(topic.second, name);
29 if (def) {
30 return def;
31 }
32 }
33 return nullptr;
34}
35
Cary Clarkbef063a2017-10-31 15:44:45 -040036bool FiddleBase::parseFiddles() {
Cary Clark8032b982017-07-28 11:04:54 -040037 if (!this->skipExact("{\n")) {
38 return false;
39 }
40 while (!this->eof()) {
41 if (!this->skipExact(" \"")) {
42 return false;
43 }
44 const char* nameLoc = fChar;
45 if (!this->skipToEndBracket("\"")) {
46 return false;
47 }
48 string name(nameLoc, fChar - nameLoc);
49 if (!this->skipExact("\": {\n")) {
50 return false;
51 }
52 if (!this->skipExact(" \"compile_errors\": [")) {
53 return false;
54 }
55 if (']' != this->peek()) {
56 // report compiler errors
57 int brackets = 1;
Cary Clark8032b982017-07-28 11:04:54 -040058 do {
59 if ('[' == this->peek()) {
60 ++brackets;
61 } else if (']' == this->peek()) {
62 --brackets;
63 }
64 } while (!this->eof() && this->next() && brackets > 0);
Cary Clarkd0530ba2017-09-14 11:25:39 -040065 this->reportError("fiddle compile error");
Cary Clark8032b982017-07-28 11:04:54 -040066 }
67 if (!this->skipExact("],\n")) {
68 return false;
69 }
70 if (!this->skipExact(" \"runtime_error\": \"")) {
71 return false;
72 }
73 if ('"' != this->peek()) {
Cary Clark8032b982017-07-28 11:04:54 -040074 if (!this->skipToEndBracket('"')) {
75 return false;
76 }
Cary Clarkd0530ba2017-09-14 11:25:39 -040077 this->reportError("fiddle runtime error");
Cary Clark8032b982017-07-28 11:04:54 -040078 }
79 if (!this->skipExact("\",\n")) {
80 return false;
81 }
82 if (!this->skipExact(" \"fiddleHash\": \"")) {
83 return false;
84 }
85 const char* hashStart = fChar;
86 if (!this->skipToEndBracket('"')) {
87 return false;
88 }
89 Definition* example = this->findExample(name);
90 if (!example) {
Cary Clarkd0530ba2017-09-14 11:25:39 -040091 this->reportError("missing example");
Cary Clark8032b982017-07-28 11:04:54 -040092 }
93 string hash(hashStart, fChar - hashStart);
94 if (example) {
95 example->fHash = hash;
96 }
97 if (!this->skipExact("\",\n")) {
98 return false;
99 }
100 if (!this->skipExact(" \"text\": \"")) {
101 return false;
102 }
103 if ('"' != this->peek()) {
104 const char* stdOutStart = fChar;
105 do {
106 if ('\\' == this->peek()) {
107 this->next();
108 } else if ('"' == this->peek()) {
109 break;
110 }
111 } while (!this->eof() && this->next());
112 const char* stdOutEnd = fChar;
Cary Clarkbef063a2017-10-31 15:44:45 -0400113 if (example && fTextOut) {
114 if (!this->textOut(example, stdOutStart, stdOutEnd)) {
115 return false;
116 }
117 }
118 } else {
119 if (example && fPngOut) {
120 if (!this->pngOut(example)) {
121 return false;
Cary Clark8032b982017-07-28 11:04:54 -0400122 }
123 }
124 }
125 if (!this->skipExact("\"\n")) {
126 return false;
127 }
128 if (!this->skipExact(" }")) {
129 return false;
130 }
131 if ('\n' == this->peek()) {
132 break;
133 }
134 if (!this->skipExact(",\n")) {
135 return false;
136 }
137 }
Cary Clarkbef063a2017-10-31 15:44:45 -0400138 return true;
139}
140
141bool FiddleParser::textOut(Definition* example, const char* stdOutStart,
142 const char* stdOutEnd) {
143 bool foundStdOut = false;
144 for (auto& textOut : example->fChildren) {
145 if (MarkType::kStdOut != textOut->fMarkType) {
146 continue;
147 }
148 foundStdOut = true;
149 bool foundVolatile = false;
150 for (auto& stdOutChild : textOut->fChildren) {
151 if (MarkType::kVolatile == stdOutChild->fMarkType) {
152 foundVolatile = true;
153 break;
154 }
155 }
156 TextParser bmh(textOut);
157 EscapeParser fiddle(stdOutStart, stdOutEnd);
158 do {
159 bmh.skipWhiteSpace();
160 fiddle.skipWhiteSpace();
161 const char* bmhEnd = bmh.trimmedLineEnd();
162 const char* fiddleEnd = fiddle.trimmedLineEnd();
163 ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
164 SkASSERT(bmhLen > 0);
165 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
166 SkASSERT(fiddleLen > 0);
167 if (bmhLen != fiddleLen) {
168 if (!foundVolatile) {
169 bmh.reportError("mismatched stdout len\n");
170 }
171 } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
172 if (!foundVolatile) {
173 bmh.reportError("mismatched stdout text\n");
174 }
Cary Clark8032b982017-07-28 11:04:54 -0400175 }
Cary Clarkbef063a2017-10-31 15:44:45 -0400176 bmh.skipToLineStart();
177 fiddle.skipToLineStart();
178 } while (!bmh.eof() && !fiddle.eof());
179 if (!foundStdOut) {
180 bmh.reportError("bmh %s missing stdout\n");
181 } else if (!bmh.eof() || !fiddle.eof()) {
182 if (!foundVolatile) {
183 bmh.reportError("%s mismatched stdout eof\n");
Cary Clark8032b982017-07-28 11:04:54 -0400184 }
185 }
186 }
Cary Clark8032b982017-07-28 11:04:54 -0400187 return true;
188}