source: Revenant/yamlprovider/src/yamlgmcfgrd.cpp@ 4962c49

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

Introduce CLI Terrain Generator utility

  • Property mode set to 100755
File size: 9.4 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()), _pNodes(new NodeVector()), _input(input)
120 {}
121
122 YAMLGeoMorphConfigReader::~YAMLGeoMorphConfigReader()
123 {
124 for (FactoryVector::iterator i = _pList->begin(); i != _pList->end(); ++i)
125 delete *i;
126 delete _pList;
127 delete _pNodes;
128 }
129
130 IConfigFactoryBase * YAMLGeoMorphConfigReader::readNext()
131 {
132 using namespace YAML;
133 Node node = Load(_input);
134
135 if (node.IsNull())
136 return NULL;
137
138 if (node.Type() != NodeType::Map)
139 throw GMMalformedConfigEx("Expected map"); // TODO: Proper exception handling
140
141 std::string sName, sAlias;
142
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 _pNodes->push_back(node);
171 _pList->push_back(pFactory);
172 return pFactory;
173 }
174
175 GeoTemplatePhase YAMLGeoMorphConfigReader::getPhaseFor( const std::string & sPhase )
176 {
177 if (sPhase == "pre")
178 return geoworld::GTP_Pre;
179 else if (sPhase == "post")
180 return geoworld::GTP_Post;
181 else
182 throw InvalidPhaseName();
183 }
184
185 geoworld::IConfigGMFactory * YAMLGeoMorphConfigReader::readGMFactory(const std::string & sName, const std::string & sAlias, const YAML::Node * pndConfigSection)
186 {
187 IConfigGMFactory::Settings settings;
188
189 (*pndConfigSection)["frequency"] >> settings.frequency;
190 return new GMFactory(sName, sAlias, (*pndConfigSection)["parameters"], settings);
191 }
192
193 geoworld::IConfigGTFactory * YAMLGeoMorphConfigReader::readGTFactory(const std::string & sName, const std::string & sAlias, const YAML::Node * pndConfigSection)
194 {
195 IConfigGTFactory::Settings settings;
196
197 std::string sPhase;
198
199 (*pndConfigSection)["phase"] >> sPhase;
200 try
201 {
202 settings.phase = getPhaseFor(sPhase);
203 }
204 catch (InvalidPhaseName &)
205 {
206 throw YAML::InvalidScalar(pndConfigSection->Mark());
207 }
208
209 return new GTFactory(sName, sAlias, (*pndConfigSection)["parameters"], settings);
210 }
211
212
213 ConfigSection::ConfigSection( const YAML::Node & nd )
214 : _node(nd)
215 {
216 if (nd.Type() != YAML::NodeType::Map)
217 throw GMMalformedConfigEx("Expected map");
218 }
219
220 ConfigSection::~ConfigSection()
221 {
222 for (Map::iterator i = _map.begin(); i != _map.end(); ++i)
223 delete i->second;
224 }
225
226 const IConfigValue * ConfigSection::operator [] ( const std::string & sKey ) const
227 {
228 ConfigValue * pValue = NULL;
229
230 if (_map.find(sKey) == _map.end())
231 {
232 pValue = new ConfigValue(_node[sKey]);
233 _map[sKey] = pValue;
234 } else
235 pValue = _map[sKey];
236
237 return pValue;
238 }
239
240 ConfigSequence::ConfigSequence( const YAML::Node & nd )
241 : _node(nd)
242 {
243 if (nd.Type() != YAML::NodeType::Sequence)
244 throw GMMalformedConfigEx("Expected sequence");
245 }
246
247 ConfigSequence::~ConfigSequence()
248 {
249 for (List::iterator i = _list.begin(); i != _list.end(); ++i)
250 delete *i;
251 }
252
253 const IConfigValue * ConfigSequence::operator [] ( const size_t & nIdx ) const
254 {
255 ConfigValue * pValue = NULL;
256
257 if (nIdx >= _list.size())
258 {
259 _list.resize(nIdx + 1);
260 pValue = new ConfigValue(_node[nIdx]);
261 _list[nIdx] = pValue;
262 } else
263 pValue = _list[nIdx];
264
265 return pValue;
266 }
267
268 std::string & ConfigValue::operator >> ( std::string & out ) const
269 {
270 try
271 {
272 _node >> out;
273 return out;
274 }
275 catch (YAML::TypedKeyNotFound< std::string > & e)
276 {
277 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
278 }
279 }
280
281 IConfigSection * ConfigValue::operator >>( IConfigSection * & pSection ) const
282 {
283 if (_sect == NULL)
284 _sect = new ConfigSection(_node);
285
286 return _sect;
287 }
288
289 IConfigSequence * ConfigValue::operator>>( IConfigSequence * & pSequence ) const
290 {
291 if (_seq == NULL)
292 _seq = new ConfigSequence(_node);
293
294 return _seq;
295 }
296
297 float & ConfigValue::operator >> ( float & out ) const
298 {
299 try
300 {
301 _node >> out;
302 }
303 catch (YAML::TypedKeyNotFound< std::string > & e)
304 {
305 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
306 }
307 return out;
308 }
309
310 bool & ConfigValue::operator >> (bool & out) const
311 {
312 try
313 {
314 _node >> out;
315 }
316 catch (YAML::TypedKeyNotFound< std::string > & e)
317 {
318 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
319 }
320 return out;
321 }
322 unsigned int & ConfigValue::operator >> (unsigned int & out) const
323 {
324 try
325 {
326 _node >> out;
327 }
328 catch (YAML::TypedKeyNotFound< std::string > & e)
329 {
330 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
331 }
332 return out;
333 }
334
335 unsigned short & ConfigValue::operator >>( unsigned short & out ) const
336 {
337 try
338 {
339 _node >> out;
340 }
341 catch (YAML::TypedKeyNotFound< std::string > & e)
342 {
343 throw GMInvalidPropertyEx(e.key, e.msg.c_str());
344 }
345 return out;
346 }
347
348 VectorTag< GeoHeightMap::Precision >::V2 & ConfigValue::operator >>( VectorTag< GeoHeightMap::Precision >::V2 & out ) const
349 {
350 if (_node.Type() != YAML::NodeType::Sequence)
351 throw GMMalformedConfigEx("Expected a sequence");
352
353 return out = VectorTag< GeoHeightMap::Precision >::V2 (_node[0].as<GeoHeightMap::Precision>(), _node[1].as<GeoHeightMap::Precision>());
354 }
355
356 VectorTag< GeoHeightMap::Precision >::V3 & ConfigValue::operator >>( VectorTag< GeoHeightMap::Precision >::V3 & out ) const
357 {
358 using Numba = GeoHeightMap::Precision;
359 if (_node.Type() != YAML::NodeType::Sequence)
360 throw GMMalformedConfigEx("Expected a sequence");
361
362 return out = VectorTag< Numba >::V3 (
363 _node[0].as<Numba>(),
364 _node[1].as<Numba>(),
365 _node[2].as<Numba>()
366 );
367 }
368
369 mars::RangeX< double > & ConfigValue::toRange( mars::RangeX< double > & out ) const
370 {
371 try
372 {
373 return out = autorange< double >();
374 }
375 catch (YAML::TypedKeyNotFound< int > & e)
376 {
377 throw GMIndexOutOfBoundsEx(e.key, e.msg);
378 }
379 }
380
381 mars::RangeX< long > & ConfigValue::toRange( mars::RangeX< long > & out ) const
382 {
383 try
384 {
385 return out = autorange< long >();
386 }
387 catch (YAML::TypedKeyNotFound< int > & e)
388 {
389 throw GMIndexOutOfBoundsEx(e.key, e.msg);
390 }
391 }
392
393 ConfigValue::ConfigValue( const YAML::Node & nd )
394 : _node(nd), _sect(NULL), _seq(NULL) {}
395
396 ConfigValue::~ConfigValue()
397 {
398 delete _sect;
399 delete _seq;
400 }
401
402}
Note: See TracBrowser for help on using the repository browser.