tag map file parser in C++ by using dkutil
Powered by dKingyo VB2005 | ポケットリファレンス | 図解 辞典 | AJAX | TurboGears
と言う事で、dkutilを使って簡易パーサー書きました。
ちなみにこの日記を書いている時点でdkutilはリリースされていませんのであしからず。
ロジックを見て各自、移植してください。
#include <helper/boost_assert.hpp> #include <dkutil/dktl/map_ex.hpp> #include <dkutil/filesystem/std_filestream.hpp> #include <dkutil/detail/convert_interface.hpp> #include <dkutil/filesystem/path_string.hpp> namespace dkutil{ inline std::string file_to_string(path_string_ref filename) { std_filestream x; std::string::value_type v[1024]; size_t rs; std::string str; if(false==x.reset(filename,read_mode | text_mode) || false==x.open()) { throw convert_error("file_to_string error"); } for(;x.eof()==false;) {//buffer overflow対策は万全 v[1024 - 1] = '\0'; rs = x.read(v,1024 - 1); dkcmNOT_ASSERT(rs > 1024 - 1); v[rs] = '\0'; str += v; } return str; } struct tag_map_file : public map_ex<std::string,std::string>{ typedef map_ex<std::string,std::string> base_type; typedef base_type::iterator iterator; typedef base_type::const_iterator const_iterator; typedef base_type::value_type value_type; typedef base_type::DATA_TYPE DATA_TYPE; bool parse(const char *str,size_t size,const char *tag="</>") { size_t i,state = 0; DATA_TYPE v; for(i=0;i<size;i++){ switch(state){ case 0: v.first.clear(); v.second.clear(); //*<name> if(tag[0] == str[i]){ state = 1; } break; case 1: //<*name> if(tag[2] == str[i]){ state = 2; break; } v.first += str[i]; break; case 2://<name>*</name> if(tag[0] == str[i] && tag[1] == str[i+1]) {//NULL文字あるからAccess Violationにはならない size_t j,len = v.first.size(); if(size - i > len){ //後ろのタグを抜き出す std::string vl; for(j=0;j<len;j++){ vl += str[i+j+2]; } if(vl != v.first){ v.second += str[i]; break;//別の終了タグだった。 } } state = 3; i++;// "</" を抜かす break; } v.second += str[i]; break; case 3://</*name> if(tag[2] == str[i]){ state = 0; if(false==base_type::rb_insert(v)){ return false; } } break; default: throw -1; }//eos }//eof return true; } }; }//end of namespace using namespace dkutil; #include <iostream> using namespace std; int main(int argc,const char **argv) { tag_map_file tsf; if(argc <= 1) return -1; std::string str = file_to_string(argv[1]); tsf.parse(str.c_str(),str.size()); tag_map_file::iterator it = tsf.begin(); for(;it != tsf.end();it++) { std::string tx = (*it).first.c_str(); cout <<"key : " << tx << endl; cout <<"contents : " <<endl; tx = (*it).second.c_str(); cout << tx << endl; cout <<"---------------------------------" << endl; } return 0; }
追記:ChangeLog
- 20070323:データ部にHTMLタグが記述されているとタグ終了の部分が削除されるバグをFIX