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 10bool FiddleBase::parseFiddles() { 11 if (!this->skipExact("{\n")) { 12 return false; 13 } 14 while (!this->eof()) { 15 if (!this->skipExact(" \"")) { 16 return false; 17 } 18 const char* nameLoc = fChar; 19 if (!this->skipToEndBracket("\"")) { 20 return false; 21 } 22 string name(nameLoc, fChar - nameLoc); 23 if (!this->skipExact("\": {\n")) { 24 return false; 25 } 26 if (!this->skipExact(" \"compile_errors\": [")) { 27 return false; 28 } 29 if (']' != this->peek()) { 30 // report compiler errors 31 int brackets = 1; 32 do { 33 if ('[' == this->peek()) { 34 ++brackets; 35 } else if (']' == this->peek()) { 36 --brackets; 37 } 38 } while (!this->eof() && this->next() && brackets > 0); 39 this->reportError("fiddle compile error"); 40 } 41 if (!this->skipExact("],\n")) { 42 return false; 43 } 44 if (!this->skipExact(" \"runtime_error\": \"")) { 45 return false; 46 } 47 if ('"' != this->peek()) { 48 if (!this->skipToEndBracket('"')) { 49 return false; 50 } 51 this->reportError("fiddle runtime error"); 52 } 53 if (!this->skipExact("\",\n")) { 54 return false; 55 } 56 if (!this->skipExact(" \"fiddleHash\": \"")) { 57 return false; 58 } 59 const char* hashStart = fChar; 60 if (!this->skipToEndBracket('"')) { 61 return false; 62 } 63 Definition* example = this->findExample(name); 64 if (!example) { 65 this->reportError("missing example"); 66 } 67 string hash(hashStart, fChar - hashStart); 68 if (example) { 69 example->fHash = hash; 70 } 71 if (!this->skipExact("\",\n")) { 72 return false; 73 } 74 if (!this->skipExact(" \"text\": \"")) { 75 return false; 76 } 77 if ('"' != this->peek()) { 78 const char* stdOutStart = fChar; 79 do { 80 if ('\\' == this->peek()) { 81 this->next(); 82 } else if ('"' == this->peek()) { 83 break; 84 } 85 } while (!this->eof() && this->next()); 86 const char* stdOutEnd = fChar; 87 if (example && fTextOut) { 88 if (!this->textOut(example, stdOutStart, stdOutEnd)) { 89 return false; 90 } 91 } 92 } else { 93 if (example && fPngOut) { 94 if (!this->pngOut(example)) { 95 return false; 96 } 97 } 98 } 99 if (!this->skipExact("\"\n")) { 100 return false; 101 } 102 if (!this->skipExact(" }")) { 103 return false; 104 } 105 if ('\n' == this->peek()) { 106 break; 107 } 108 if (!this->skipExact(",\n")) { 109 return false; 110 } 111 } 112 return true; 113} 114 115bool FiddleParser::textOut(Definition* example, const char* stdOutStart, 116 const char* stdOutEnd) { 117 bool foundStdOut = false; 118 for (auto& textOut : example->fChildren) { 119 if (MarkType::kStdOut != textOut->fMarkType) { 120 continue; 121 } 122 foundStdOut = true; 123 bool foundVolatile = false; 124 for (auto& stdOutChild : textOut->fChildren) { 125 if (MarkType::kVolatile == stdOutChild->fMarkType) { 126 foundVolatile = true; 127 break; 128 } 129 } 130 TextParser bmh(textOut); 131 EscapeParser fiddle(stdOutStart, stdOutEnd); 132 do { 133 bmh.skipWhiteSpace(); 134 fiddle.skipWhiteSpace(); 135 const char* bmhEnd = bmh.trimmedLineEnd(); 136 const char* fiddleEnd = fiddle.trimmedLineEnd(); 137 ptrdiff_t bmhLen = bmhEnd - bmh.fChar; 138 SkASSERT(bmhLen > 0); 139 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar; 140 SkASSERT(fiddleLen > 0); 141 if (bmhLen != fiddleLen) { 142 if (!foundVolatile) { 143 bmh.reportError("mismatched stdout len\n"); 144 } 145 } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) { 146 if (!foundVolatile) { 147 bmh.reportError("mismatched stdout text\n"); 148 } 149 } 150 bmh.skipToLineStart(); 151 fiddle.skipToLineStart(); 152 } while (!bmh.eof() && !fiddle.eof()); 153 if (!foundStdOut) { 154 bmh.reportError("bmh %s missing stdout\n"); 155 } else if (!bmh.eof() || !fiddle.eof()) { 156 if (!foundVolatile) { 157 bmh.reportError("%s mismatched stdout eof\n"); 158 } 159 } 160 } 161 return true; 162} 163