source: Revenant/yamlprovider/src/yamlgmcfgrd.cpp

port/mars-tycoon
Last change on this file was aad5afa, checked in by Jonathan Neufeld <support@…>, 3 years ago

Fix YAML provider bugs preventing YAML configurations from loading properly.

  • Property mode set to 100755
File size: 9.3 KB
Line 
1#include "yamlgmcfgrd.h"
2
3#include "yamlext.h"
4
5#include <yaml.h>
6
7#include <iostream>
8#include <fstream>
9#include <sstream>
10
11#include <gwconfig.h>
12
13namespace genesis
14{
15 using namespace geoworld;
16
17 class ConfigValue : public IConfigValue
18 {
19 protected:
20 const YAML::Node _node;
21 mutable IConfigSection * _sect;
22 mutable IConfigSequence * _seq;
23
24 template< typename T >
25 mars::Range< T > autorange () const
26 {
27 T min, max;
28
29 if (_node.Type() == YAML::NodeType::Sequence)
30 {
31 _node[0] >> min;
32 _node[1] >> max;
33 } else
34 {
35 _node >> min;
36 _node >> max;
37 }
38
39 return mars::Range< T > (min, max);
40 }
41
42 virtual mars::RangeX< double > & toRange (mars::RangeX< double > & out) const;
43 virtual mars::RangeX< long > & toRange (mars::RangeX< long > & out) const;
44
45 public:
46 ConfigValue( const YAML::Node & nd );
47
48 virtual IConfigSection * operator >> (IConfigSection * & pSection) const;
49 virtual IConfigSequence * operator >> (IConfigSequence * & pSequence) const;
50 virtual std::string & operator >> (std::string & out) const;
51 virtual float & operator >> (float & out) const;
52 virtual bool & operator >> (bool & out) const;
53 virtual unsigned int & operator >> (unsigned int & out) const;
54 virtual unsigned short & operator >> (unsigned short & out) const;
55
56 virtual VectorTag< GeoHeightMap::Precision >::V2 & operator >> (VectorTag< GeoHeightMap::Precision >::V2 & out) const;
57 virtual VectorTag< GeoHeightMap::Precision >::V3 & operator >> (VectorTag< GeoHeightMap::Precision >::V3 & out) const;
58
59 virtual ~ConfigValue();
60 };
61
62 class ConfigSection : public IConfigSection
63 {
64 private:
65 typedef std::map< std::string, ConfigValue * > Map;
66
67 mutable Map _map;
68 const YAML::Node _node;
69
70 public:
71 ConfigSection( const YAML::Node & nd );
72
73 virtual const IConfigValue * operator []( const std::string & sKey ) const;
74
75 virtual ~ConfigSection();
76 };
77
78 class ConfigSequence : public IConfigSequence
79 {
80 private:
81 typedef std::vector< ConfigValue * > List;
82
83 mutable List _list;
84 const YAML::Node _node;
85
86 public:
87 ConfigSequence( const YAML::Node & nd );
88
89 virtual const IConfigValue * operator []( const size_t & nIdx ) const;
90
91 virtual ~ConfigSequence();
92 };
93
94 class GMFactory : public IConfigGMFactory
95 {
96 private:
97 ConfigSection _section;
98
99 public:
100 GMFactory(const std::string & name, const std::string & alias, const YAML::Node & nd, const Settings & settings)
101 : IConfigGMFactory(name, alias, settings), _section(nd) {}
102
103 virtual IConfigSection * getSection() { return &_section; }
104 };
105
106 class GTFactory : public IConfigGTFactory
107 {
108 private:
109 ConfigSection _section;
110
111 public:
112 GTFactory(const std::string & name, const std::string & alias, const YAML::Node & nd, const Settings & settings)
113 : IConfigGTFactory(name, alias, settings), _section(nd) {}
114
115 virtual IConfigSection * getSection() { return &_section; }
116 };
117
118 YAMLGeoMorphConfigReader::YAMLGeoMorphConfigReader(std::istream & input)
119 : _pList(new FactoryVector()), _docs(YAML::LoadAll(input)), _i(_docs.begin())
120 {}
121
122 YAMLGeoMorphConfigReader::~YAMLGeoMorphConfigReader()
123 {
124 for (FactoryVector::iterator i = _pList->begin(); i != _pList->end(); ++i)
125 delete *i;
126 delete _pList;
127 }
128
129 IConfigFactoryBase * YAMLGeoMorphConfigReader::readNext()
130 {
131 using namespace YAML;
132 Node node = *_i++;
133
134 if (node.IsNull())
135 return NULL;
136
137 if (node.Type() != NodeType::Map)
138 throw GMMalformedConfigEx("Expected map"); // TODO: Proper exception handling
139
140 std::string sName, sAlias;
141
142 auto rruj = Dump(node);
143 node["factory"] >> sName;
144
145 try
146 {
147 node["alias"] >> sAlias;
148 }
149 catch (YAML::TypedKeyNotFound< std::string >)
150 {
151 sAlias = sName;
152 }
153
154 IConfigFactoryBase * pFactory;
155
156 try {
157 if (node.Tag() == "!template")
158 pFactory = readGTFactory(sName, sAlias, &node);
159 else
160 if (node.Tag() == "!morph" || node.Tag().empty())
161 pFactory = readGMFactory(sName, sAlias, &node);
162 else
163 throw GMMalformedConfigEx("Unknown document tag type: " + node.Tag());
164 }
165 catch (YAML::RepresentationException &)
166 {
167 throw GMMalformedConfigEx("Malformed");
168 }
169
170 _pList->push_back(pFactory);
171 return pFactory;
172 }
173
174 GeoTemplatePhase YAMLGeoMorphConfigReader::getPhaseFor( const std::string & sPhase )
175 {
176 if (sPhase == "pre")
177 return geoworld::GTP_Pre;
178 else if (sPhase == "post")
179 return geoworld::GTP_Post;
180 else
181 throw InvalidPhaseName();
182 }
183
184 geoworld::IConfigGMFactory * YAMLGeoMorphConfigReader::readGMFactory(const std::string & sName, const std::string & sAlias, const YAML::Node * pndConfigSection)
185 {
186 IConfigGMFactory::Settings settings;
187
188 (*pndConfigSection)["frequency"] >> settings.frequency;
189 return new GMFactory(sName, sAlias, (*pndConfigSection)["parameters"], settings);
190 }
191
192 geoworld::IConfigGTFactory * YAMLGeoMorphConfigReader::readGTFactory(const std::string & sName, const std::string & sAlias, const YAML::Node * pndConfigSection)
193 {
194 IConfigGTFactory::Settings settings;
195
196 std::string sPhase;
197
198 (*pndConfigSection)["phase"] >> sPhase;
199 try
200 {
201 settings.phase = getPhaseFor(sPhase);
202 }
203 catch (InvalidPhaseName &)
204 {
205 throw YAML::InvalidScalar(pndConfigSection->Mark());
206 }
207
208 return new GTFactory(sName, sAlias, (*pndConfigSection)["parameters"], settings);
209 }
210
211
212 ConfigSection::ConfigSection( const YAML::Node & nd )
213 : _node(nd)
214 {
215 if (nd.Type() != YAML::NodeType::Map)
216 throw GMMalformedConfigEx("Expected map");
217 }
218
219 ConfigSection::~ConfigSection()
220 {
221 for (Map::iterator i = _map.begin(); i != _map.end(); ++i)
222 delete i->second;
223 }
224
225 const IConfigValue * ConfigSection::operator [] ( const std::string & sKey ) const
226 {
227 ConfigValue * pValue = NULL;
228
229 if (_map.find(sKey) == _map.end())
230 {
231 pValue = new ConfigValue(_node[sKey]);
232 _map[sKey] = pValue;
233 } else
234 pValue = _map[sKey];
235
236 return pValue;
237 }
238
239 ConfigSequence::ConfigSequence( const YAML::Node & nd )
240 : _node(nd)
241 {
242 if (nd.Type() != YAML::NodeType::Sequence)
243 throw GMMalformedConfigEx("Expected sequence");
244 }
245
246 ConfigSequence::~ConfigSequence()
247 {
248 for (List::iterator i = _list.begin(); i != _list.end(); ++i)
249 delete *i;
250 }
251
252 const IConfigValue * ConfigSequence::operator [] ( const size_t & nIdx ) const
253 {
254 ConfigValue * pValue = NULL;
255
256 if (nIdx >= _list.size())
257 {
258 _list.resize(nIdx + 1);
259 pValue = new ConfigValue(_node[nIdx]);
260 _list[nIdx] = pValue;
261 } else
262 pValue = _list[nIdx];
263
264 return pValue;
265 }
266
267 std::string & ConfigValue::operator >> ( std::string & out ) const
268 {
269 try
270 {
271 _node >> out;
272 return out;
273 }
274 catch (YAML::TypedKeyNotFound< std::string > & e)
275 {
276 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
277 }
278 }
279
280 IConfigSection * ConfigValue::operator >>( IConfigSection * & pSection ) const
281 {
282 if (_sect == NULL)
283 _sect = new ConfigSection(_node);
284
285 return _sect;
286 }
287
288 IConfigSequence * ConfigValue::operator>>( IConfigSequence * & pSequence ) const
289 {
290 if (_seq == NULL)
291 _seq = new ConfigSequence(_node);
292
293 return _seq;
294 }
295
296 float & ConfigValue::operator >> ( float & out ) const
297 {
298 try
299 {
300 _node >> out;
301 }
302 catch (YAML::TypedKeyNotFound< std::string > & e)
303 {
304 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
305 }
306 return out;
307 }
308
309 bool & ConfigValue::operator >> (bool & out) const
310 {
311 try
312 {
313 _node >> out;
314 }
315 catch (YAML::TypedKeyNotFound< std::string > & e)
316 {
317 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
318 }
319 return out;
320 }
321 unsigned int & ConfigValue::operator >> (unsigned int & out) const
322 {
323 try
324 {
325 _node >> out;
326 }
327 catch (YAML::TypedKeyNotFound< std::string > & e)
328 {
329 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
330 }
331 return out;
332 }
333
334 unsigned short & ConfigValue::operator >>( unsigned short & out ) const
335 {
336 try
337 {
338 _node >> out;
339 }
340 catch (YAML::TypedKeyNotFound< std::string > & e)
341 {
342 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
343 }
344 return out;
345 }
346
347 VectorTag< GeoHeightMap::Precision >::V2 & ConfigValue::operator >>( VectorTag< GeoHeightMap::Precision >::V2 & out ) const
348 {
349 if (_node.Type() != YAML::NodeType::Sequence)
350 throw GMMalformedConfigEx("Expected a sequence");
351
352 return out = VectorTag< GeoHeightMap::Precision >::V2 (_node[0].as<GeoHeightMap::Precision>(), _node[1].as<GeoHeightMap::Precision>());
353 }
354
355 VectorTag< GeoHeightMap::Precision >::V3 & ConfigValue::operator >>( VectorTag< GeoHeightMap::Precision >::V3 & out ) const
356 {
357 using Numba = GeoHeightMap::Precision;
358 if (_node.Type() != YAML::NodeType::Sequence)
359 throw GMMalformedConfigEx("Expected a sequence");
360
361 return out = VectorTag< Numba >::V3 (
362 _node[0].as<Numba>(),
363 _node[1].as<Numba>(),
364 _node[2].as<Numba>()
365 );
366 }
367
368 mars::RangeX< double > & ConfigValue::toRange( mars::RangeX< double > & out ) const
369 {
370 try
371 {
372 return out = autorange< double >();
373 }
374 catch (YAML::TypedKeyNotFound< int > & e)
375 {
376 throw GMIndexOutOfBoundsEx(e.key, e.msg);
377 }
378 }
379
380 mars::RangeX< long > & ConfigValue::toRange( mars::RangeX< long > & out ) const
381 {
382 try
383 {
384 return out = autorange< long >();
385 }
386 catch (YAML::TypedKeyNotFound< int > & e)
387 {
388 throw GMIndexOutOfBoundsEx(e.key, e.msg);
389 }
390 }
391
392 ConfigValue::ConfigValue( const YAML::Node & nd )
393 : _node(nd), _sect(NULL), _seq(NULL) {}
394
395 ConfigValue::~ConfigValue()
396 {
397 delete _sect;
398 delete _seq;
399 }
400
401}
Note: See TracBrowser for help on using the repository browser.