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