source: Revenant/yamlprovider/src/yamlminreader.cpp@ 25c4774

port/mars-tycoon
Last change on this file since 25c4774 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: 15.6 KB
RevLine 
[80a6a52]1#include "yamlminreader.h"
2
3#include "yamlext.h"
4
5#include <iostream>
6#include <fstream>
7#include <stdarg.h>
8
9#include <assert.h>
10
11namespace genesis
12{
13 using namespace geoworld;
14
15 static void operator >> (const YAML::Node & nd, geoworld::PointScale & pt)
16 {
17 unsigned value = static_cast <unsigned> (pt);
18 nd >> value;
19 pt = static_cast <geoworld::PointScale> (value);
20 }
21
22 static void operator >> (const YAML::Node & nd, geoworld::MineralPtr & mineral)
23 {
24 std::string id;
25 nd >> id;
26 mineral = id;
27 }
28 static void operator >> (const YAML::Node & nd, geoworld::MinClassPtr & rock)
29 {
30 std::string id;
31 nd >> id;
32 rock = id;
33 }
34
35 inline static void operator >> (const YAML::Node & nd, geoworld::PhasePoint & pp)
36 {
37 nd[0] >> pp.temperature;
38 nd[1] >> pp.pressure;
39 }
40
41 class MineralsYAMLReaderImpl
42 {
43 private:
[aad5afa]44 typedef std::vector< YAML::Node > NodeVector;
45
[80a6a52]46 geoworld::PetrogenyDef * _defPetroDef;
[aad5afa]47 NodeVector _docs;
[80a6a52]48
49 public:
50 template <typename T>
51 void readScalarOrSequence (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::list<T> & collection);
52 template <typename T>
53 void readScalarOrSequence (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::vector<T> & collection);
54 template <typename T, typename L>
55 void readScalarOrSequenceA (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), L & collection);
56 template <typename T, int N>
57 void readScalarOrBitset (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::bitset<N> & bset);
58
59 void readGroupDef( IMineralsDatabase * pMinDB, const YAML::Node & nd, mars::ptr<geoworld::MineralGroupDef> & group );
60 void readClassDefinition ( const YAML::Node & nd, mars::ptr<geoworld::MineralClass> & rclass);
61 void readMineralDef( const YAML::Node &nd, mars::ptr<geoworld::MineralDef> & mineral );
62
63 void readClassDisposition( const YAML::Node &nd, geoworld::MineralClass::Disposition & disposition );
64 void readYield (const YAML::Node & nd, geoworld::MineralDef::YieldSet & set);
65 void readGenesis (const YAML::Node & nd, geoworld::PetrogenyDef & mineral);
66 void readEnvironment (const YAML::Node & nd, geoworld::MinClassPtr & clazz);
67 void readAssociation (const YAML::Node & nd, geoworld::MineralReference & assoc);
68 void readDistribution (const YAML::Node & nd, geoworld::DepositDistribution & distribution);
69 void readSediment (const YAML::Node & nd, geoworld::Sediment & sediment);
70
71 void resolveReferences ();
72 void resolve( geoworld::MineralPtr & rWRef );
73
74 template <typename E>
75 static void strToEnumV (const std::string & str, E & enRet, const char * szKey, va_list & vl);
76
77 template <typename E>
78 static void strToEnumOrPtSc (const YAML::Node & nd, E & enRet, geoworld::PointScale & ptsc, const char * szFirst, ...);
79
80 template <typename E>
81 static void strToEnum (const YAML::Node & nd, E & enRet, const char * szFirst, ...);
82 template <typename E>
83 static void strToEnum (const std::string & str, E & enRet, const char * szFirst, ...);
84
85 MineralsYAMLReaderImpl(std::istream & input);
86
87 virtual bool load (IMineralsDatabase * pMinDB);
88 };
89
90 MineralsYAMLReaderImpl::MineralsYAMLReaderImpl(std::istream & input)
[aad5afa]91 : _docs(YAML::LoadAll(input)) {}
[80a6a52]92
93 template <typename E>
94 void MineralsYAMLReaderImpl::strToEnum( const std::string & str, E & enRet, const char * szFirst, ... )
95 {
96 va_list vl;
97
98 va_start(vl, enRet);
99 strToEnumV(str, enRet, szFirst, vl);
100 va_end(vl);
101 }
102
103 template <typename E>
104 void MineralsYAMLReaderImpl::strToEnum( const YAML::Node & nd, E & enRet, const char * szFirst, ... )
105 {
106 std::string sKey;
107 va_list vl;
108
109 nd >> sKey;
110 va_start(vl, szFirst);
111 strToEnumV(sKey, enRet, szFirst, vl);
112 va_end(vl);
113 }
114
115 template <typename E>
116 void MineralsYAMLReaderImpl::strToEnumOrPtSc( const YAML::Node & nd, E & enRet, geoworld::PointScale & ptsc, const char * szFirst, ... )
117 {
118 std::string sKey;
119 va_list vl;
120 int i;
121
122 nd >> sKey;
123 i = atoi(sKey.c_str());
124
125 if (i > 0 || sKey == "0")
126 ptsc = static_cast <PointScale> (i);
127 else
128 {
129 va_start(vl, szFirst);
130 strToEnumV(sKey, enRet, szFirst, vl);
131 va_end(vl);
132 }
133 }
134
135 template <typename E>
136 void MineralsYAMLReaderImpl::strToEnumV( const std::string & str, E & enRet, const char * szKey, va_list & vl )
137 {
138 while (szKey != NULL)
139 {
140 const E enVal = static_cast< E > (va_arg(vl, int));
141
142 if (str == szKey)
143 enRet = enVal;
144
145 szKey = va_arg(vl, const char *);
146 }
147 }
148
149 template <typename T, int N>
150 void MineralsYAMLReaderImpl::readScalarOrBitset( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::bitset<N> & bset )
151 {
152 using namespace YAML;
153
154 if (nd.Type() == NodeType::Sequence)
155 {
156 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
157 {
158 T data;
159 (this->*fnProc)(*it, data);
160 if (data > 0 && data < N)
161 bset.set(data);
162 }
163 } else
164 {
165 T data;
166 (this->*fnProc)(nd, data);
167 if (data > 0 && data < N)
168 bset.set(data);
169 }
170 }
171
172 template <typename T, typename L>
173 void MineralsYAMLReaderImpl::readScalarOrSequenceA( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), L & collection )
174 {
175 using namespace YAML;
176
177 if (nd.Type() == NodeType::Sequence)
178 {
179 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
180 {
181 T data;
182 (this->*fnProc)(*it, data);
183 collection.push_back(data);
184 }
185 } else
186 {
187 T data;
188 (this->*fnProc)(nd, data);
189 collection.push_back(data);
190 }
191 }
192
193 template <typename T>
194 void MineralsYAMLReaderImpl::readScalarOrSequence( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::vector<T> & collection )
195 {
196 readScalarOrSequenceA<T, std::vector< T > >(nd, fnProc, collection);
197 }
198
199 template <typename T>
200 void MineralsYAMLReaderImpl::readScalarOrSequence( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::list<T> & collection )
201 {
202 readScalarOrSequenceA<T, std::list< T > >(nd, fnProc, collection);
203 }
204
205 void MineralsYAMLReaderImpl::readYield (const YAML::Node & nd, MineralDef::YieldSet & set)
206 {
207 using namespace YAML;
208
209 for (const_iterator itchem = nd.begin(); itchem != nd.end(); ++itchem)
210 {
211 std::string smin;
212 const Node & ndParticle = itchem->second;
213 float pct, flux = 0.0f;
214
215 if (ndParticle.Type() == NodeType::Scalar)
216 ndParticle >> pct;
217 else
218 {
219 ndParticle[0] >> pct;
220 ndParticle[1] >> flux;
221 }
222 itchem->first >> smin;
223
224 set.add (MineralDef::YieldMin (smin, pct, flux));
225 }
226 }
227
228 void MineralsYAMLReaderImpl::readClassDefinition ( const YAML::Node & nd, mars::ptr <MineralClass> & rclass)
229 {
230 using namespace YAML;
231
232 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
233 {
234 std::string key;
235 it->first >> key;
236
237 if (key == "class")
238 {
239 it->second >> rclass->name;
240 }
241 else if (key == "type")
242 {
243 strToEnum(it->second, rclass->type,
244 "igneous", MineralClass::Type_Igneous,
245 "sedimentary", MineralClass::Type_Sedimentary,
246 NULL
247 );
248 }
249 else if (key == "dispositions")
250 {
251 readScalarOrSequence (it->second, &MineralsYAMLReaderImpl::readClassDisposition, rclass->dispositions);
252 }
253 }
254 }
255
256 void MineralsYAMLReaderImpl::readGenesis( const YAML::Node & nd, PetrogenyDef & genesis )
257 {
258 using namespace YAML;
259
260 genesis = *this->_defPetroDef;
261
262 // TODO: Implement exception throwing rules
263 for (const_iterator it2 = nd.begin(); it2 != nd.end(); ++it2)
264 {
265 std::string key;
266 it2->first >> key;
267
268 if (key == "distribution")
269 {
270 readScalarOrBitset< DepositDistribution, CountDist >(it2->second, &MineralsYAMLReaderImpl::readDistribution, genesis.distributions);
271 } else if (key == "abundance")
272 {
273 it2->second >> genesis.abundance;
274 } else if (key == "size")
275 {
276 it2->second >> genesis.size;
277 } else if (key == "association")
278 {
279 readScalarOrSequence(it2->second, &MineralsYAMLReaderImpl::readAssociation, genesis.associations);
280 } else if (key == "host")
281 {
282 readAssociation(it2->second, genesis.host);
283 } else if (key == "environment")
284 {
285 readScalarOrSequence(it2->second, &MineralsYAMLReaderImpl::readEnvironment, genesis.environments);
286 } else
287 continue;
288 }
289 }
290 void MineralsYAMLReaderImpl::readMineralDef( const YAML::Node &nd, mars::ptr<MineralDef> & mineral )
291 {
292 using namespace YAML;
293
294 assert(mineral != NULL);
295
296 this->_defPetroDef = new PetrogenyDef();
297 try
298 {
299 readGenesis(nd["deposit"], *this->_defPetroDef);
300 }
301 catch (YAML::TypedKeyNotFound <std::string> &) {}
302
303 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
304 {
305 std::string key;
306 const YAML::Node & val = it->second;
307
308 it->first >> key;
309
310 if (key == "mineral")
311 val >> mineral->name;
312 else if (key == "boiling_point")
313 val >> mineral->boiling_point;
314 else if (key == "melting_point")
315 val >> mineral->melting_point;
316 else if (key == "triple_point")
317 val >> mineral->triple_point;
318 else if (key == "critical_point")
319 val >> mineral->critical_point;
320 else if (key == "sublimation_point")
321 val >> mineral->sublimation_point;
322 else if (key == "geochemistry")
323 readScalarOrSequence(val, &MineralsYAMLReaderImpl::readYield, mineral->yields);
324 else if (key == "genesis")
325 readScalarOrSequence(val, &MineralsYAMLReaderImpl::readGenesis, mineral->genesis);
326 else if (key == "class")
327 val >> mineral->clazz;
328 }
329 delete this->_defPetroDef;
330 }
331
332 void MineralsYAMLReaderImpl::readClassDisposition( const YAML::Node &nd, MineralClass::Disposition & disposition )
333 {
334 using namespace YAML;
335
336 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
337 {
338 try
339 {
340 std::string key;
341 it->first >> key;
342
343 if (key == "silica")
344 {
345 strToEnumOrPtSc(it->second, disposition.silica.base, disposition.silica.numeric,
346 "ultra-mafic", Silica_UltraMafic,
347 "mafic", Silica_Mafic,
348 "intermediate", Silica_Intermediate,
349 "inter-felsic", Silica_InterFelsic,
350 "felsic", Silica_Felsic,
351 NULL
352 );
353 } else if (key == "origin")
354 {
355 strToEnum(it->second, disposition.origin,
356 "volcanic", Origin_Volcanic,
357 "subvolcanic", Origin_Subvolcanic,
358 "plutonic", Origin_Plutonic,
359 "meteoritic", Origin_Meteoritic,
360 NULL
361 );
362 } else if (key == "temperature")
363 {
364 it->second >> disposition.temperature;
365 } else if (key == "pressure")
366 {
367 it->second >> disposition.pressure;
368 } else if (key == "sediment")
369 {
370 readScalarOrBitset<Sediment, Sediment_COUNT> (it->second, &MineralsYAMLReaderImpl::readSediment, disposition.sediment);
371 } else if (key == "weathered")
372 {
373 it->second >> disposition.weathered;
374 }
375 }
376 catch (YAML::RepresentationException &)
377 {
378
379 }
380 }
381 }
382
383 void MineralsYAMLReaderImpl::readAssociation( const YAML::Node & nd, MineralReference & assoc )
384 {
385 using namespace YAML;
386
387 std::string name;
388
389 if (nd.Type() == NodeType::Map)
390 {
391 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
392 {
393 std::string key;
394 it->first >> key;
395
396 if (key == "mineral")
397 it->second >> assoc.mineral;
398 else if (key == "distribution")
399 readScalarOrBitset< DepositDistribution, CountDist > (it->second, &MineralsYAMLReaderImpl::readDistribution, assoc.distributions);
400 }
401 } else
402 nd >> assoc.mineral;
403 }
404
405 void MineralsYAMLReaderImpl::readGroupDef( IMineralsDatabase * pMinDB, const YAML::Node & nd, mars::ptr<geoworld::MineralGroupDef> & group )
406 {
407 using namespace YAML;
408
409 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
410 {
411 std::string key;
412 it->first >> key;
413
414 if (key == "group")
415 {
416 it->second >> group->name;
417 }
418 else if (key == "members")
419 {
420 for (const_iterator itMemb = it->second.begin(); itMemb != it->second.end(); ++itMemb)
421 {
422 if (itMemb->Type() == NodeType::Scalar)
423 {
424 std::string sRefName;
425
426 *itMemb >> sRefName;
427 group->members.push_back(sRefName);
428 } else
429 {
430 mars::ptr <MineralDef> mineral = new MineralDef();
431
432 readMineralDef(*itMemb, mineral);
433 group->members.push_back (pMinDB->addMineral(mineral));
434 }
435 }
436 }
437 }
438 }
439
440 void MineralsYAMLReaderImpl::readEnvironment( const YAML::Node & nd, MinClassPtr & clazz )
441 {
442 nd >> clazz;
443 }
444
445 void MineralsYAMLReaderImpl::readDistribution( const YAML::Node & nd, DepositDistribution & distribution )
446 {
447 strToEnum (nd, distribution,
448 "cluster", Dist_Cluster,
449 "vein", Dist_Vein,
450 "sill", Dist_Sill,
451 "dike", Dist_Dike,
452 "layer", Dist_Layer,
453 "laccolith", Dist_Laccolith,
454 NULL
455 );
456 }
457
458 void MineralsYAMLReaderImpl::readSediment( const YAML::Node & nd, Sediment & sediment )
459 {
460 strToEnum (nd, sediment,
461 "gravel", Sediment_Gravel,
462 "sand", Sediment_Sand,
463 "sandy-silt", Sediment_SandySilt,
464 "silt", Sediment_Silt,
465 "silty-clay", Sediment_SiltyClay,
466 "clay", Sediment_Clay,
467 "evaporite", Sediment_Evaporite,
468 NULL
469 );
470 }
471
472
473 bool MineralsYAMLReaderImpl::load (IMineralsDatabase * pMinDB)
474 {
475 using namespace YAML;
476
477 try
478 {
[aad5afa]479 for (NodeVector::const_iterator i = _docs.begin(); i != _docs.end(); ++i) {
480 const YAML::Node nd = *i;
[80a6a52]481
482 if (nd.Type() == NodeType::Map)
483 {
484 std::string type;
485
486 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
487 {
488 std::string key;
489 it->first >> key;
490
491 if (key == "mineral")
492 {
493 type = key;
494 break;
495 } else if (key == "class")
496 {
497 type = key;
498 } else if (key == "group")
499 {
500 type = key;
501 }
502 }
503 if (type == "mineral")
504 {
505 mars::ptr <MineralDef> mineral = new MineralDef();
506
507 readMineralDef(nd, mineral);
508 pMinDB->addMineral(mineral);
509 } else if (type == "class")
510 {
511 mars::ptr <MineralClass> rock = new MineralClass();
512
513 readClassDefinition(nd, rock);
514 pMinDB->addClass(rock);
515 } else if (type == "group")
516 {
517 mars::ptr <MineralGroupDef> group = new MineralGroupDef();
518
519 readGroupDef(pMinDB, nd, group);
520 pMinDB->addGroup (group);
521 }
522 }
[aad5afa]523 }
[80a6a52]524
525 return true;
526
527 } catch (YAML::RepresentationException &)
528 {
529 return false;
530 }
531 }
532
533 MineralsYAMLReader::MineralsYAMLReader( const char * szFile, ... )
534 : _pifs(new FileList())
535 {
536 va_list vaFiles;
537
538 const char * szIncer = szFile;
539 va_start(vaFiles, szFile);
540
541 while (szIncer != NULL)
542 {
543 _pifs->push_back(new std::ifstream(szIncer, std::ios::in));
544 szIncer = va_arg(vaFiles, const char *);
545 }
546
547 va_end(vaFiles);
548 }
549
550 MineralsYAMLReader::~MineralsYAMLReader()
551 {
552 for (std::vector< std::ifstream * >::iterator i = _pifs->begin(); i != _pifs->end(); ++i)
553 delete *i;
554
555 delete _pifs;
556 }
557
558 bool MineralsYAMLReader::load( IMineralsDatabase * pMinDB )
559 {
560 bool b = true;
561 for (std::vector< std::ifstream * >::iterator iFile = _pifs->begin(); iFile != _pifs->end(); ++iFile)
562 {
563 MineralsYAMLReaderImpl impl(**iFile);
564
565 b = b && impl.load(pMinDB);
566 }
567 return b;
568 }
569
570}
Note: See TracBrowser for help on using the repository browser.