1 /* 2 * Copyright 2018 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 #ifndef parserCommon_DEFINED 9 #define parserCommon_DEFINED 10 11 #include "SkData.h" 12 #include "SkJSONCPP.h" 13 14 #include "definition.h" 15 #include "textParser.h" 16 17 enum class StatusFilter { 18 kCompleted, 19 kInProgress, 20 kUnknown, 21 }; 22 23 class ParserCommon : public TextParser { 24 public: 25 enum class OneFile { 26 kNo, 27 kYes, 28 }; 29 30 enum class OneLine { 31 kNo, 32 kYes, 33 }; 34 35 enum class IndentKind { 36 kConstOut, 37 kEnumChild, 38 kEnumChild2, 39 kEnumHeader, 40 kEnumHeader2, 41 kMethodOut, 42 kStructMember, 43 }; 44 45 struct IndentState { IndentStateIndentState46 IndentState(IndentKind kind, int indent) 47 : fKind(kind) 48 , fIndent(indent) { 49 } 50 51 IndentKind fKind; 52 int fIndent; 53 }; 54 ParserCommon()55 ParserCommon() : TextParser() 56 , fParent(nullptr) 57 , fDebugOut(false) 58 , fValidate(false) 59 , fReturnOnWrite(false) 60 { 61 } 62 ~ParserCommon()63 ~ParserCommon() override { 64 } 65 addDefinition(Definition * def)66 void addDefinition(Definition* def) { 67 fParent->fChildren.push_back(def); 68 fParent = def; 69 } 70 71 void checkLineLength(size_t len, const char* str); 72 static string ConvertRef(const string str, bool first); 73 static void CopyToFile(string oldFile, string newFile); 74 static char* FindDateTime(char* buffer, int size); 75 static string HtmlFileName(string bmhFileName); 76 indentIn(IndentKind kind)77 void indentIn(IndentKind kind) { 78 fIndent += 4; 79 fIndentStack.emplace_back(kind, fIndent); 80 } 81 indentOut()82 void indentOut() { 83 SkASSERT(fIndent >= 4); 84 SkASSERT(fIndentStack.back().fIndent == fIndent); 85 fIndent -= 4; 86 fIndentStack.pop_back(); 87 } 88 indentToColumn(int column)89 void indentToColumn(int column) { 90 SkASSERT(column >= fColumn); 91 SkASSERT(!fReturnOnWrite); 92 SkASSERT(column < 80); 93 FPRINTF("%*s", column - fColumn, ""); 94 fColumn = column; 95 fSpaces += column - fColumn; 96 } 97 leadingPunctuation(const char * str,size_t len)98 bool leadingPunctuation(const char* str, size_t len) const { 99 if (!fPendingSpace) { 100 return false; 101 } 102 if (len < 2) { 103 return false; 104 } 105 if ('.' != str[0] && ',' != str[0] && ';' != str[0] && ':' != str[0]) { 106 return false; 107 } 108 return ' ' >= str[1]; 109 } 110 lf(int count)111 void lf(int count) { 112 fPendingLF = SkTMax(fPendingLF, count); 113 this->nl(); 114 } 115 lfAlways(int count)116 void lfAlways(int count) { 117 this->lf(count); 118 this->writePending(); 119 } 120 lfcr()121 void lfcr() { 122 this->lf(1); 123 } 124 nl()125 void nl() { 126 SkASSERT(!fReturnOnWrite); 127 fLinefeeds = 0; 128 fSpaces = 0; 129 fColumn = 0; 130 fPendingSpace = 0; 131 } 132 133 bool parseFile(const char* file, const char* suffix, OneFile ); 134 bool parseStatus(const char* file, const char* suffix, StatusFilter filter); 135 virtual bool parseFromFile(const char* path) = 0; 136 bool parseSetup(const char* path); 137 popObject()138 void popObject() { 139 fParent->fContentEnd = fParent->fTerminator = fChar; 140 fParent = fParent->fParent; 141 } 142 143 static char* ReadToBuffer(string filename, int* size); 144 145 virtual void reset() = 0; 146 resetCommon()147 void resetCommon() { 148 fLine = fChar = fStart; 149 fLineCount = 0; 150 fLinesWritten = 1; 151 fParent = nullptr; 152 fIndent = 0; 153 fOut = nullptr; 154 fMaxLF = 2; 155 fPendingLF = 0; 156 fPendingSpace = 0; 157 fOutdentNext = false; 158 fWritingIncludes = false; 159 fDebugWriteCodeBlock = false; 160 nl(); 161 } 162 setAsParent(Definition * definition)163 void setAsParent(Definition* definition) { 164 if (fParent) { 165 fParent->fChildren.push_back(definition); 166 definition->fParent = fParent; 167 } 168 fParent = definition; 169 } 170 singleLF()171 void singleLF() { 172 fMaxLF = 1; 173 } 174 175 void stringAppend(string& result, char ch) const; 176 void stringAppend(string& result, string str) const; 177 void stringAppend(string& result, const Definition* ) const; 178 writeBlock(int size,const char * data)179 void writeBlock(int size, const char* data) { 180 SkAssertResult(writeBlockTrim(size, data)); 181 } 182 183 bool writeBlockIndent(int size, const char* data, bool ignoreIndent); 184 writeBlockSeparator()185 void writeBlockSeparator() { 186 this->writeString( 187 "# ------------------------------------------------------------------------------"); 188 this->lf(2); 189 } 190 191 bool writeBlockTrim(int size, const char* data); 192 writeCommentHeader()193 void writeCommentHeader() { 194 this->lf(2); 195 this->writeString("/**"); 196 this->writeSpace(); 197 } 198 writeCommentTrailer(OneLine oneLine)199 void writeCommentTrailer(OneLine oneLine) { 200 if (OneLine::kNo == oneLine) { 201 this->lf(1); 202 } else { 203 this->writeSpace(); 204 } 205 this->writeString("*/"); 206 this->lfcr(); 207 } 208 209 void writePending(); 210 211 // write a pending space, so that two consecutive calls 212 // don't double write, and trailing spaces on lines aren't written 213 void writeSpace(int count = 1) { 214 SkASSERT(!fReturnOnWrite); 215 SkASSERT(!fPendingLF); 216 SkASSERT(!fLinefeeds); 217 SkASSERT(fColumn > 0); 218 SkASSERT(!fSpaces); 219 fPendingSpace = count; 220 } 221 222 void writeString(const char* str); 223 writeString(string str)224 void writeString(string str) { 225 this->writeString(str.c_str()); 226 } 227 228 static bool WrittenFileDiffers(string filename, string readname); 229 230 unordered_map<string, sk_sp<SkData>> fRawData; 231 unordered_map<string, vector<char>> fLFOnly; 232 vector<IndentState> fIndentStack; 233 Definition* fParent; 234 FILE* fOut; 235 string fRawFilePathDir; 236 int fLinefeeds; // number of linefeeds last written, zeroed on non-space 237 int fMaxLF; // number of linefeeds allowed 238 int fPendingLF; // number of linefeeds to write (can be suppressed) 239 int fSpaces; // number of spaces (indent) last written, zeroed on non-space 240 int fColumn; // current column; number of chars past last linefeed 241 int fIndent; // desired indention 242 int fPendingSpace; // one or two spaces should preceed the next string or block 243 size_t fLinesWritten; // as opposed to fLineCount, number of lines read 244 char fLastChar; // last written 245 bool fDebugOut; // set true to write to std out 246 bool fValidate; // set true to check anchor defs and refs 247 bool fOutdentNext; // set at end of embedded struct to prevent premature outdent 248 bool fWroteSomething; // used to detect empty content; an alternative source is preferable 249 bool fReturnOnWrite; // used to detect non-empty content; allowing early return 250 bool fWritingIncludes; // set true when writing includes to check >100 columns 251 mutable bool fDebugWriteCodeBlock; 252 253 private: 254 typedef TextParser INHERITED; 255 }; 256 257 struct JsonStatus { 258 const Json::Value& fObject; 259 Json::Value::iterator fIter; 260 string fName; 261 StatusFilter fStatusFilter; 262 }; 263 264 class JsonCommon : public ParserCommon { 265 public: empty()266 bool empty() { return fStack.empty(); } 267 bool parseFromFile(const char* path) override; 268 reset()269 void reset() override { 270 fStack.clear(); 271 INHERITED::resetCommon(); 272 } 273 274 vector<JsonStatus> fStack; 275 Json::Value fRoot; 276 private: 277 typedef ParserCommon INHERITED; 278 }; 279 280 class StatusIter : public JsonCommon { 281 public: 282 StatusIter(const char* statusFile, const char* suffix, StatusFilter); ~StatusIter()283 ~StatusIter() override {} 284 string baseDir(); 285 bool next(string* file, StatusFilter* filter); 286 private: 287 const char* fSuffix; 288 StatusFilter fFilter; 289 }; 290 291 class HackParser : public ParserCommon { 292 public: HackParser(const BmhParser & bmhParser)293 HackParser(const BmhParser& bmhParser) 294 : ParserCommon() 295 , fBmhParser(bmhParser) { 296 this->reset(); 297 } 298 parseFromFile(const char * path)299 bool parseFromFile(const char* path) override { 300 if (!INHERITED::parseSetup(path)) { 301 return false; 302 } 303 return hackFiles(); 304 } 305 reset()306 void reset() override { 307 INHERITED::resetCommon(); 308 } 309 310 void replaceWithPop(const Definition* ); 311 312 private: 313 const BmhParser& fBmhParser; 314 bool hackFiles(); 315 316 typedef ParserCommon INHERITED; 317 }; 318 319 #endif 320