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 "bmhParser.h"
9 #include "fiddleParser.h"
10
11 // could make this more elaborate and look up the example definition in the bmh file;
12 // see if a simpler hint provided is sufficient
report_error(const char * blockName,const char * errorMessage)13 static bool report_error(const char* blockName, const char* errorMessage) {
14 SkDebugf("%s: %s\n", blockName, errorMessage);
15 return false;
16 }
17
findExample(string name) const18 Definition* FiddleBase::findExample(string name) const {
19 return fBmhParser->findExample(name);
20 }
21
parseFiddles()22 bool FiddleBase::parseFiddles() {
23 if (fStack.empty()) {
24 return false;
25 }
26 JsonStatus* status = &fStack.back();
27 while (status->fIter != status->fObject.end()) {
28 const char* blockName = status->fIter.memberName();
29 Definition* example = nullptr;
30 string textString;
31 if (!status->fObject.isObject()) {
32 return report_error(blockName, "expected object");
33 }
34 for (auto iter = status->fIter->begin(); status->fIter->end() != iter; ++iter) {
35 const char* memberName = iter.memberName();
36 if (!strcmp("compile_errors", memberName)) {
37 if (!iter->isArray()) {
38 return report_error(blockName, "expected array");
39 }
40 if (iter->size()) {
41 return report_error(blockName, "fiddle compiler error");
42 }
43 continue;
44 }
45 if (!strcmp("runtime_error", memberName)) {
46 if (!iter->isString()) {
47 return report_error(blockName, "expected string 1");
48 }
49 if (iter->asString().length()) {
50 return report_error(blockName, "fiddle runtime error");
51 }
52 continue;
53 }
54 if (!strcmp("fiddleHash", memberName)) {
55 if (!iter->isString()) {
56 return report_error(blockName, "expected string 2");
57 }
58 example = this->findExample(blockName);
59 if (!example) {
60 return report_error(blockName, "missing example");
61 }
62 if (example->fHash.length() && example->fHash != iter->asString()) {
63 return example->reportError<bool>("mismatched hash");
64 }
65 example->fHash = iter->asString();
66 continue;
67 }
68 if (!strcmp("text", memberName)) {
69 if (!iter->isString()) {
70 return report_error(blockName, "expected string 3");
71 }
72 textString = iter->asString();
73 continue;
74 }
75 return report_error(blockName, "unexpected key");
76 }
77 if (!example) {
78 return report_error(blockName, "missing fiddleHash");
79 }
80 size_t strLen = textString.length();
81 if (strLen) {
82 if (fTextOut
83 && !this->textOut(example, textString.c_str(), textString.c_str() + strLen)) {
84 return false;
85 }
86 } else if (fPngOut && !this->pngOut(example)) {
87 return false;
88 }
89 status->fIter++;
90 }
91 return true;
92 }
93
parseFromFile(const char * path)94 bool FiddleParser::parseFromFile(const char* path) {
95 if (!INHERITED::parseFromFile(path)) {
96 return false;
97 }
98 fBmhParser->resetExampleHashes();
99 if (!INHERITED::parseFiddles()) {
100 return false;
101 }
102 return fBmhParser->checkExampleHashes();
103 }
104
textOut(Definition * example,const char * stdOutStart,const char * stdOutEnd)105 bool FiddleParser::textOut(Definition* example, const char* stdOutStart,
106 const char* stdOutEnd) {
107 bool foundStdOut = false;
108 for (auto& textOut : example->fChildren) {
109 if (MarkType::kStdOut != textOut->fMarkType) {
110 continue;
111 }
112 foundStdOut = true;
113 bool foundVolatile = false;
114 for (auto& stdOutChild : textOut->fChildren) {
115 if (MarkType::kVolatile == stdOutChild->fMarkType) {
116 foundVolatile = true;
117 break;
118 }
119 }
120 TextParser bmh(textOut);
121 EscapeParser fiddle(stdOutStart, stdOutEnd);
122 do {
123 bmh.skipWhiteSpace();
124 fiddle.skipWhiteSpace();
125 const char* bmhEnd = bmh.trimmedLineEnd();
126 const char* fiddleEnd = fiddle.trimmedLineEnd();
127 ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
128 SkASSERT(bmhLen > 0);
129 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
130 SkASSERT(fiddleLen > 0);
131 if (bmhLen != fiddleLen) {
132 if (!foundVolatile) {
133 bmh.reportError("mismatched stdout len\n");
134 }
135 } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
136 if (!foundVolatile) {
137 SkDebugf("%.*s\n", fiddleLen, fiddle.fChar);
138 bmh.reportError("mismatched stdout text\n");
139 }
140 }
141 bmh.skipToLineStart();
142 fiddle.skipToLineStart();
143 } while (!bmh.eof() && !fiddle.eof());
144 if (!foundStdOut) {
145 bmh.reportError("bmh %s missing stdout\n");
146 } else if (!bmh.eof() || !fiddle.eof()) {
147 if (!foundVolatile) {
148 bmh.reportError("%s mismatched stdout eof\n");
149 }
150 }
151 }
152 return true;
153 }
154