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 13 static bool report_error(const char* blockName, const char* errorMessage) { 14 SkDebugf("%s: %s\n", blockName, errorMessage); 15 return false; 16 } 17 18 Definition* FiddleBase::findExample(string name) const { 19 return fBmhParser->findExample(name); 20 } 21 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 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 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