#include #include #include #include #include #include #include "XML_Parser.h" #include "XMLWriter.h" #include "DEBUG.H" vfs::PropertyContainer::TagMap::TagMap() { // setup default map _map[L"Container"] = L"Container"; _map[L"Section"] = L"Section"; _map[L"SectionID"] = L"name"; _map[L"Key"] = L"Key"; _map[L"KeyID"] = L"name"; } vfs::String const& vfs::PropertyContainer::TagMap::container(vfs::String::char_t* container) { if(container) { _map[L"Container"] = container; } return _map[L"Container"]; } vfs::String const& vfs::PropertyContainer::TagMap::section(vfs::String::char_t* section) { if(section) { _map[L"Section"] = section; } return _map[L"Section"]; } vfs::String const& vfs::PropertyContainer::TagMap::sectionID(vfs::String::char_t* section_id) { if(section_id) { _map[L"SectionID"] = section_id; } return _map[L"SectionID"]; } vfs::String const& vfs::PropertyContainer::TagMap::key(vfs::String::char_t* key) { if(key) { _map[L"Key"] = key; } return _map[L"Key"]; } vfs::String const& vfs::PropertyContainer::TagMap::keyID(vfs::String::char_t* key_id) { if(key_id) { _map[L"KeyID"] = key_id; } return _map[L"KeyID"]; } bool vfs::PropertyContainer::writeToXMLFile(vfs::Path const& sFileName, vfs::PropertyContainer::TagMap& tagmap) { XMLWriter xmlw; xmlw.openNode(tagmap.container()); tSections::iterator sit = m_mapProps.begin(); for(; sit != m_mapProps.end(); ++sit) { xmlw.addAttributeToNextValue(tagmap.sectionID(),sit->first.utf8()); xmlw.openNode(tagmap.section()); vfs::PropertyContainer::Section& section = sit->second; vfs::PropertyContainer::Section::tProps::iterator kit = section.mapProps.begin(); for(; kit != section.mapProps.end(); ++kit) { xmlw.addAttributeToNextValue(tagmap.keyID(), kit->first.utf8()); xmlw.addValue(tagmap.key(), kit->second.utf8()); } xmlw.closeNode(); } xmlw.closeNode(); return xmlw.writeToFile(sFileName); } /*********************************************************************************/ /*********************************************************************************/ class CPropertyXMLParser : public IXMLParser { enum DOM_OBJECT { DO_ELEMENT_Container, DO_ELEMENT_Section, DO_ELEMENT_Key, DO_ELEMENT_NONE, }; public: CPropertyXMLParser( vfs::PropertyContainer& container, vfs::PropertyContainer::TagMap& tagmap, XML_Parser &parser, IXMLParser* caller = NULL) : IXMLParser("",&parser,caller), _container(container), _tagmap(tagmap), current_state(DO_ELEMENT_NONE) // doesn't matter where we come from, we start fresh {}; virtual void onStartElement(const XML_Char* name, const XML_Char** atts); virtual void onEndElement(const XML_Char* name); virtual void onTextElement(const XML_Char *str, int len); private: vfs::PropertyContainer& _container; vfs::PropertyContainer::TagMap& _tagmap; DOM_OBJECT current_state; vfs::String current_section; vfs::String current_key; }; void CPropertyXMLParser::onStartElement(const XML_Char *name, const XML_Char **atts) { vfs::String utf8_name(name); if(current_state == DO_ELEMENT_NONE && vfs::StrCmp::Equal(utf8_name,_tagmap.container())) { current_state = DO_ELEMENT_Container; } else if(current_state == DO_ELEMENT_Container && vfs::StrCmp::Equal(utf8_name, _tagmap.section())) { current_state = DO_ELEMENT_Section; current_section = this->getAttribute(_tagmap.sectionID().utf8().c_str(),atts); } else if(current_state == DO_ELEMENT_Section && vfs::StrCmp::Equal(utf8_name, _tagmap.key())) { current_state = DO_ELEMENT_Key; current_key = this->getAttribute(_tagmap.keyID().utf8().c_str(),atts); } sCharData = ""; } void CPropertyXMLParser::onEndElement(const XML_Char* name) { vfs::String utf8_name(name); if(current_state == DO_ELEMENT_Key && vfs::StrCmp::Equal(utf8_name, _tagmap.key())) { _container.setStringProperty(current_section, current_key, vfs::trimString(sCharData,0,sCharData.length())); current_state = DO_ELEMENT_Section; } else if(current_state == DO_ELEMENT_Section && vfs::StrCmp::Equal(utf8_name, _tagmap.section())) { current_state = DO_ELEMENT_Container; } else if(current_state == DO_ELEMENT_Container && vfs::StrCmp::Equal(utf8_name, _tagmap.container())) { current_state = DO_ELEMENT_NONE; } } void CPropertyXMLParser::onTextElement(const XML_Char *str, int len) { if(current_state == DO_ELEMENT_Key) { sCharData.append(str,len); } } bool vfs::PropertyContainer::initFromXMLFile(vfs::Path const& sFileName, vfs::PropertyContainer::TagMap& tagmap) { vfs::tReadableFile *file = NULL; bool delete_file = false; if(getVFS()->fileExists(sFileName)) { vfs::COpenReadFile rfile(sFileName); file = &rfile.file(); rfile.release(); } else { vfs::CFile* rfile = new vfs::CFile(sFileName); delete_file = true; file = vfs::tReadableFile::cast(rfile); if(!file->openRead()) { delete file; return false; } } if(!file) { return false; } vfs::size_t size = file->getSize(); std::vector buffer(size+1); SGP_TRYCATCH_RETHROW( file->read(&buffer[0],size), L"" ); buffer[size] = 0; file->close(); if(delete_file) delete file; XML_Parser parser = XML_ParserCreate(NULL); CPropertyXMLParser pp(*this,tagmap,parser,NULL); pp.grabParser(); if(!XML_Parse(parser, &buffer[0], size, TRUE)) { std::wstringstream wss; wss << L"XML Parser Error in Groups.xml: " << vfs::String::as_utf16(XML_ErrorString(XML_GetErrorCode(parser))) << L" at line " << XML_GetCurrentLineNumber(parser); SGP_THROW(wss.str().c_str()); //return false; } return true; }