• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
find_fiddle(Definition * def,const string & name)10 static 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 
findExample(const string & name) const23 Definition* FiddleBase::findExample(const string& name) const {
24     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 
parseFiddles()36 bool FiddleBase::parseFiddles() {
37     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;
58             do {
59                 if ('[' == this->peek()) {
60                     ++brackets;
61                 } else if (']' == this->peek()) {
62                     --brackets;
63                 }
64             } while (!this->eof() && this->next() && brackets > 0);
65             this->reportError("fiddle compile error");
66         }
67         if (!this->skipExact("],\n")) {
68             return false;
69         }
70         if (!this->skipExact("    \"runtime_error\": \"")) {
71             return false;
72         }
73         if ('"' != this->peek()) {
74             if (!this->skipToEndBracket('"')) {
75                 return false;
76             }
77             this->reportError("fiddle runtime error");
78         }
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) {
91             this->reportError("missing example");
92         }
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;
113             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;
122                 }
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     }
138     return true;
139 }
140 
textOut(Definition * example,const char * stdOutStart,const char * stdOutEnd)141 bool 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                 }
175             }
176             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");
184             }
185         }
186     }
187     return true;
188 }
189