PLaSK library

Loading...
Searching...
No Matches
reader.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__GEOMETRY_READER_H
15#define PLASK__GEOMETRY_READER_H
16
17#include <functional>
18
19#include "../utils/xml/reader.hpp"
20#include "../axes.hpp"
21#include "../material/db.hpp"
22#include "../mesh/boundary_conditions.hpp"
23#include "../manager.hpp"
24#include "space.hpp"
25
26 namespace plask {
27
34 class PLASK_API GeometryReader {
35
37 std::map<std::string, shared_ptr<GeometryObject> > autoNamedObjects;
38
39 public:
40
41 static constexpr const char* const XML_NAME_ATTR = "name";
42 static constexpr const char* const XML_MATERIAL_ATTR = "material";
43 static constexpr const char* const XML_MATERIAL_TOP_ATTR = "material-top";
44 static constexpr const char* const XML_MATERIAL_BOTTOM_ATTR = "material-bottom";
45 static constexpr const char* const XML_MATERIAL_GRADING_ATTR = "material-shape";
46
48 bool materialsAreRequired;
49
57 typedef shared_ptr<GeometryObject> object_read_f(GeometryReader& reader);
58
63 static std::map<std::string, object_read_f*>& objectReaders();
64
70 static void registerObjectReader(const std::string& tag_name, object_read_f* reader);
71
77 struct PLASK_API RegisterObjectReader {
78 RegisterObjectReader(const std::string& tag_name, object_read_f* reader) {
79 GeometryReader::registerObjectReader(tag_name, reader);
80 }
81 };
82
89 const char* expectedSuffix;
90
98 typedef std::function<GeometryObject::Changer*(GeometryReader& reader)> changer_read_f;
99
104 static std::map<std::string, changer_read_f>& changerReaders();
105
111 static void registerChangerReader(const std::string& tag_name, changer_read_f reader);
112
118 struct PLASK_API RegisterChangerReader {
119 RegisterChangerReader(const std::string& tag_name, changer_read_f reader) {
120 GeometryReader::registerChangerReader(tag_name, reader);
121 }
122 };
123
124 const AxisNames& getAxisNames() const;
125
131 std::string getAxisName(std::size_t axis_index);
132
137 std::string getAxisLongName() { return getAxisName(axis::lon_index); }
138
143 std::string getAxisTranName() { return getAxisName(axis::tran_index); }
144
149 std::string getAxisVertName() { return getAxisName(axis::up_index); }
150
154 struct PLASK_API SetExpectedSuffix {
155 GeometryReader& reader;
156 const char* old;
157 SetExpectedSuffix(GeometryReader& reader, const char* new_expected_suffix);
158 SetExpectedSuffix(GeometryReader& reader, int dim);
159 ~SetExpectedSuffix() { reader.expectedSuffix = old; }
160 };
161
165 struct PLASK_API RevertMaterialsAreRequired {
166 GeometryReader& reader;
167 bool old;
168 RevertMaterialsAreRequired(GeometryReader &reader): reader(reader), old(reader.materialsAreRequired) {}
169 RevertMaterialsAreRequired(GeometryReader& reader, bool new_value): reader(reader), old(reader.materialsAreRequired) { reader.materialsAreRequired = new_value; }
170 ~RevertMaterialsAreRequired() { reader.materialsAreRequired = old; }
171 };
172
174 Manager& manager;
175
177 XMLReader& source;
178
180 const MaterialsDB* materialsDB;
181
189 shared_ptr<Material> getMaterial(const std::string& material_full_name) const;
190
191 shared_ptr<MaterialsDB::MixedCompositionFactory> getMixedCompositionFactory(const std::string& material1_full_name,
192 const std::string& material2_full_name,
193 double shape=1.) const;
194
201 shared_ptr<Material> requireMaterial() const {
202 try {
203 return getMaterial(source.requireAttribute(XML_MATERIAL_ATTR));
204 } catch (const XMLNoAttrException& err) {
205 manager.throwErrorIfNotDraft(err);
206 return plask::make_shared<DummyMaterial>("");
207 }
208 }
209
213 SolidOrGradientMaterial requireSolidOrGradientMaterial() const;
214
220 GeometryReader(Manager& manager, XMLReader& source, const MaterialsDB& materialsDB = MaterialsDB::getDefault());
221
234 shared_ptr<GeometryObject> readObject();
235
243 shared_ptr<GeometryObject> readExactlyOneChild();
244
254 template <typename RequiredObjectType>
255 shared_ptr<RequiredObjectType> readObject();
256
262 template <typename RequiredObjectType>
263 shared_ptr<RequiredObjectType> readExactlyOneChild();
264
269 shared_ptr<Geometry> readGeometry();
270
277 shared_ptr<GeometryObject> requireObjectWithName(const std::string& name) const;
278
285 shared_ptr<GeometryObject> requireObjectFromAttribute(const std::string& attr) const {
286 try {
287 return requireObjectWithName(source.requireAttribute(attr));
288 } catch (const XMLNoAttrException& err) {
289 manager.throwErrorIfNotDraft(err);
290 return shared_ptr<GeometryObject>();
291 }
292 }
293
301 void registerObjectName(const std::string& name, shared_ptr<GeometryObject> object);
302
310 void registerObjectName(const plask::optional<std::string>& name, shared_ptr<GeometryObject> object) {
311 if (name) registerObjectName(*name, object);
312 }
313
321 void registerObjectName(const plask::optional<const std::string>& name, shared_ptr<GeometryObject> object) {
322 if (name) registerObjectName(*name, object);
323 }
324
325
333 void registerObjectNameFromCurrentNode(shared_ptr<GeometryObject> object) {
334 auto name = source.getAttribute(XML_NAME_ATTR);
335 if (name) {
336 std::replace(name->begin(), name->end(), '-', '_');
337 registerObjectName(*name, object);
338 }
339 }
340
341};
342
343// specialization for most types
344 template <typename RequiredObjectType>
345 inline shared_ptr<RequiredObjectType> GeometryReader::readObject() {
346 shared_ptr<RequiredObjectType> result = dynamic_pointer_cast<RequiredObjectType>(readObject());
347 if (!result) manager.throwErrorIfNotDraft(UnexpectedGeometryObjectTypeException());
348 return result;
349}
350
351// specialization for GeometryObject which doesn't require dynamic_cast
352 template <>
353 inline shared_ptr<GeometryObject> GeometryReader::readObject<GeometryObject>() {
354 return readObject();
355}
356
357// specialization for most types
358 template <typename RequiredObjectType>
359 inline shared_ptr<RequiredObjectType> GeometryReader::readExactlyOneChild() {
360 shared_ptr<GeometryObject> before_cast;
361 bool require_end = true;
362 if (source.requireNext((!manager.draft)
363 ? XMLReader::NODE_ELEMENT
364 : (XMLReader::NODE_ELEMENT | XMLReader::NODE_ELEMENT_END)) == XMLReader::NODE_ELEMENT)
365 before_cast = readObject();
366 else
367 require_end = false;
368 if (!require_end && manager.draft) {
369 manager.pushError(XMLUnexpectedElementException(source, "new tag"));
370 return shared_ptr<RequiredObjectType>();
371 }
372 shared_ptr<RequiredObjectType> result = dynamic_pointer_cast<RequiredObjectType>(before_cast);
373 if (!result) manager.throwErrorIfNotDraft(UnexpectedGeometryObjectTypeException());
374 if (require_end) source.requireTagEnd();
375 return result;
376}
377
378// specialization for GeometryObject which doesn't required dynamic_cast
379 template <>
380 inline shared_ptr<GeometryObject> GeometryReader::readExactlyOneChild<GeometryObject>() {
381 return readExactlyOneChild();
382}
383
384/*template <typename FunctorType, typename RequiredObjectType>
385 inline void GeometryReader::readAllObjects(XMLReader& source, FunctorType functor) {
386 while(source.read()) {
387 switch (source.getNodeType()) {
388 case irr::io::EXN_ELEMENT_END: return;
389 case irr::io::EXN_ELEMENT: functor(readObject<RequiredObjectType>(source));
390 //TODO what with all other XML types (which now are just ignored)?
391 }
392 }
393}*/
394
395} // namespace plask
396
397#endif // PLASK__GEOMETRY_READER_H