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

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

Get to a compile state for terrain procedural generation

  • Property mode set to 100755
File size: 15.5 KB
Line 
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:
44 geoworld::PetrogenyDef * _defPetroDef;
45 std::istream & _input;
46
47 public:
48 template <typename T>
49 void readScalarOrSequence (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::list<T> & collection);
50 template <typename T>
51 void readScalarOrSequence (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::vector<T> & collection);
52 template <typename T, typename L>
53 void readScalarOrSequenceA (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), L & collection);
54 template <typename T, int N>
55 void readScalarOrBitset (const YAML::Node & nd, void(MineralsYAMLReaderImpl::*fnProc)(const YAML::Node &, T &), std::bitset<N> & bset);
56
57 void readGroupDef( IMineralsDatabase * pMinDB, const YAML::Node & nd, mars::ptr<geoworld::MineralGroupDef> & group );
58 void readClassDefinition ( const YAML::Node & nd, mars::ptr<geoworld::MineralClass> & rclass);
59 void readMineralDef( const YAML::Node &nd, mars::ptr<geoworld::MineralDef> & mineral );
60
61 void readClassDisposition( const YAML::Node &nd, geoworld::MineralClass::Disposition & disposition );
62 void readYield (const YAML::Node & nd, geoworld::MineralDef::YieldSet & set);
63 void readGenesis (const YAML::Node & nd, geoworld::PetrogenyDef & mineral);
64 void readEnvironment (const YAML::Node & nd, geoworld::MinClassPtr & clazz);
65 void readAssociation (const YAML::Node & nd, geoworld::MineralReference & assoc);
66 void readDistribution (const YAML::Node & nd, geoworld::DepositDistribution & distribution);
67 void readSediment (const YAML::Node & nd, geoworld::Sediment & sediment);
68
69 void resolveReferences ();
70 void resolve( geoworld::MineralPtr & rWRef );
71
72 template <typename E>
73 static void strToEnumV (const std::string & str, E & enRet, const char * szKey, va_list & vl);
74
75 template <typename E>
76 static void strToEnumOrPtSc (const YAML::Node & nd, E & enRet, geoworld::PointScale & ptsc, const char * szFirst, ...);
77
78 template <typename E>
79 static void strToEnum (const YAML::Node & nd, E & enRet, const char * szFirst, ...);
80 template <typename E>
81 static void strToEnum (const std::string & str, E & enRet, const char * szFirst, ...);
82
83 MineralsYAMLReaderImpl(std::istream & input);
84
85 virtual bool load (IMineralsDatabase * pMinDB);
86 };
87
88 MineralsYAMLReaderImpl::MineralsYAMLReaderImpl(std::istream & input)
89 : _input(input) {}
90
91 template <typename E>
92 void MineralsYAMLReaderImpl::strToEnum( const std::string & str, E & enRet, const char * szFirst, ... )
93 {
94 va_list vl;
95
96 va_start(vl, enRet);
97 strToEnumV(str, enRet, szFirst, vl);
98 va_end(vl);
99 }
100
101 template <typename E>
102 void MineralsYAMLReaderImpl::strToEnum( const YAML::Node & nd, E & enRet, const char * szFirst, ... )
103 {
104 std::string sKey;
105 va_list vl;
106
107 nd >> sKey;
108 va_start(vl, szFirst);
109 strToEnumV(sKey, enRet, szFirst, vl);
110 va_end(vl);
111 }
112
113 template <typename E>
114 void MineralsYAMLReaderImpl::strToEnumOrPtSc( const YAML::Node & nd, E & enRet, geoworld::PointScale & ptsc, const char * szFirst, ... )
115 {
116 std::string sKey;
117 va_list vl;
118 int i;
119
120 nd >> sKey;
121 i = atoi(sKey.c_str());
122
123 if (i > 0 || sKey == "0")
124 ptsc = static_cast <PointScale> (i);
125 else
126 {
127 va_start(vl, szFirst);
128 strToEnumV(sKey, enRet, szFirst, vl);
129 va_end(vl);
130 }
131 }
132
133 template <typename E>
134 void MineralsYAMLReaderImpl::strToEnumV( const std::string & str, E & enRet, const char * szKey, va_list & vl )
135 {
136 while (szKey != NULL)
137 {
138 const E enVal = static_cast< E > (va_arg(vl, int));
139
140 if (str == szKey)
141 enRet = enVal;
142
143 szKey = va_arg(vl, const char *);
144 }
145 }
146
147 template <typename T, int N>
148 void MineralsYAMLReaderImpl::readScalarOrBitset( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::bitset<N> & bset )
149 {
150 using namespace YAML;
151
152 if (nd.Type() == NodeType::Sequence)
153 {
154 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
155 {
156 T data;
157 (this->*fnProc)(*it, data);
158 if (data > 0 && data < N)
159 bset.set(data);
160 }
161 } else
162 {
163 T data;
164 (this->*fnProc)(nd, data);
165 if (data > 0 && data < N)
166 bset.set(data);
167 }
168 }
169
170 template <typename T, typename L>
171 void MineralsYAMLReaderImpl::readScalarOrSequenceA( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), L & collection )
172 {
173 using namespace YAML;
174
175 if (nd.Type() == NodeType::Sequence)
176 {
177 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
178 {
179 T data;
180 (this->*fnProc)(*it, data);
181 collection.push_back(data);
182 }
183 } else
184 {
185 T data;
186 (this->*fnProc)(nd, data);
187 collection.push_back(data);
188 }
189 }
190
191 template <typename T>
192 void MineralsYAMLReaderImpl::readScalarOrSequence( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::vector<T> & collection )
193 {
194 readScalarOrSequenceA<T, std::vector< T > >(nd, fnProc, collection);
195 }
196
197 template <typename T>
198 void MineralsYAMLReaderImpl::readScalarOrSequence( const YAML::Node & nd, void(MineralsYAMLReaderImpl::* fnProc)(const YAML::Node &, T &), std::list<T> & collection )
199 {
200 readScalarOrSequenceA<T, std::list< T > >(nd, fnProc, collection);
201 }
202
203 void MineralsYAMLReaderImpl::readYield (const YAML::Node & nd, MineralDef::YieldSet & set)
204 {
205 using namespace YAML;
206
207 for (const_iterator itchem = nd.begin(); itchem != nd.end(); ++itchem)
208 {
209 std::string smin;
210 const Node & ndParticle = itchem->second;
211 float pct, flux = 0.0f;
212
213 if (ndParticle.Type() == NodeType::Scalar)
214 ndParticle >> pct;
215 else
216 {
217 ndParticle[0] >> pct;
218 ndParticle[1] >> flux;
219 }
220 itchem->first >> smin;
221
222 set.add (MineralDef::YieldMin (smin, pct, flux));
223 }
224 }
225
226 void MineralsYAMLReaderImpl::readClassDefinition ( const YAML::Node & nd, mars::ptr <MineralClass> & rclass)
227 {
228 using namespace YAML;
229
230 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
231 {
232 std::string key;
233 it->first >> key;
234
235 if (key == "class")
236 {
237 it->second >> rclass->name;
238 }
239 else if (key == "type")
240 {
241 strToEnum(it->second, rclass->type,
242 "igneous", MineralClass::Type_Igneous,
243 "sedimentary", MineralClass::Type_Sedimentary,
244 NULL
245 );
246 }
247 else if (key == "dispositions")
248 {
249 readScalarOrSequence (it->second, &MineralsYAMLReaderImpl::readClassDisposition, rclass->dispositions);
250 }
251 }
252 }
253
254 void MineralsYAMLReaderImpl::readGenesis( const YAML::Node & nd, PetrogenyDef & genesis )
255 {
256 using namespace YAML;
257
258 genesis = *this->_defPetroDef;
259
260 // TODO: Implement exception throwing rules
261 for (const_iterator it2 = nd.begin(); it2 != nd.end(); ++it2)
262 {
263 std::string key;
264 it2->first >> key;
265
266 if (key == "distribution")
267 {
268 readScalarOrBitset< DepositDistribution, CountDist >(it2->second, &MineralsYAMLReaderImpl::readDistribution, genesis.distributions);
269 } else if (key == "abundance")
270 {
271 it2->second >> genesis.abundance;
272 } else if (key == "size")
273 {
274 it2->second >> genesis.size;
275 } else if (key == "association")
276 {
277 readScalarOrSequence(it2->second, &MineralsYAMLReaderImpl::readAssociation, genesis.associations);
278 } else if (key == "host")
279 {
280 readAssociation(it2->second, genesis.host);
281 } else if (key == "environment")
282 {
283 readScalarOrSequence(it2->second, &MineralsYAMLReaderImpl::readEnvironment, genesis.environments);
284 } else
285 continue;
286 }
287 }
288 void MineralsYAMLReaderImpl::readMineralDef( const YAML::Node &nd, mars::ptr<MineralDef> & mineral )
289 {
290 using namespace YAML;
291
292 assert(mineral != NULL);
293
294 this->_defPetroDef = new PetrogenyDef();
295 try
296 {
297 readGenesis(nd["deposit"], *this->_defPetroDef);
298 }
299 catch (YAML::TypedKeyNotFound <std::string> &) {}
300
301 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
302 {
303 std::string key;
304 const YAML::Node & val = it->second;
305
306 it->first >> key;
307
308 if (key == "mineral")
309 val >> mineral->name;
310 else if (key == "boiling_point")
311 val >> mineral->boiling_point;
312 else if (key == "melting_point")
313 val >> mineral->melting_point;
314 else if (key == "triple_point")
315 val >> mineral->triple_point;
316 else if (key == "critical_point")
317 val >> mineral->critical_point;
318 else if (key == "sublimation_point")
319 val >> mineral->sublimation_point;
320 else if (key == "geochemistry")
321 readScalarOrSequence(val, &MineralsYAMLReaderImpl::readYield, mineral->yields);
322 else if (key == "genesis")
323 readScalarOrSequence(val, &MineralsYAMLReaderImpl::readGenesis, mineral->genesis);
324 else if (key == "class")
325 val >> mineral->clazz;
326 }
327 delete this->_defPetroDef;
328 }
329
330 void MineralsYAMLReaderImpl::readClassDisposition( const YAML::Node &nd, MineralClass::Disposition & disposition )
331 {
332 using namespace YAML;
333
334 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
335 {
336 try
337 {
338 std::string key;
339 it->first >> key;
340
341 if (key == "silica")
342 {
343 strToEnumOrPtSc(it->second, disposition.silica.base, disposition.silica.numeric,
344 "ultra-mafic", Silica_UltraMafic,
345 "mafic", Silica_Mafic,
346 "intermediate", Silica_Intermediate,
347 "inter-felsic", Silica_InterFelsic,
348 "felsic", Silica_Felsic,
349 NULL
350 );
351 } else if (key == "origin")
352 {
353 strToEnum(it->second, disposition.origin,
354 "volcanic", Origin_Volcanic,
355 "subvolcanic", Origin_Subvolcanic,
356 "plutonic", Origin_Plutonic,
357 "meteoritic", Origin_Meteoritic,
358 NULL
359 );
360 } else if (key == "temperature")
361 {
362 it->second >> disposition.temperature;
363 } else if (key == "pressure")
364 {
365 it->second >> disposition.pressure;
366 } else if (key == "sediment")
367 {
368 readScalarOrBitset<Sediment, Sediment_COUNT> (it->second, &MineralsYAMLReaderImpl::readSediment, disposition.sediment);
369 } else if (key == "weathered")
370 {
371 it->second >> disposition.weathered;
372 }
373 }
374 catch (YAML::RepresentationException &)
375 {
376
377 }
378 }
379 }
380
381 void MineralsYAMLReaderImpl::readAssociation( const YAML::Node & nd, MineralReference & assoc )
382 {
383 using namespace YAML;
384
385 std::string name;
386
387 if (nd.Type() == NodeType::Map)
388 {
389 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
390 {
391 std::string key;
392 it->first >> key;
393
394 if (key == "mineral")
395 it->second >> assoc.mineral;
396 else if (key == "distribution")
397 readScalarOrBitset< DepositDistribution, CountDist > (it->second, &MineralsYAMLReaderImpl::readDistribution, assoc.distributions);
398 }
399 } else
400 nd >> assoc.mineral;
401 }
402
403 void MineralsYAMLReaderImpl::readGroupDef( IMineralsDatabase * pMinDB, const YAML::Node & nd, mars::ptr<geoworld::MineralGroupDef> & group )
404 {
405 using namespace YAML;
406
407 for (const_iterator it = nd.begin(); it != nd.end(); ++it)
408 {
409 std::string key;
410 it->first >> key;
411
412 if (key == "group")
413 {
414 it->second >> group->name;
415 }
416 else if (key == "members")
417 {
418 for (const_iterator itMemb = it->second.begin(); itMemb != it->second.end(); ++itMemb)
419 {
420 if (itMemb->Type() == NodeType::Scalar)
421 {
422 std::string sRefName;
423
424 *itMemb >> sRefName;
425 group->members.push_back(sRefName);
426 } else
427 {
428 mars::ptr <MineralDef> mineral = new MineralDef();
429
430 readMineralDef(*itMemb, mineral);
431 group->members.push_back (pMinDB->addMineral(mineral));
432 }
433 }
434 }
435 }
436 }
437
438 void MineralsYAMLReaderImpl::readEnvironment( const YAML::Node & nd, MinClassPtr & clazz )
439 {
440 nd >> clazz;
441 }
442
443 void MineralsYAMLReaderImpl::readDistribution( const YAML::Node & nd, DepositDistribution & distribution )
444 {
445 strToEnum (nd, distribution,
446 "cluster", Dist_Cluster,
447 "vein", Dist_Vein,
448 "sill", Dist_Sill,
449 "dike", Dist_Dike,
450 "layer", Dist_Layer,
451 "laccolith", Dist_Laccolith,
452 NULL
453 );
454 }
455
456 void MineralsYAMLReaderImpl::readSediment( const YAML::Node & nd, Sediment & sediment )
457 {
458 strToEnum (nd, sediment,
459 "gravel", Sediment_Gravel,
460 "sand", Sediment_Sand,
461 "sandy-silt", Sediment_SandySilt,
462 "silt", Sediment_Silt,
463 "silty-clay", Sediment_SiltyClay,
464 "clay", Sediment_Clay,
465 "evaporite", Sediment_Evaporite,
466 NULL
467 );
468 }
469
470
471 bool MineralsYAMLReaderImpl::load (IMineralsDatabase * pMinDB)
472 {
473 using namespace YAML;
474
475 try
476 {
477 YAML::Node nd;
478
479 do {
480 nd = Load(_input);
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 }
523 } while (!nd.IsNull());
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.