00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "typeinst.h"
00035
00036 #include <fstream>
00037
00038 #include "common/wave_ex.h"
00039 #include "datahash/datahash_text.h"
00040 #include "datahash/datahash_util.h"
00041 #include "geometry/geometry_3d.h"
00042 #include "perf/perf.h"
00043 #include "story/story.h"
00044 #include "threadsafe/threadsafe_map.h"
00045 #include "threadsafe/threadsafe_queue.h"
00046 #include "util/parsing.h"
00047 #include "util/token_stream.h"
00048
00049
00050 namespace aesop {
00051
00052
00053
00054 ComponentData::~ComponentData(void) throw() { }
00055 Instance::~Instance(void) throw() { }
00056 TypeComponentLoader::~TypeComponentLoader(void) throw() { }
00057
00058
00059 typedef threadsafe_queue<smart_ptr<TypeComponentLoader> > vec_loader_t;
00060
00061 typedef threadsafe_map<std::string, smart_ptr<vec_loader_t> > map_loaders_t;
00062
00063
00064 static map_loaders_t s_loaders;
00065
00066
00068
00069
00070
00072
00073 static void
00074 readIdFromStream
00075 (
00076 IO std::istream& stream,
00077 OUT AESOPIdBuffer& buffer,
00078 IO std::string& token
00079 )
00080 {
00081 if (!stream.good()) {
00082 WAVE_EX(wex);
00083 wex << "bad stream while parsing instances?";
00084 }
00085
00086 getNextToken(stream, token);
00087 buffer.set(token.c_str());
00088 DPRINTF(" read Id: %s", (const char *) buffer);
00089 }
00090
00091
00092
00093 static bool
00094 isReservedComponent
00095 (
00096 IN const char * name
00097 )
00098 {
00099 ASSERT(name, "null");
00100
00101
00102 return (!*name || '_' == *name);
00103 }
00104
00105
00106
00108
00109
00110
00112
00113 void
00114 ComponentData::dump
00115 (
00116 IN const char * msg
00117 )
00118 const
00119 throw()
00120 {
00121
00122 if (msg) {
00123 DPRINTF("%s", msg);
00124 }
00125 DPRINTF(" (data dump not overridden from base class)");
00126 }
00127
00128
00129
00131
00132
00133
00135
00136 class Registry {
00137 public:
00138
00139 Registry(void) throw() { }
00140 ~Registry(void) throw() { }
00141
00142
00143 void initialize(IN smart_ptr<story::Story>& story);
00144 void loadInstanceComponentData(IN smart_ptr<Instance>& instance);
00145 const Datahash * getComponentData(IN const char * typeName,
00146 IN const char * componentName);
00147
00148 private:
00149
00150 typedef std::map<std::string, smart_ptr<TypeComponentLoader> >
00151 loader_map_t;
00152
00153 struct type_rec_t {
00154 smart_ptr<Datahash> typeData;
00155 loader_map_t loaders;
00156 };
00157
00158 typedef threadsafe_map<std::string, smart_ptr<type_rec_t> > type_map_t;
00159
00160
00161 bool isTypeLoaded(IN const char * typeId);
00162 smart_ptr<type_rec_t> loadType(IN const char * typeId);
00163 smart_ptr<type_rec_t> getType(IN const char * typeId);
00164
00165
00166 smart_ptr<story::Story> m_story;
00167 type_map_t m_types;
00168 };
00169
00170
00171 static smart_ptr<Registry> s_registry;
00172
00173
00174 void
00175 Registry::initialize
00176 (
00177 IN smart_ptr<story::Story>& story
00178 )
00179 {
00180 ASSERT(story, "null");
00181
00182 m_story = story;
00183 }
00184
00185
00186
00188
00189
00190
00191
00192
00194
00195 void
00196 Registry::loadInstanceComponentData
00197 (
00198 IN smart_ptr<Instance>& instance
00199 )
00200 {
00201 ASSERT(instance, "null");
00202
00203 const char * typeId = instance->getTypeId();
00204 DPRINTF("Loading instance component data for type %s", typeId);
00205
00206 smart_ptr<type_rec_t> tr = this->getType(typeId);
00207 if (!tr) {
00208 DPRINTF(" No such type? %s", typeId);
00209 ASSERT(false, "stop");
00210 return;
00211 }
00212 DPRINTF("Got a type: %s", typeId);
00213
00214
00215 for (loader_map_t::iterator i = tr->loaders.begin();
00216 i != tr->loaders.end(); ++i) {
00217 const char * name = i->first.c_str();
00218 smart_ptr<TypeComponentLoader> tcl = i->second;
00219 ASSERT(tcl, "null");
00220
00221 DPRINTF(" Loading '%s' component...", name);
00222
00223
00224 smart_ptr<Datahash> hash = getSubhash(tr->typeData, name);
00225 const char * id = getString(hash, "id");
00226
00227
00228 std::string full_path = m_story->getObjectPath(name, id);
00229 DPRINTF(" path: %s", full_path.c_str());
00230
00231
00232 smart_ptr<ComponentData> cdata =
00233 tcl->loadTS(instance, hash, full_path.c_str());
00234
00235
00236 instance->setComponentData(name, cdata);
00237 }
00238 }
00239
00240
00241
00242 const Datahash *
00243 Registry::getComponentData
00244 (
00245 IN const char * typeName,
00246 IN const char * componentName
00247 )
00248 {
00249 ASSERT(typeName, "null");
00250 ASSERT(componentName, "null");
00251
00252 smart_ptr<type_rec_t> type = this->getType(typeName);
00253 if (!type) {
00254 DPRINTF("No such type: '%s'", typeName);
00255 return NULL;
00256 }
00257
00258 if (!type->typeData) {
00259 DPRINTF("No type data? type='%s'", typeName);
00260 return NULL;
00261 }
00262
00263 int nElements = type->typeData->count(componentName);
00264 if (!nElements) {
00265 DPRINTF("type '%s' contains no component data: '%s'",
00266 typeName, componentName);
00267 return NULL;
00268 }
00269 ASSERT_THROW(1 == nElements, "Type '" << typeName << "' contains "
00270 "multiple '" << componentName << "' component entries?");
00271
00272
00273 Datahash::iterator_t i;
00274 type->typeData->getIterator(componentName, i);
00275 const hash_value_t * hv = type->typeData->getNextElementUnsafe(i);
00276 ASSERT_THROW(hv, "component disappeared");
00277 ASSERT_THROW(hv->hash, "component is not a hash");
00278 return hv->hash;
00279 }
00280
00281
00282
00284
00285
00286
00288
00289 smart_ptr<Registry::type_rec_t>
00290 Registry::loadType
00291 (
00292 IN const char * typeId
00293 )
00294 {
00295 perf::Timer timer("TypeRegistry::loadType");
00296 ASSERT(typeId, "null");
00297 ASSERT(m_story, "null");
00298
00299
00300
00301 DPRINTF("Reading type '%s'", typeId);
00302
00303
00304 smart_ptr<type_rec_t> type_rec = new type_rec_t;
00305 ASSERT(type_rec, "out of memory");
00306
00307
00308 std::string path = m_story->getObjectPath("type", typeId);
00309 path += ".type";
00310
00311
00312 type_rec->typeData = readHashFromTextFile(path.c_str());
00313 ASSERT(type_rec->typeData, "null");
00314
00315
00316 VecString badKeys;
00317 Datahash * hash = type_rec->typeData;
00318 Datahash::iterator_t i;
00319 hash->getIterator(i);
00320 std::string keystr;
00321 hash_value_t hv;
00322 while (hash->getNextElement(i, keystr, hv)) {
00323 const char * key = keystr.c_str();
00324 DPRINTF(" key: %s", key);
00325 smart_ptr<Datahash> data = hv.hash;
00326 if (!data)
00327 continue;
00328
00329
00330 const char * id = getString(data, "id");
00331 DPRINTF(" id: %s", id);
00332
00333
00334 std::string full_path = m_story->getObjectPath(key, id);
00335 DPRINTF(" path: %s", full_path.c_str());
00336
00337
00338 smart_ptr<TypeComponentLoader> tcl;
00339 smart_ptr<vec_loader_t> pv;
00340 s_loaders.lookup(key, pv);
00341 if (pv) {
00342 vec_loader_t::iterator_t i;
00343 pv->getIterator(i);
00344 smart_ptr<TypeComponentLoader> p;
00345 while (pv->getNextElement(i, p)) {
00346 ASSERT(p, "null loader in queue");
00347 DPRINTF(" Checking loader...");
00348 if (p->isMyFormat(data, full_path.c_str())) {
00349 tcl = p;
00350 break;
00351 }
00352 }
00353 }
00354
00355 if (!tcl) {
00356
00357 DPRINTF("No loader for component %s=%s in type %s (%s)",
00358 key, id, typeId, path.c_str());
00359
00360
00361 badKeys.push_back(key);
00362 } else {
00363
00364 DPRINTF("Found a loader for %s=%s in type %s (%s)",
00365 key, id, typeId, path.c_str());
00366 DPRINTF(" Have %d loaders so far",
00367 (int) type_rec->loaders.size());
00368 type_rec->loaders[key] = tcl;
00369 }
00370 }
00371
00372
00373 for (VecString::const_iterator i = badKeys.begin(); i != badKeys.end();
00374 ++i) {
00375 const char * key = i->c_str();
00376 type_rec->typeData->remove(key);
00377 }
00378
00379
00380 DPRINTF("Have a type, about to insert...");
00381 m_types.insert(typeId, type_rec);
00382 DPRINTF("Returning type record now...");
00383 return type_rec;
00384 }
00385
00386
00387
00388 smart_ptr<Registry::type_rec_t>
00389 Registry::getType
00390 (
00391 IN const char * typeId
00392 )
00393 {
00394 ASSERT(typeId, "null");
00395
00396
00397 smart_ptr<type_rec_t> result;
00398 m_types.lookup(typeId, result);
00399
00400
00401 return (result) ? result : this->loadType(typeId);
00402 }
00403
00404
00405
00407
00408
00409
00411
00412 class InstImpl : public Instance {
00413 public:
00414
00415 ~InstImpl(void) throw() { }
00416
00417
00418 void initialize(IO std::istream& stream);
00419 void initialize(IN const char * instanceId,
00420 IN const char * typeId)
00421 {
00422 if (instanceId) {
00423 m_instanceId.set(instanceId);
00424 }
00425 m_typeId.set(typeId);
00426 }
00427
00428
00429
00430
00431 const char * getInstanceId(void) const throw() { return m_instanceId; }
00432 const char * getTypeId(void) const throw() { return m_typeId; }
00433 placement_t& getPlacement(void) throw() { return m_placement; }
00434 void setComponentData(IN const char * name,
00435 IN smart_ptr<ComponentData>& data);
00436 smart_ptr<ComponentData> getComponentData(IN const char * name);
00437 const Datahash * getTypeComponentData(IN const char * name);
00438 void dump(IN const char * title) throw();
00439 void setInstanceData(IN const char * name,
00440 IN smart_ptr<Datahash>& data);
00441 smart_ptr<Datahash> getInstanceData(IN const char * name);
00442
00443 private:
00444
00445 typedef threadsafe_map<std::string, smart_ptr<ComponentData> >
00446 data_map_t;
00447
00448 typedef threadsafe_map<std::string, smart_ptr<Datahash> >
00449 instData_map_t;
00450
00451
00452
00453
00454 AESOPIdBuffer m_instanceId;
00455 AESOPIdBuffer m_typeId;
00456 placement_t m_placement;
00457 data_map_t m_data;
00458 instData_map_t m_instData;
00459 };
00460
00461
00462
00464
00465
00466
00468
00469 void
00470 InstImpl::initialize
00471 (
00472 IN std::istream& stream
00473 )
00474 {
00475 ASSERT(stream.good(), "bad?");
00476
00477
00478 bool readTypeId = false;
00479 bool readPlacement = false;
00480
00481
00482 std::string token;
00483 for (;;) {
00484 getNextToken(stream, token);
00485 if ("}" == token)
00486 break;
00487
00488
00489 if ("typeId" == token) {
00490 readIdFromStream(stream, m_typeId, token);
00491 readTypeId = true;
00492 } else if ("placement" == token) {
00493 expectToken(stream, "{");
00494 m_placement = parsePlacement(stream);
00495 readPlacement = true;
00496 } else if ("instanceId" == token) {
00497 readIdFromStream(stream, m_instanceId, token);
00498 } else if ("instanceData" == token) {
00499 expectToken(stream, "{");
00500 smart_ptr<Datahash> hash =
00501 readHashFromStream("instanceData", stream);
00502
00503
00504 Datahash::iterator_t i;
00505 hash->getIterator(i);
00506 std::string keystr;
00507 hash_value_t hv;
00508 while (hash->getNextElement(i, keystr, hv)) {
00509 if (!hv.hash)
00510 continue;
00511 const char * name = keystr.c_str();
00512 DPRINTF(" Setting instance data: %s", name);
00513 this->setInstanceData(name, hv.hash);
00514 }
00515 } else {
00516 WAVE_EX(wex);
00517 wex << "Unexpected keyword while parsing instance: ";
00518 wex << token;
00519 }
00520 }
00521
00522
00523 if (!readTypeId || !readPlacement) {
00524 WAVE_EX(wex);
00525 wex << "Instance is missing type and/or placement.";
00526 }
00527 }
00528
00529
00530
00532
00533
00534
00536
00537 void
00538 InstImpl::setComponentData
00539 (
00540 IN const char * name,
00541 IN smart_ptr<ComponentData>& data
00542 )
00543 {
00544 ASSERT(name, "null");
00545
00546
00547
00548 if (data) {
00549
00550 m_data.insert(name, data);
00551 return;
00552 }
00553
00554
00555 m_data.remove(name);
00556 }
00557
00558
00559
00560 smart_ptr<ComponentData>
00561 InstImpl::getComponentData
00562 (
00563 IN const char * name
00564 )
00565 {
00566 ASSERT(name, "null");
00567
00568 smart_ptr<ComponentData> cdata;
00569 m_data.lookup(name, cdata);
00570 return cdata;
00571 }
00572
00573
00574
00575 const Datahash *
00576 InstImpl::getTypeComponentData
00577 (
00578 IN const char * name
00579 )
00580 {
00581 ASSERT(name, "null");
00582 ASSERT(s_registry, "null");
00583
00584 return s_registry->getComponentData(m_typeId, name);
00585 }
00586
00587
00588
00589 void
00590 InstImpl::dump
00591 (
00592 IN const char * title
00593 )
00594 throw()
00595 {
00596 DPRINTF("Instance (%s)", title);
00597 DPRINTF(" instanceId=%s", this->getInstanceId());
00598 DPRINTF(" typeId=%s", this->getTypeId());
00599 m_placement.dump("instance");
00600
00601
00602 data_map_t::iterator_t i;
00603 m_data.getIterator(i);
00604 std::string name;
00605 smart_ptr<ComponentData> data;
00606 while (m_data.getNextElement(i, name, data)) {
00607 ASSERT(data, "null");
00608
00609 DPRINTF(" Contains component data: %s", name.c_str());
00610 std::string msg = " '";
00611 msg += name;
00612 msg += "' component data";
00613 data->dump(msg.c_str());
00614 }
00615 }
00616
00617
00618
00619 void
00620 InstImpl::setInstanceData
00621 (
00622 IN const char * name,
00623 IN smart_ptr<Datahash>& data
00624 )
00625 {
00626 ASSERT(name, "null");
00627
00628
00629 if (data) {
00630 m_instData.insert(name, data);
00631 } else {
00632 m_instData.remove(name);
00633 }
00634 }
00635
00636
00637
00638 smart_ptr<Datahash>
00639 InstImpl::getInstanceData
00640 (
00641 IN const char * name
00642 )
00643 {
00644 smart_ptr<Datahash> data;
00645 m_instData.lookup(name, data);
00646 return data;
00647 }
00648
00649
00650
00652
00653
00654
00656
00657 smart_ptr<Instance>
00658 Instance::parse
00659 (
00660 IO std::istream& stream
00661 )
00662 {
00663 perf::Timer timer("parseInstance");
00664 ASSERT(stream.good(), "bad?");
00665 ASSERT(s_registry, "need to call initializeTypeInstanceLibrary()");
00666
00667 DPRINTF("Parsing instance...");
00668 smart_ptr<InstImpl> local = new InstImpl;
00669 ASSERT(local, "out of memory");
00670
00671 local->initialize(stream);
00672
00673 smart_ptr<Instance> i = local;
00674 s_registry->loadInstanceComponentData(i);
00675
00676 i->dump("Just parsed");
00677
00678
00679 return i;
00680 }
00681
00682
00683
00684 smart_ptr<Instance>
00685 Instance::create
00686 (
00687 IN const char * instanceId,
00688 IN const char * typeId
00689 )
00690 {
00691
00692 ASSERT(typeId, "null");
00693 ASSERT(s_registry, "need to call initializeTypeInstanceLibrary()");
00694
00695 smart_ptr<InstImpl> local = new InstImpl;
00696 ASSERT(local, "out of memory");
00697
00698 local->initialize(instanceId, typeId);
00699
00700 smart_ptr<Instance> i = local;
00701 s_registry->loadInstanceComponentData(i);
00702
00703 i->dump("Just created");
00704
00705 return i;
00706 }
00707
00708
00709
00711
00712
00713
00715
00716 void
00717 registerTypeComponentLoader
00718 (
00719 IN smart_ptr<TypeComponentLoader>& tcl
00720 )
00721 {
00722 ASSERT(tcl, "null");
00723
00724
00725 const char * cName = tcl->getComponentName();
00726 DPRINTF("Registering component loader: '%s'", cName);
00727 ASSERT(cName, "null");
00728
00729
00730 ASSERT_THROW(!isReservedComponent(cName),
00731 "Cannot register a type component loader for this type: '" <<
00732 cName << "'. That is a reserved type component name.");
00733
00734
00735 smart_ptr<vec_loader_t> pv;
00736 s_loaders.lookup(cName, pv);
00737 if (!pv) {
00738
00739 smart_ptr<vec_loader_t> pv1 = new vec_loader_t;
00740 ASSERT(pv1, "out of memory");
00741 s_loaders.insert(cName, pv1);
00742 pv = pv1;
00743 }
00744
00745
00746 ASSERT(pv, "should have a vector of component loaders now");
00747 pv->push_back(tcl);
00748 }
00749
00750
00751
00752 void
00753 initializeTypeInstanceLibrary
00754 (
00755 IN smart_ptr<story::Story>& story
00756 )
00757 {
00758 ASSERT(story, "null");
00759
00760
00761 if (s_registry) {
00762 DPRINTF("already created registry!");
00763 DPRINTF("ignoring redundant initializeTypeInstanceLibrary() call");
00764 return;
00765 }
00766
00767 smart_ptr<Registry> local = new Registry;
00768 ASSERT(local, "out of memory");
00769 local->initialize(story);
00770
00771
00772 s_registry = local;
00773 }
00774
00775
00776
00777 void
00778 loadInstances
00779 (
00780 IO std::istream& stream,
00781 OUT vec_instance_t& instances
00782 )
00783 {
00784 perf::Timer timer("loadInstances");
00785 ASSERT(stream.good(), "bad?");
00786 instances.clear();
00787
00788
00789 std::string token;
00790 while (true) {
00791 bool eof = false;
00792 getNextToken(stream, token, true, &eof);
00793 if (eof || "}" == token) {
00794 break;
00795 }
00796
00797 if ("instance" != token) {
00798 WAVE_EX(wex);
00799 wex << "Invalid token! Expected 'instance' in ";
00800 wex << "instance list, read '" << token << "' instead.";
00801 }
00802
00803
00804 expectToken(stream, "{");
00805
00806
00807 instances.push_back(Instance::parse(stream));
00808 }
00809
00810
00811 DPRINTF("Read %d instances from stream", (int) instances.size());
00812 }
00813
00814
00815
00816 const char *
00817 getKeyWithOverrides
00818 (
00819 IN const char * keyName,
00820 IN const Datahash * instanceData,
00821 IN const Datahash * typeData,
00822 IN const Datahash * modelData,
00823 IN eDatahash_Flag flag
00824 )
00825 {
00826 ASSERT(keyName, "null");
00827
00828
00829
00830
00831 const char * val = NULL;
00832
00833
00834 if (instanceData) {
00835 val = getString(instanceData, keyName, eDatahash_Optional);
00836 }
00837 if (val) {
00838 DPRINTF(" Getting value from instance: %s = %s", keyName,
00839 val);
00840 return val;
00841 }
00842
00843
00844 if (typeData) {
00845 val = getString(typeData, keyName, eDatahash_Optional);
00846 }
00847 if (val) {
00848 DPRINTF(" Getting value from type: %s = %s", keyName, val);
00849 return val;
00850 }
00851
00852
00853 if (modelData) {
00854 val = getString(modelData, keyName, flag);
00855 }
00856 if (val) {
00857 DPRINTF(" Getting value from model: %s = %s", keyName, val);
00858 }
00859 return val;
00860 }
00861
00862
00863
00864 };