PLaSK library

Loading...
Searching...
No Matches
writer.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__UTILS_XMLWRITER_H
15#define PLASK__UTILS_XMLWRITER_H
16
17#include <string>
18#include <iostream>
19#include <cstdio>
20
21#include "exceptions.hpp"
22#include "../format.hpp"
23
24 namespace plask {
25
46 struct PLASK_API XMLWriter {
47
51 struct PLASK_API Output {
52
53 virtual ~Output() {}
54
60 virtual void write(const char* buffer, std::size_t n) = 0;
61
68 template <int n>
69 void puts(const char (&str)[n]) { write(str, n-1); }
70
77 virtual void put(char c) { write(&c, 1); }
78
82 void newline() { put('\n'); }
83
84 };
85
91 class PLASK_API Element {
92
94 std::string name;
95
97 XMLWriter* writer;
98
100 Element* parent;
101
103 bool attributesStillAlowed;
104
106 bool hasChildren;
107
108 public:
109
115 Element(XMLWriter& writer, const std::string& name);
116
122 Element(XMLWriter& writer, std::string&& name);
123
129 Element(Element& parent, const std::string& name);
130
136 Element(Element& parent, std::string&& name);
137
139 Element(const Element&) = delete;
140
142 Element& operator=(const Element&) = delete;
143
145 Element(Element&& to_move);
146
148 Element& operator=(Element&& to_move);
149
151 ~Element();
152
156 std::size_t getLevel() const;
157
164 Element& attr(const std::string& attr_name, const std::string& attr_value);
165
172 template <typename ValueT>
173 Element& attr(const std::string& attr_name, const ValueT& attr_value) {
174 return attr(attr_name, str(attr_value));
175 }
176
182 Element& writeText(const char* str);
183
189 Element& writeText(const std::string& str) { return writeText(str.c_str()); }
190
196 template <class T>
197 Element& writeText(const T& value) {
198 return writeText(str(value));
199 }
200
201 Element& writeCDATA(const std::string& str);
202
206 void indent ();
207
212 template <typename name_t>
213 Element addElement(name_t&& name) { return Element(*this, std::forward<name_t>(name)); }
214
219 template <typename name_t>
220 Element addTag(name_t&& name) { return Element(*this, std::forward<name_t>(name)); }
221
226 Element& end();
227
232 bool canAppendAttributes() const { return this->attributesStillAlowed; }
233
238 bool isCurrent() const { return writer->current == this; }
239
244 bool isEnded() const { return writer != 0; }
245
250 const std::string& getName() const { return name; }
251
256 XMLWriter* getWriter() const { return writer; }
257
262 Element* getParent() const { return parent; }
263
264 private:
265 void writeOpening();
266
267 void writeClosing();
268
269 bool disallowAttributes();
270
271 void ensureIsCurrent();
272 };
273
274 private:
275
277 Output* out;
278
279 void appendStr(const std::string& s) { out->write(s.data(), s.size()); }
280
281 void appendStrQuoted(const char* s);
282
283 void appendStrQuoted(const std::string& s) { appendStrQuoted(s.c_str()); }
284
286 Element* current;
287
289 std::size_t indentation;
290
291 public:
292
298 XMLWriter(std::ostream& out, std::size_t indentation=2);
299
305 XMLWriter(const std::string& file_name, std::size_t indentation=2);
306
314 XMLWriter(std::FILE* cfile, std::size_t indentation=2);
315
321 XMLWriter(Output* out, std::size_t indentation=2);
322
324 ~XMLWriter() { delete out; assert(current == 0); }
325
327 void writeHeader() {
328 out->puts("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
329 out->newline();
330 }
331
337 template <typename name_t>
338 Element addElement(name_t&& name) { return Element(*this, std::forward<name_t>(name)); }
339
345 template <typename name_t>
346 Element addTag(name_t&& name) { return Element(*this, std::forward<name_t>(name)); }
347
352 template <typename text_t>
353 void writeText(text_t&& text) {
354 if (!current) throw XMLWriterException("no tag is open");
355 current->writeText(std::forward<text_t>(text));
356 }
357
362 template <typename text_t>
363 void writeCDATA(text_t&& cdata) {
364 if (!current) throw XMLWriterException("no tag is open");
365 current->writeCDATA(std::forward<text_t>(cdata));
366 }
367
371 void indent () {
372 if (current) current->indent();
373 }
374
379 Element* getCurrent() {
380 return current;
381 }
382
383};
384
386 typedef XMLWriter::Element XMLElement;
387
388} // namespace plask
389
390#endif // PLASK__UTILS_XMLWRITER_H