blob: f31cbd63cdd6c4c7993a7ecf0d1574bc037101d6 [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"
12#include "SkJSONCPP.h"
13
14#include "definition.h"
15#include "textParser.h"
16
17enum class StatusFilter {
18 kCompleted,
19 kInProgress,
20 kUnknown,
21};
22
23class ParserCommon : public TextParser {
24public:
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 {
46 IndentState(IndentKind kind, int indent)
47 : fKind(kind)
48 , fIndent(indent) {
49 }
50
51 IndentKind fKind;
52 int fIndent;
53 };
54
55 ParserCommon() : TextParser()
56 , fParent(nullptr)
57 , fDebugOut(false)
58 , fValidate(false)
59 , fReturnOnWrite(false)
60 {
61 }
62
63 ~ParserCommon() override {
64 }
65
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
77 void indentIn(IndentKind kind) {
78 fIndent += 4;
79 fIndentStack.emplace_back(kind, fIndent);
80 }
81
82 void indentOut() {
83 SkASSERT(fIndent >= 4);
84 SkASSERT(fIndentStack.back().fIndent == fIndent);
85 fIndent -= 4;
86 fIndentStack.pop_back();
87 }
88
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
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
111 void lf(int count) {
112 fPendingLF = SkTMax(fPendingLF, count);
113 this->nl();
114 }
115
116 void lfAlways(int count) {
117 this->lf(count);
118 this->writePending();
119 }
120
121 void lfcr() {
122 this->lf(1);
123 }
124
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
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
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
163 void setAsParent(Definition* definition) {
164 if (fParent) {
165 fParent->fChildren.push_back(definition);
166 definition->fParent = fParent;
167 }
168 fParent = definition;
169 }
170
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
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
185 void writeBlockSeparator() {
186 this->writeString(
187 "# ------------------------------------------------------------------------------");
188 this->lf(2);
189 }
190
191 bool writeBlockTrim(int size, const char* data);
192
193 void writeCommentHeader() {
194 this->lf(2);
195 this->writeString("/**");
196 this->writeSpace();
197 }
198
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
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
253private:
254 typedef TextParser INHERITED;
255};
256
257struct JsonStatus {
258 const Json::Value& fObject;
259 Json::Value::iterator fIter;
260 string fName;
261 StatusFilter fStatusFilter;
262};
263
264class JsonCommon : public ParserCommon {
265public:
266 bool empty() { return fStack.empty(); }
267 bool parseFromFile(const char* path) override;
268
269 void reset() override {
270 fStack.clear();
271 INHERITED::resetCommon();
272 }
273
274 vector<JsonStatus> fStack;
275 Json::Value fRoot;
276private:
277 typedef ParserCommon INHERITED;
278};
279
280class StatusIter : public JsonCommon {
281public:
282 StatusIter(const char* statusFile, const char* suffix, StatusFilter);
283 ~StatusIter() override {}
284 string baseDir();
285 bool next(string* file, StatusFilter* filter);
286private:
287 const char* fSuffix;
288 StatusFilter fFilter;
289};
290
291class HackParser : public ParserCommon {
292public:
293 HackParser(const BmhParser& bmhParser)
294 : ParserCommon()
295 , fBmhParser(bmhParser) {
296 this->reset();
297 }
298
299 bool parseFromFile(const char* path) override {
300 if (!INHERITED::parseSetup(path)) {
301 return false;
302 }
303 return hackFiles();
304 }
305
306 void reset() override {
307 INHERITED::resetCommon();
308 }
309
310 void replaceWithPop(const Definition* );
311
312private:
313 const BmhParser& fBmhParser;
314 bool hackFiles();
315
316 typedef ParserCommon INHERITED;
317};
318
319#endif