diff options
| author | Petr Mrázek | 2010-08-23 01:29:55 +0200 |
|---|---|---|
| committer | Petr Mrázek | 2010-08-23 01:29:55 +0200 |
| commit | 368de864a1723df3ece4c58968036e76c8035e97 (patch) | |
| tree | 0899557e0b4c1fedd9cbdbd291705751be9f0960 /library/VersionInfoFactory.cpp | |
| parent | 1bceac23433fa097e4b5d43aa3eb1999a370872f (diff) | |
| download | dfhack-368de864a1723df3ece4c58968036e76c8035e97.tar.gz dfhack-368de864a1723df3ece4c58968036e76c8035e97.tar.bz2 dfhack-368de864a1723df3ece4c58968036e76c8035e97.tar.xz | |
Sync
Diffstat (limited to 'library/VersionInfoFactory.cpp')
| -rw-r--r-- | library/VersionInfoFactory.cpp | 363 |
1 files changed, 276 insertions, 87 deletions
diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index 6f2e6a32..002b9ae4 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -32,18 +32,19 @@ using namespace DFHack; VersionInfoFactory::~VersionInfoFactory() { - // for each in std::vector<memory_info*> meminfo;, delete - for(uint32_t i = 0; i < meminfo.size();i++) + // for each stored version, delete + for(uint32_t i = 0; i < versions.size();i++) { - delete meminfo[i]; + delete versions[i]; } - meminfo.clear(); + versions.clear(); } void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) { TiXmlElement* pClassEntry; TiXmlElement* pClassSubEntry; + /* // check for rebase, do rebase if check positive const char * rebase = vtable->Attribute("rebase"); if(rebase) @@ -51,6 +52,7 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) int32_t rebase_offset = strtol(rebase, NULL, 16); mem->RebaseVTable(rebase_offset); } + */ // parse vtable entries pClassEntry = vtable->FirstChildElement(); for(;pClassEntry;pClassEntry=pClassEntry->NextSiblingElement()) @@ -92,26 +94,214 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) } } -void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map <string ,TiXmlElement *>& knownEntries) +void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem) +{ + TiXmlElement* pElement; + TiXmlElement* pElement2nd; + const char *cstr_version = entry->Attribute("name"); + + if (!cstr_version) + throw Error::MemoryXmlBadAttribute("name"); + + mem->setVersion(cstr_version); + mem->setOS(VersionInfo::OS_BAD); + + // process additional entries + pElement = entry->FirstChildElement()->ToElement(); + for(;pElement;pElement=pElement->NextSiblingElement()) + { + // only elements get processed + const char *cstr_type = pElement->Value(); + std::string type = cstr_type; + if(type == "VTable") + { + ParseVTable(pElement, mem); + continue; + } + else if(type == "Offsets") + { + // we don't care about the descriptions here, do nothing + //ParseBaseOffsets(pMemEntry, mem); + continue; + } + else if (type == "Professions") + { + pElement2nd = entry->FirstChildElement("Profession")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Profession")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + // FIXME: missing some attributes here + if(id && name) + { + mem->setProfession(id,name); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Jobs") + { + pElement2nd = entry->FirstChildElement("Job")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Job")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + if(id && name) + { + mem->setJob(id,name); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Skills") + { + pElement2nd = entry->FirstChildElement("Skill")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Skill")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + if(id && name) + { + mem->setSkill(id,name); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Traits") + { + pElement2nd = entry->FirstChildElement("Trait")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + const char * lvl0 = pElement->Attribute("level_0"); + const char * lvl1 = pElement->Attribute("level_1"); + const char * lvl2 = pElement->Attribute("level_2"); + const char * lvl3 = pElement->Attribute("level_3"); + const char * lvl4 = pElement->Attribute("level_4"); + const char * lvl5 = pElement->Attribute("level_5"); + if(id && name && lvl0 && lvl1 && lvl2 && lvl3 && lvl4 && lvl5) + { + mem->setTrait(id, name, lvl0, lvl1, lvl2, lvl3, lvl4, lvl5); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Labors") + { + pElement2nd = entry->FirstChildElement("Labor")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Labor")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + if(id && name) + { + mem->setLabor(id,name); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Levels") + { + pElement2nd = entry->FirstChildElement("Level")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Level")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + const char * nextlvl = pElement2nd->Attribute("xpNxtLvl"); + if(id && name && nextlvl) + { + mem->setLevel(id, name, nextlvl); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else if (type == "Moods") + { + pElement2nd = entry->FirstChildElement("Mood")->ToElement(); + for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Mood")) + { + const char * id = pElement2nd->Attribute("id"); + const char * name = pElement2nd->Attribute("name"); + if(id && name) + { + mem->setMood(id, name); + } + else + { + // FIXME: this is crap, doesn't tell anything about the error + throw Error::MemoryXmlUnderspecifiedEntry(name); + } + } + } + else + { + //FIXME: only log, not hard error + //throw Error::MemoryXmlUnknownType(type.c_str()); + } + } // for +} // method + +void VersionInfoFactory::EvalVersion(string base, VersionInfo * mem) +{ + if(knownVersions.find(base) != knownVersions.end()) + { + v_descr & desc = knownVersions[base]; + if (!desc.second) + { + VersionInfo * newmem = new VersionInfo(); + ParseVersion(desc.first, newmem); + desc.second = newmem; + versions.push_back(newmem); + } + mem->copy(desc.second); + } +} + +void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem) { TiXmlElement* pMemEntry; - const char *cstr_version = entry->Attribute("version"); + const char *cstr_name = entry->Attribute("name"); const char *cstr_os = entry->Attribute("os"); const char *cstr_base = entry->Attribute("base"); const char *cstr_rebase = entry->Attribute("rebase"); if(cstr_base) { string base = cstr_base; - ParseEntry(knownEntries[base], mem, knownEntries); + EvalVersion(base, mem); } - if (!cstr_version) - throw Error::MemoryXmlBadAttribute("version"); + if (!cstr_name) + throw Error::MemoryXmlBadAttribute("name"); if (!cstr_os) throw Error::MemoryXmlBadAttribute("os"); string os = cstr_os; - mem->setVersion(cstr_version); + mem->setVersion(cstr_name); mem->setOS(cstr_os); // offset inherited addresses by 'rebase'. @@ -134,10 +324,6 @@ void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map // users are free to use a sane kernel that doesn't do this kind of **** by default mem->setBase(0x0); } - else if ( os == "all") - { - // yay - } else { throw Error::MemoryXmlBadAttribute("os"); @@ -148,75 +334,55 @@ void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map pMemEntry = entry->FirstChildElement()->ToElement(); for(;pMemEntry;pMemEntry=pMemEntry->NextSiblingElement()) { - // only elements get processed - const char *cstr_type = pMemEntry->Value(); - const char *cstr_name = pMemEntry->Attribute("name"); - const char *cstr_value = pMemEntry->GetText(); - - if(!cstr_value) - cstr_value = pMemEntry->Attribute("id"); - - // check for missing parts string type, name, value; + const char *cstr_type = pMemEntry->Value(); type = cstr_type; + // check for missing parts if(type == "VTable") { ParseVTable(pMemEntry, mem); continue; } - if(!(cstr_name && cstr_value)) - { - throw Error::MemoryXmlUnderspecifiedEntry(cstr_version); - } - name = cstr_name; - value = cstr_value; - if (type == "HexValue") - { - mem->setHexValue(name, value); - } - else if (type == "Address") - { - mem->setAddress(name, value); - } - else if (type == "Offset") - { - mem->setOffset(name, value); - } - else if (type == "String") - { - mem->setString(name, value); - } - else if (type == "Profession") - { - mem->setProfession(value,name); - } - else if (type == "Job") - { - mem->setJob(value,name); - } - else if (type == "Skill") - { - mem->setSkill(value,name); - } - else if (type == "Trait") + else if(type == "Offsets") { - mem->setTrait(value, name,pMemEntry->Attribute("level_0"),pMemEntry->Attribute("level_1"),pMemEntry->Attribute("level_2"),pMemEntry->Attribute("level_3"),pMemEntry->Attribute("level_4"),pMemEntry->Attribute("level_5")); - } - else if (type == "Labor") - { - mem->setLabor(value,name); - } - else if (type == "Level") - { - mem->setLevel(value, name, pMemEntry->Attribute("xpNxtLvl")); + /* + if (type == "HexValue") + { + mem->setHexValue(name, value); + } + else if (type == "Address") + { + mem->setAddress(name, value); + } + else if (type == "Offset") + { + mem->setOffset(name, value); + } + else if (type == "String") + { + mem->setString(name, value); + } + else + { + throw Error::MemoryXmlUnknownType(type.c_str()); + } + */ + //ParseOffsets(pMemEntry, mem); + continue; } - else if (type == "Mood") + else if (type == "MD5") { - mem->setMood(value, name); + const char *cstr_value = pMemEntry->Attribute("value"); + if(!cstr_value) + throw Error::MemoryXmlUnderspecifiedEntry(cstr_name); + mem->setMD5(cstr_value); } - else + else if (type == "PETimeStamp") { - throw Error::MemoryXmlUnknownType(type.c_str()); + const char *cstr_value = pMemEntry->Attribute("value"); + if(!cstr_value) + throw Error::MemoryXmlUnderspecifiedEntry(cstr_name); + mem->setPE(atol(cstr_value)); } } // for } // method @@ -240,7 +406,7 @@ bool VersionInfoFactory::loadFile(string path_to_xml) TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); - VersionInfo mem; + VersionInfo *mem; // block: name { @@ -263,31 +429,54 @@ bool VersionInfoFactory::loadFile(string path_to_xml) // transform elements { // trash existing list - for(uint32_t i = 0; i < meminfo.size(); i++) + for(uint32_t i = 0; i < versions.size(); i++) { - delete meminfo[i]; + delete versions[i]; } - meminfo.clear(); - TiXmlElement* pMemInfo=hRoot.FirstChild( "MemoryDescriptors" ).FirstChild( "Entry" ).Element(); + versions.clear(); + + // For each base version + TiXmlElement* pMemInfo=hRoot.FirstChild( "Base" ).Element(); map <string ,TiXmlElement *> map_pNamedEntries; - vector <TiXmlElement *> v_pEntries; - for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Entry")) + vector <string> v_sEntries; + for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Base")) { - v_pEntries.push_back(pMemInfo); - const char *id = pMemInfo->Attribute("id"); - if(id) + const char *name = pMemInfo->Attribute("name"); + if(name) { - string str_id = id; - map_pNamedEntries[str_id] = pMemInfo; + string str_name = name; + VersionInfo *base = new VersionInfo(); + ParseBase( pMemInfo , mem ); + knownVersions[str_name] = v_descr (pMemInfo, mem); } } - for(uint32_t i = 0; i< v_pEntries.size();i++) + + // For each derivative version + pMemInfo=hRoot.FirstChild( "Version" ).Element(); + for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Version")) + { + const char *name = pMemInfo->Attribute("name"); + if(name) + { + string str_name = name; + knownVersions[str_name] = v_descr (pMemInfo, NULL); + v_sEntries.push_back(str_name); + } + } + // Parse the versions + for(uint32_t i = 0; i< v_sEntries.size();i++) { - VersionInfo *mem = new VersionInfo(); //FIXME: add a set of entries processed in a step of this cycle, use it to check for infinite loops - /* recursive */ParseEntry( v_pEntries[i] , mem , map_pNamedEntries); - meminfo.push_back(mem); + string & name = v_sEntries[i]; + v_descr & desc = knownVersions[name]; + if(!desc.second) + { + VersionInfo *version = new VersionInfo(); + ParseVersion( desc.first , version ); + versions.push_back(version); + } } + // process found things here } error = false; |
