• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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