diff --git a/MiniEngine_Xml.cpp b/MiniEngine_Xml.cpp index af67694..04a35e5 100644 --- a/MiniEngine_Xml.cpp +++ b/MiniEngine_Xml.cpp @@ -15,7 +15,7 @@ XMLDB::~XMLDB() close(); } -int XMLDB::open(const std::string& XMLFileName) +int XMLDB::open(const std::string& XMLFileName,bool saveOnClose) { if(_opened) return -2; @@ -23,9 +23,12 @@ int XMLDB::open(const std::string& XMLFileName) { rapidxml::file<> temp(XMLFileName.c_str()); _doc.parse<0>(temp.data()); + _rootnode=_doc.first_node("Database"); + _dbinfo=_rootnode->first_node("DBInfo"); _filename=XMLFileName; _opened=true; _changed=false; + _autosave_onclose=saveOnClose; } catch(...) { @@ -35,12 +38,35 @@ int XMLDB::open(const std::string& XMLFileName) return 0; } +int XMLDB::create(const std::string& XMLFileName) +{ + if(_opened) return -2; + _rootnode=_doc.allocate_node(rapidxml::node_element,"Database"); + _dbinfo=_doc.allocate_node(rapidxml::node_element,"DBInfo"); + _tbinfo=_doc.allocate_node(rapidxml::node_element,"TableInfo"); + _tbroot=_doc.allocate_node(rapidxml::node_element,"Tables"); + + _dbinfo->append_node(_tbinfo); + + _rootnode->append_node(_dbinfo); + _rootnode->append_node(_tbroot); + + _doc.append_node(_rootnode); + + _opened=true; + _changed=true; + _autosave_onclose=true; + _filename=XMLFileName; + return 0; +} + int XMLDB::save() { if(!_opened) return -2; if(!_changed) return 0; std::ofstream ofs(_filename); ofs<<_doc; + _changed=false; return 0; } @@ -48,6 +74,8 @@ int XMLDB::close() { if(!_opened) return 0; + if(_autosave_onclose) save(); + _doc.clear(); _filename.clear(); _opened=false; @@ -59,87 +87,65 @@ bool XMLDB::isopen() const return _opened; } -rapidxml::xml_node<>* XMLDB::getDBroot(const std::string& dbname) +void XMLDB::setChanged() { - for(rapidxml::xml_node<>* root=_doc.first_node("Database");root!=nullptr;root=root->next_sibling("Database")) - { - rapidxml::xml_attribute<>* attr=root->first_attribute("name"); - if(attr==nullptr||dbname!=attr->value()) continue; - else return root; - } - - return nullptr; + _changed=true; } +// protected +bool XMLDB::isNameUnique(const std::string& tbname) +{ + return _tbroot->first_node(tbname.c_str()) == nullptr; +} + +int XMLDB::newTB(const std::string& tbname,const std::vector& colname) +{ + if(tbname.empty()) return -1; + if(!isNameUnique(tbname)) return -2; + + char* stra=_doc.allocate_string(tbname.c_str()); + node* newtb=_doc.allocate_node(rapidxml::node_element,stra); + + node* newinfo=_doc.allocate_node(rapidxml::node_element,stra); + for(size_t i=0;iappend_node(_doc.allocate_node(rapidxml::node_element,"col",_doc.allocate_string(colname.at(i).c_str()))); + } + + _tbinfo->append_node(newinfo); + _tbroot->append_node(newtb); + + return 0; +} + +int XMLDB::dropTB(const std::string& tbname) +{ + node* tbnode=getTBroot(tbname); + _tbroot->remove_node(tbnode); + _tbinfo->remove_node(_tbinfo->first_node(tbname.c_str())); + setChanged(); + return 0; +} + +int XMLDB::dropAllTB() +{ + _tbroot->remove_all_nodes(); + _tbinfo->remove_all_nodes(); + setChanged(); + return 0; +} + +// protected +XMLDB::node* XMLDB::getTBroot(const std::string& tbname) +{ + return _tbroot->first_node(tbname.c_str()); +} + +//experimental rapidxml::xml_document<>* XMLDB::getdoc() { return &_doc; } -XMLController::XMLController() -{ - _pdb=nullptr; -} - -XMLController::~XMLController() -{ - -} - -int XMLController::connect(const XMLDB& xmldb) -{ - if(!xmldb.isopen()) - { - return -1; - } - _pdb=const_cast(&xmldb); - return 0; -} - -int XMLController::usedb(const std::string& dbname) -{ - rapidxml::xml_node<>* node=_pdb->getDBroot(dbname); - if(node==nullptr) - { - return -1; - } - else - { - _dbroot=node; - return 0; - } - return 0; -} - -int XMLController::createdb(const std::string& dbname,std::vector& colname) -{ - if(dbname.empty()) return -1; - - if(_pdb->getDBroot(dbname)!=nullptr) - { - /// Invalid Name (Same as another database). - return -2; - } - rapidxml::xml_node<>* newnode=_pdb->getdoc()->allocate_node(rapidxml::node_element,"Database"); - if(newnode==nullptr) return -3; - rapidxml::xml_attribute<>* newattr=_pdb->getdoc()->allocate_attribute("name",dbname.c_str()); - if(newattr==nullptr) - { - /// FIXME: What will happen to newnode? - return -4; - } - rapidxml::xml_node<>* dbinfonode=_pdb->getdoc()->allocate_node(rapidxml::node_element,"DBInfo"); - if(dbinfonode==nullptr) return -5; - for(size_t i=0;i* ntnode=_pdb->getdoc()->allocate_node(rapidxml::node_element,"colname",colname.at(i).c_str()); - if(ntnode==nullptr) return -6; - dbinfonode->append_node(ntnode); - } - newnode->append_node(dbinfonode); - newnode->append_attribute(newattr); - - return 0; -} }///End of namespace MiniEngine diff --git a/MiniEngine_Xml.h b/MiniEngine_Xml.h index 991cfda..bf4fecc 100644 --- a/MiniEngine_Xml.h +++ b/MiniEngine_Xml.h @@ -15,41 +15,61 @@ namespace MiniEngine class XMLDB : public MiniEngine::NonCopyable { public: + typedef rapidxml::xml_node<> node; + typedef rapidxml::xml_attribute<> attribute; + typedef rapidxml::xml_document<> document; + XMLDB(); ~XMLDB(); - int open(const std::string& XMLFileName); + int open(const std::string& XMLFileName,bool saveOnClose); + int create(const std::string& XMLFileName); int save(); int close(); bool isopen() const; - rapidxml::xml_node<>* getDBroot(const std::string& dbname); + /// Create a table with colname, returns table node + int newTB(const std::string& tbname,const std::vector& colname); + /// Insert a col before a index (use -1 for push back) + int newTBCol(const std::string& tbname,const std::string& newColname,int insertBefore); - /// Directly Get Document - rapidxml::xml_document<>* getdoc(); + int newTBRow(const std::string& tbname,const std::vector& rowval,int insertBefore); + + int setTBRow(const std::string& tbname,int rowid,const std::vector& rowval); + + int getTBRow(const std::string& tbname,int rowid,std::vector& out_rowval); + + int dropTBRow(const std::string& tbname,int rowid); + + /// Get Table Col Size + int getTBColsize(const std::string& tbname); + /// Drop a table + int dropTB(const std::string& tbname); + /// Drop all table + int dropAllTB(); + + /// Directly Get Document (Experimental) + document* getdoc(); + /// Announce something changed + void setChanged(); +protected: + bool isNameUnique(const std::string& tbname); + /// Get root node of a table + node* getTBroot(const std::string& tbname); private: - rapidxml::xml_document<> _doc; + document _doc; + + node* _rootnode; + + node* _dbinfo; + node* _tbinfo; + + node* _tbroot; + bool _changed; bool _opened; + bool _autosave_onclose; std::string _filename; }; -class XMLController -{ -public: - XMLController(); - ~XMLController(); - int connect(const XMLDB& xmldb); - int usedb(const std::string& dbname); - int createdb(const std::string& dbname,std::vector& colname); - int dropdb(const std::string& dbname); - int close(); - - int execute(const std::string& command); - int execute(const std::string& command,std::vector& vec); -private: - XMLDB* _pdb; - std::string _dbname; - rapidxml::xml_node<>* _dbroot; -}; }/// End of namespace MiniEngine