Home | History | Annotate | Download | only in bookmaker
      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