|
ferencd@0
|
1 /*
|
|
ferencd@0
|
2 * This project is licensed under the MIT license. For more information see the
|
|
ferencd@0
|
3 * LICENSE file.
|
|
ferencd@0
|
4 */
|
|
ferencd@0
|
5 #pragma once
|
|
ferencd@0
|
6
|
|
ferencd@0
|
7 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
8
|
|
ferencd@0
|
9 #include <functional>
|
|
ferencd@0
|
10 #include <string>
|
|
ferencd@0
|
11 #include <regex>
|
|
ferencd@0
|
12
|
|
ferencd@0
|
13 #include "maddy/blockparser.h"
|
|
ferencd@0
|
14
|
|
ferencd@0
|
15 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
16
|
|
ferencd@0
|
17 namespace maddy {
|
|
ferencd@0
|
18
|
|
ferencd@0
|
19 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
20
|
|
ferencd@0
|
21 /**
|
|
ferencd@0
|
22 * TableParser
|
|
ferencd@0
|
23 *
|
|
ferencd@0
|
24 * For more information, see the docs folder.
|
|
ferencd@0
|
25 *
|
|
ferencd@0
|
26 * @class
|
|
ferencd@0
|
27 */
|
|
ferencd@0
|
28 class TableParser : public BlockParser
|
|
ferencd@0
|
29 {
|
|
ferencd@0
|
30 public:
|
|
ferencd@0
|
31 /**
|
|
ferencd@0
|
32 * ctor
|
|
ferencd@0
|
33 *
|
|
ferencd@0
|
34 * @method
|
|
ferencd@0
|
35 * @param {std::function<void(std::string&)>} parseLineCallback
|
|
ferencd@0
|
36 * @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
|
ferencd@0
|
37 */
|
|
ferencd@0
|
38 TableParser(
|
|
ferencd@0
|
39 std::function<void(std::string&)> parseLineCallback,
|
|
ferencd@0
|
40 std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
|
ferencd@0
|
41 )
|
|
ferencd@0
|
42 : BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
|
ferencd@0
|
43 , isStarted(false)
|
|
ferencd@0
|
44 , isFinished(false)
|
|
ferencd@0
|
45 , currentBlock(0)
|
|
ferencd@0
|
46 , currentRow(0)
|
|
ferencd@0
|
47 {}
|
|
ferencd@0
|
48
|
|
ferencd@0
|
49 /**
|
|
ferencd@0
|
50 * IsStartingLine
|
|
ferencd@0
|
51 *
|
|
ferencd@0
|
52 * If the line has exact `|table>`, then it is starting the table.
|
|
ferencd@0
|
53 *
|
|
ferencd@0
|
54 * @method
|
|
ferencd@0
|
55 * @param {const std::string&} line
|
|
ferencd@0
|
56 * @return {bool}
|
|
ferencd@0
|
57 */
|
|
ferencd@0
|
58 static bool
|
|
ferencd@0
|
59 IsStartingLine(const std::string& line)
|
|
ferencd@0
|
60 {
|
|
ferencd@0
|
61 static std::string matchString("|table>");
|
|
ferencd@0
|
62 return line == matchString;
|
|
ferencd@0
|
63 }
|
|
ferencd@0
|
64
|
|
ferencd@0
|
65 /**
|
|
ferencd@0
|
66 * AddLine
|
|
ferencd@0
|
67 *
|
|
ferencd@0
|
68 * Adding a line which has to be parsed.
|
|
ferencd@0
|
69 *
|
|
ferencd@0
|
70 * @method
|
|
ferencd@0
|
71 * @param {std::string&} line
|
|
ferencd@0
|
72 * @return {void}
|
|
ferencd@0
|
73 */
|
|
ferencd@0
|
74 void
|
|
ferencd@0
|
75 AddLine(std::string& line) override
|
|
ferencd@0
|
76 {
|
|
ferencd@0
|
77 if (!this->isStarted && line == "|table>")
|
|
ferencd@0
|
78 {
|
|
ferencd@0
|
79 this->isStarted = true;
|
|
ferencd@0
|
80 return;
|
|
ferencd@0
|
81 }
|
|
ferencd@0
|
82
|
|
ferencd@0
|
83 if (this->isStarted)
|
|
ferencd@0
|
84 {
|
|
ferencd@0
|
85 if (line == "- | - | -")
|
|
ferencd@0
|
86 {
|
|
ferencd@0
|
87 ++this->currentBlock;
|
|
ferencd@0
|
88 this->currentRow = 0;
|
|
ferencd@0
|
89 return;
|
|
ferencd@0
|
90 }
|
|
ferencd@0
|
91
|
|
ferencd@0
|
92 if (line == "|<table")
|
|
ferencd@0
|
93 {
|
|
ferencd@0
|
94 static std::string emptyLine = "";
|
|
ferencd@0
|
95 this->parseBlock(emptyLine);
|
|
ferencd@0
|
96 this->isFinished = true;
|
|
ferencd@0
|
97 return;
|
|
ferencd@0
|
98 }
|
|
ferencd@0
|
99
|
|
ferencd@0
|
100 if (this->table.size() < this->currentBlock + 1)
|
|
ferencd@0
|
101 {
|
|
ferencd@0
|
102 this->table.push_back(std::vector<std::vector<std::string>>());
|
|
ferencd@0
|
103 }
|
|
ferencd@0
|
104 this->table[this->currentBlock].push_back(std::vector<std::string>());
|
|
ferencd@0
|
105
|
|
ferencd@0
|
106 std::string segment;
|
|
ferencd@0
|
107 std::stringstream streamToSplit(line);
|
|
ferencd@0
|
108
|
|
ferencd@0
|
109 while (std::getline(streamToSplit, segment, '|'))
|
|
ferencd@0
|
110 {
|
|
ferencd@0
|
111 this->parseLine(segment);
|
|
ferencd@0
|
112 this->table[this->currentBlock][this->currentRow].push_back(segment);
|
|
ferencd@0
|
113 }
|
|
ferencd@0
|
114
|
|
ferencd@0
|
115 ++this->currentRow;
|
|
ferencd@0
|
116 }
|
|
ferencd@0
|
117 }
|
|
ferencd@0
|
118
|
|
ferencd@0
|
119 /**
|
|
ferencd@0
|
120 * IsFinished
|
|
ferencd@0
|
121 *
|
|
ferencd@0
|
122 * A table ends with `|<table`.
|
|
ferencd@0
|
123 *
|
|
ferencd@0
|
124 * @method
|
|
ferencd@0
|
125 * @return {bool}
|
|
ferencd@0
|
126 */
|
|
ferencd@0
|
127 bool
|
|
ferencd@0
|
128 IsFinished() const override
|
|
ferencd@0
|
129 {
|
|
ferencd@0
|
130 return this->isFinished;
|
|
ferencd@0
|
131 }
|
|
ferencd@0
|
132
|
|
ferencd@0
|
133 protected:
|
|
ferencd@0
|
134 bool
|
|
ferencd@0
|
135 isInlineBlockAllowed() const override
|
|
ferencd@0
|
136 {
|
|
ferencd@0
|
137 return false;
|
|
ferencd@0
|
138 }
|
|
ferencd@0
|
139
|
|
ferencd@0
|
140 bool
|
|
ferencd@0
|
141 isLineParserAllowed() const override
|
|
ferencd@0
|
142 {
|
|
ferencd@0
|
143 return true;
|
|
ferencd@0
|
144 }
|
|
ferencd@0
|
145
|
|
ferencd@0
|
146 void
|
|
ferencd@0
|
147 parseBlock(std::string&) override
|
|
ferencd@0
|
148 {
|
|
ferencd@0
|
149 result << "<table>";
|
|
ferencd@0
|
150
|
|
ferencd@0
|
151 bool hasHeader = false;
|
|
ferencd@0
|
152 bool hasFooter = false;
|
|
ferencd@0
|
153 bool isFirstBlock = true;
|
|
ferencd@0
|
154 uint32_t currentBlockNumber = 0;
|
|
ferencd@0
|
155
|
|
ferencd@0
|
156 if (this->table.size() > 1)
|
|
ferencd@0
|
157 {
|
|
ferencd@0
|
158 hasHeader = true;
|
|
ferencd@0
|
159 }
|
|
ferencd@0
|
160
|
|
ferencd@0
|
161 if (this->table.size() >= 3)
|
|
ferencd@0
|
162 {
|
|
ferencd@0
|
163 hasFooter = true;
|
|
ferencd@0
|
164 }
|
|
ferencd@0
|
165
|
|
ferencd@0
|
166 for (const std::vector<std::vector<std::string>>& block : this->table)
|
|
ferencd@0
|
167 {
|
|
ferencd@0
|
168 bool isInHeader = false;
|
|
ferencd@0
|
169 bool isInFooter = false;
|
|
ferencd@0
|
170 ++currentBlockNumber;
|
|
ferencd@0
|
171
|
|
ferencd@0
|
172 if (hasHeader && isFirstBlock)
|
|
ferencd@0
|
173 {
|
|
ferencd@0
|
174 result << "<thead>";
|
|
ferencd@0
|
175 isInHeader = true;
|
|
ferencd@0
|
176 }
|
|
ferencd@0
|
177 else if (hasFooter && currentBlockNumber == this->table.size())
|
|
ferencd@0
|
178 {
|
|
ferencd@0
|
179 result << "<tfoot>";
|
|
ferencd@0
|
180 isInFooter = true;
|
|
ferencd@0
|
181 }
|
|
ferencd@0
|
182 else
|
|
ferencd@0
|
183 {
|
|
ferencd@0
|
184 result << "<tbody>";
|
|
ferencd@0
|
185 }
|
|
ferencd@0
|
186
|
|
ferencd@0
|
187 for (const std::vector<std::string>& row : block)
|
|
ferencd@0
|
188 {
|
|
ferencd@0
|
189 result << "<tr>";
|
|
ferencd@0
|
190
|
|
ferencd@0
|
191 for (const std::string& column : row)
|
|
ferencd@0
|
192 {
|
|
ferencd@0
|
193 if (isInHeader)
|
|
ferencd@0
|
194 {
|
|
ferencd@0
|
195 result << "<th>";
|
|
ferencd@0
|
196 }
|
|
ferencd@0
|
197 else
|
|
ferencd@0
|
198 {
|
|
ferencd@0
|
199 result << "<td>";
|
|
ferencd@0
|
200 }
|
|
ferencd@0
|
201
|
|
ferencd@0
|
202 result << column;
|
|
ferencd@0
|
203
|
|
ferencd@0
|
204 if (isInHeader)
|
|
ferencd@0
|
205 {
|
|
ferencd@0
|
206 result << "</th>";
|
|
ferencd@0
|
207 }
|
|
ferencd@0
|
208 else
|
|
ferencd@0
|
209 {
|
|
ferencd@0
|
210 result << "</td>";
|
|
ferencd@0
|
211 }
|
|
ferencd@0
|
212 }
|
|
ferencd@0
|
213
|
|
ferencd@0
|
214 result << "</tr>";
|
|
ferencd@0
|
215 }
|
|
ferencd@0
|
216
|
|
ferencd@0
|
217 if (isInHeader)
|
|
ferencd@0
|
218 {
|
|
ferencd@0
|
219 result << "</thead>";
|
|
ferencd@0
|
220 }
|
|
ferencd@0
|
221 else if (isInFooter)
|
|
ferencd@0
|
222 {
|
|
ferencd@0
|
223 result << "</tfoot>";
|
|
ferencd@0
|
224 }
|
|
ferencd@0
|
225 else
|
|
ferencd@0
|
226 {
|
|
ferencd@0
|
227 result << "</tbody>";
|
|
ferencd@0
|
228 }
|
|
ferencd@0
|
229
|
|
ferencd@0
|
230 isFirstBlock = false;
|
|
ferencd@0
|
231 }
|
|
ferencd@0
|
232
|
|
ferencd@0
|
233 result << "</table>";
|
|
ferencd@0
|
234 }
|
|
ferencd@0
|
235
|
|
ferencd@0
|
236 private:
|
|
ferencd@0
|
237 bool isStarted;
|
|
ferencd@0
|
238 bool isFinished;
|
|
ferencd@0
|
239 uint32_t currentBlock;
|
|
ferencd@0
|
240 uint32_t currentRow;
|
|
ferencd@0
|
241 std::vector<std::vector<std::vector<std::string>>> table;
|
|
ferencd@0
|
242 }; // class TableParser
|
|
ferencd@0
|
243
|
|
ferencd@0
|
244 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
245
|
|
ferencd@0
|
246 } // namespace maddy
|