1 /* 2 * Copyright 2011 kubtek <kubtek@mail.com> 3 * 4 * This file is part of StarDict. 5 * 6 * StarDict is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * StarDict is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with StarDict. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef _STDDICT_HPP_ 21 #define _STDDICT_HPP_ 22 23 #include "stardict_libconfig.h" 24 25 #include <glib.h> 26 #include <string> 27 #include <vector> 28 #include <list> 29 #include <map> 30 31 #include "dictbase.h" 32 #include "collation.h" 33 #include "dictbase.h" 34 #include "storage.h" 35 #include "libcommon.h" 36 #include "dictitemid.h" 37 38 const int MAX_FUZZY_DISTANCE= 3; // at most MAX_FUZZY_DISTANCE-1 differences allowed when find similar words 39 const int MAX_MATCH_ITEM_PER_LIB=100; 40 41 /* Collation support. Effects word list sort order. */ 42 enum CollationLevelType { 43 /* Do not use collation functions */ 44 CollationLevel_NONE = 0, 45 /* Use collation function to sort word list. 46 * Only one collation function may be selected per index or synonym file. 47 * To change the collation function, the dictionary must be reloaded. 48 * The collation function is selected once for all dictionaries at startup. 49 * To switch to this mode open the Preferences dialog, 50 * Dictionary, Cache; check "Sort word list by collation function" and 51 * select a collation function. */ 52 CollationLevel_SINGLE = 1, 53 /* Use collation to sort word list. 54 * Multiple collation functions may be used per index or synonym file. 55 * Collation functions are loaded on the first use (to be precise, the word 56 * list is sorted according the selected collation function on the first use). 57 * This mode is not fully implemented. User interface does not 58 * provide an option to switch to this mode. */ 59 CollationLevel_MULTI = 2, 60 }; 61 62 extern gint stardict_strcmp(const gchar *s1, const gchar *s2); 63 extern gint stardict_server_collate(const gchar *str1, const gchar *str2, CollationLevelType CollationLevel, CollateFunctions func, int servercollatefunc); 64 65 66 class show_progress_t { 67 public: ~show_progress_t()68 virtual ~show_progress_t() {} notify_about_start(const std::string & title)69 virtual void notify_about_start(const std::string& title) {} notify_about_work()70 virtual void notify_about_work() {} 71 }; 72 73 enum CacheFileType { 74 CacheFileType_oft, 75 CacheFileType_clt, 76 CacheFileType_server_clt, 77 }; 78 79 /* url and saveurl parameters that appear on the same level, function parameters, 80 * for example, normally have the following meaning. 81 * url - the real file, the cache was build for. That file exists in file system. 82 * saveurl - the file that url represents. Use saveurl to construct cache file name. 83 * Often url = saveurl. 84 * They may be different in the case url is a compressed index, then saveurl 85 * names uncompressed index. For example, 86 * url = ".../mydict.idx.gz" 87 * saveurl = ".../mydict.idx" 88 * 89 * for uncompressed index: 90 * url = ".../mydict.idx" 91 * saveurl = ".../mydict.idx" 92 * 93 * Cache file searching algorithm 94 * 95 * This algorithm is used in load_cache and save_cache functions. 96 * 1. Search for cache file in the directory of the saveurl parameter. 97 * 1.1. Build primary file name: saveurl + ".oft". (We use here .oft file as example) 98 * 1.2. Check if that file is the target cache file. If yes, stop search. 99 * 1.3. Build next file name: dirname(saveurl) + "/" + basename(saveurl) + "(" + num + ")" + ext(saveurl) + ".oft" 100 * 1.4. num++, goto 1.2. 101 * 2. Search for cache file in the user cache directory (app_dirs->get_user_cache_dir()). 102 * 2.1. Build primary file name: user_cache_dir + filename(saveurl) + ".oft" 103 * ... 104 * */ 105 class cache_file { 106 public: 107 cache_file(CacheFileType _cachefiletype, CollateFunctions _cltfunc); 108 ~cache_file(); 109 /* Return value: true - success, false - fault. 110 * If loaded successfully, mf contains the loaded file, 111 * wordoffset points to the portion of the mapped file containing offsets. 112 * If load failed, mf and wordoffset are not changed. */ 113 bool load_cache(const std::string& url, const std::string& saveurl, glong filedatasize); 114 /* (Re)create cache file. Member data do not change. 115 * Content of the cache file is build from wordoffset array and parameters of this function. 116 * Note that this function does not load the saved file, mf member is not used. */ 117 bool save_cache(const std::string& saveurl) const; 118 // datasize in bytes 119 void allocate_wordoffset(size_t _npages); get_wordoffset(size_t ind)120 guint32& get_wordoffset(size_t ind) 121 { 122 return wordoffset[ind]; 123 } get_wordoffset(void)124 guint32* get_wordoffset(void) 125 { 126 return wordoffset; 127 } get_CollateFunction(void)128 CollateFunctions get_CollateFunction(void) const 129 { 130 return cltfunc; 131 } 132 133 private: 134 /* If mf != NULL, then wordoffset points to part of mapped file, it should not be freed. 135 * Otherwise wordoffset must be freed with g_free. */ 136 guint32 *wordoffset; 137 /* size of the wordoffset array */ 138 size_t npages; 139 CacheFileType cachefiletype; 140 MapFile *mf; 141 CollateFunctions cltfunc; 142 /* The following functions do not change member data, they return result though parameters. */ 143 bool build_primary_cache_filename_in_user_cache(const std::string& url, std::string &cachefilename, bool create) const; 144 MapFile* find_and_load_cache_file(const gchar *filename, const std::string &url, const std::string &saveurl, glong filedatasize, int next) const; 145 FILE* find_and_open_for_overwrite_cache_file(const gchar *filename, const std::string &saveurl, int next, std::string &cfilename) const; 146 gchar *get_next_filename( 147 const gchar *dirname, const gchar *basename, int num, 148 const gchar *extendname) const; 149 void build_primary_cache_filename(const std::string &url, 150 std::string &filename) const; 151 }; 152 153 class idxsyn_file; 154 class collation_file : public cache_file { 155 public: 156 collation_file(idxsyn_file *_idx_file, CacheFileType _cachefiletype, 157 CollateFunctions _CollateFunction); 158 bool lookup(const char *str, glong &idx, glong &idx_suggest); 159 const gchar *GetWord(glong idx); 160 glong GetOrigIndex(glong cltidx); 161 private: 162 idxsyn_file *idx_file; 163 }; 164 165 /* This class serves as root for classes representing index and synonym files. 166 * The class provides two main services getWord and Lookup and 167 * declares get_key and lookup pure virtual functions that must be implemented in derived classes. 168 * 169 * We may access the underlying index (synonym) file either directly or 170 * in the order specified by collate function. 171 * Direct access to the underlying file is possible immediately after the derived class completed 172 * initialization process (which include assigning protected wordcount member). 173 * To access the file in collate function order, additional initialization is required. 174 * 175 * First, you must specify the underlying index (synonym) file url with collate_save_info method. 176 * Second, you must initialize the collation object with collate_load method. 177 * This class is initialized either for CollationLevel_SINGLE or for CollationLevel_MULTI 178 * collation level type. 179 * 180 * In the CollationLevel_SINGLE case, clt_file is initialized. 181 * Now getWord and Lookup may be called with CollationLevel = CollationLevel_SINGLE, 182 * get_clt_file() returns non-NULL collation file. 183 * 184 * In the CollationLevel_MULTI case, clt_files[your_collate_func] is initialized. 185 * Since now, you may invoke getWord and Lookup with CollationLevel = CollationLevel_MULTI, 186 * servercollatefunc = your_collate_func. get_clt_file(your_collate_func) returns non-NULL. 187 * In fact, for getWord and Lookup invoke the collate_load internally, should a need be. 188 */ 189 class idxsyn_file { 190 public: 191 idxsyn_file(); 192 virtual ~idxsyn_file(); 193 const gchar *getWord(glong idx, CollationLevelType CollationLevel, int servercollatefunc); 194 bool Lookup(const char *str, glong &idx, glong &idx_suggest, CollationLevelType CollationLevel, int servercollatefunc); 195 virtual const gchar *get_key(glong idx) = 0; 196 virtual bool lookup(const char *str, glong &idx, glong &idx_suggest) = 0; 197 void collate_save_info(const std::string& _url, const std::string& _saveurl); 198 void collate_load(CollateFunctions collf, CollationLevelType CollationLevel, show_progress_t *sp = 0); get_clt_file(void)199 collation_file * get_clt_file(void) { return clt_file; } get_clt_file(size_t ind)200 collation_file * get_clt_file(size_t ind) { return clt_files[ind]; } get_word_count(void)201 glong get_word_count(void) const { return wordcount; } 202 private: 203 collation_file * collate_load_impl( 204 const std::string& _url, const std::string& _saveurl, 205 CollateFunctions collf, show_progress_t *sp, CacheFileType CacheType); 206 std::string url; 207 std::string saveurl; 208 collation_file *clt_file; 209 collation_file *clt_files[COLLATE_FUNC_NUMS]; 210 protected: 211 // number of words in the index 212 glong wordcount; 213 }; 214 215 class index_file : public idxsyn_file { 216 public: 217 /* get_data and get_key_and_data methods return their result through these 218 * members. */ 219 guint32 wordentry_offset; 220 guint32 wordentry_size; 221 222 static index_file* Create(const std::string& filebasename, 223 const char* mainext, std::string& fullfilename); 224 virtual bool load(const std::string& url, gulong wc, gulong fsize, 225 bool CreateCacheFile, CollationLevelType CollationLevel, 226 CollateFunctions _CollateFunction, show_progress_t *sp) = 0; 227 virtual void get_data(glong idx) = 0; 228 virtual const gchar *get_key_and_data(glong idx) = 0; 229 virtual bool lookup(const char *str, glong &idx, glong &idx_suggest) = 0; 230 }; 231 232 class synonym_file : public idxsyn_file { 233 public: 234 guint32 wordentry_index; 235 236 synonym_file(); 237 ~synonym_file(); 238 bool load(const std::string& url, gulong wc, bool CreateCacheFile, 239 CollationLevelType CollationLevel, CollateFunctions _CollateFunction, 240 show_progress_t *sp); 241 private: 242 const gchar *get_key(glong idx); 243 bool lookup(const char *str, glong &idx, glong &idx_suggest); 244 245 static const gint ENTR_PER_PAGE=32; 246 gulong npages; 247 248 /* offset cache file. Contains offsets in the original synonym file. 249 * Selected collation level and collate function have no effect on this cache. */ 250 cache_file oft_file; 251 FILE *synfile; 252 253 gchar wordentry_buf[MAX_INDEX_KEY_SIZE+sizeof(guint32)]; 254 struct index_entry { 255 glong idx; 256 std::string keystr; assignindex_entry257 void assign(glong i, const std::string& str) { 258 idx=i; 259 keystr.assign(str); 260 } 261 }; 262 index_entry first, last, middle, real_last; 263 264 struct page_entry { 265 gchar *keystr; 266 guint32 index; 267 }; 268 std::vector<gchar> page_data; 269 struct page_t { 270 glong idx; 271 page_entry entries[ENTR_PER_PAGE]; 272 page_tpage_t273 page_t(): idx(-1) {} 274 void fill(gchar *data, gint nent, glong idx_); 275 } page; 276 gulong load_page(glong page_idx); 277 const gchar *read_first_on_page_key(glong page_idx); 278 const gchar *get_first_on_page_key(glong page_idx); 279 }; 280 281 class Dict : public DictBase { 282 private: 283 /* in file name encoding */ 284 std::string ifo_file_name; 285 std::string bookname; // in utf-8 286 std::string dicttype; // in utf-8 287 288 /* ifofilename in file name encoding */ 289 bool load_ifofile(const std::string& ifofilename, gulong &idxfilesize, glong &wordcount, glong &synwordcount); 290 public: 291 std::auto_ptr<index_file> idx_file; 292 std::auto_ptr<synonym_file> syn_file; 293 ResourceStorage *storage; 294 295 Dict(); 296 ~Dict(); 297 /* ifofilename in file name encoding */ 298 bool load(const std::string &ifofilename, bool CreateCacheFile, 299 CollationLevelType CollationLevel, CollateFunctions CollateFunction, 300 show_progress_t *sp); 301 narticles()302 glong narticles() const { return idx_file->get_word_count(); } 303 glong nsynarticles() const; dict_name()304 const std::string& dict_name() const { return bookname; } dict_type()305 const std::string& dict_type() const { return dicttype; } ifofilename()306 const std::string& ifofilename() const { return ifo_file_name; } id()307 DictItemId id() const { return DictItemId(ifo_file_name); } 308 get_data(glong index)309 gchar *get_data(glong index) 310 { 311 idx_file->get_data(index); 312 return DictBase::GetWordData(idx_file->wordentry_offset, idx_file->wordentry_size); 313 } get_key_and_data(glong index,const gchar ** key,guint32 * offset,guint32 * size)314 void get_key_and_data(glong index, const gchar **key, guint32 *offset, guint32 *size) 315 { 316 *key = idx_file->get_key_and_data(index); 317 *offset = idx_file->wordentry_offset; 318 *size = idx_file->wordentry_size; 319 } Lookup(const char * str,glong & idx,glong & idx_suggest,CollationLevelType CollationLevel,int servercollatefunc)320 bool Lookup(const char *str, glong &idx, glong &idx_suggest, CollationLevelType CollationLevel, int servercollatefunc) 321 { 322 return idx_file->Lookup(str, idx, idx_suggest, CollationLevel, servercollatefunc); 323 } 324 bool LookupSynonym(const char *str, glong &synidx, glong &synidx_suggest, CollationLevelType CollationLevel, int servercollatefunc); 325 bool LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen); 326 bool LookupWithRuleSynonym(GPatternSpec *pspec, glong *aIndex, int iBuffLen); 327 bool LookupWithRegex(GRegex *regex, glong *aIndex, int iBuffLen); 328 bool LookupWithRegexSynonym(GRegex *regex, glong *aIndex, int iBuffLen); 329 gint GetOrigWordCount(glong& iWordIndex, bool isidx); 330 bool GetWordPrev(glong iWordIndex, glong &pidx, bool isidx, CollationLevelType CollationLevel, int servercollatefunc); 331 void GetWordNext(glong &iWordIndex, bool isidx, CollationLevelType CollationLevel, int servercollatefunc); 332 }; 333 334 struct CurrentIndex { 335 glong idx; 336 glong idx_suggest; 337 glong synidx; 338 glong synidx_suggest; 339 }; 340 341 class Libs { 342 public: 343 /* func is only used when level is CollationLevel_SINGLE, 344 * otherwise function must be COLLATE_FUNC_NONE. */ 345 Libs(show_progress_t *sp, bool create_cache_files, CollationLevelType level, CollateFunctions func); 346 ~Libs(); set_show_progress(show_progress_t * sp)347 void set_show_progress(show_progress_t *sp) { 348 if (sp) 349 show_progress = sp; 350 else 351 show_progress = &default_show_progress; 352 } get_show_progress(void)353 show_progress_t *get_show_progress(void) const 354 { 355 return show_progress; 356 } get_CollationLevel()357 CollationLevelType get_CollationLevel() const { return CollationLevel; } get_CollateFunction()358 CollateFunctions get_CollateFunction() const { return CollateFunction; } 359 bool load_dict(const std::string& url, show_progress_t *sp); 360 #ifdef SD_SERVER_CODE 361 void LoadFromXML(); 362 void SetServerDictMask(std::vector<InstantDictIndex> &dictmask, const char *dicts, int max, int level); 363 void LoadCollateFile(std::vector<InstantDictIndex> &dictmask, CollateFunctions cltfuc); 364 const std::string *get_dir_info(const char *path); 365 const std::string *get_dict_info(const char *uid, bool is_short); 366 const std::string &get_fromto_info(); 367 std::string get_dicts_list(const char *dicts, int max_dict_count, int userLevel); 368 int get_dict_level(const char *uid); 369 #endif 370 #ifdef SD_CLIENT_CODE 371 bool find_lib_by_id(const DictItemId& filename, size_t &iLib); 372 void load(const std::list<std::string> &load_list); 373 void reload(const std::list<std::string> &load_list, CollationLevelType NewCollationLevel, CollateFunctions collf); 374 #endif 375 narticles(size_t idict)376 glong narticles(size_t idict) const { return oLib[idict]->narticles(); } nsynarticles(size_t idict)377 glong nsynarticles(size_t idict) const { return oLib[idict]->nsynarticles(); } dict_name(size_t idict)378 const std::string& dict_name(size_t idict) const { return oLib[idict]->dict_name(); } dict_type(size_t idict)379 const std::string& dict_type(size_t idict) const { return oLib[idict]->dict_type(); } has_dict()380 bool has_dict() const { return !oLib.empty(); } 381 poGetWord(glong iIndex,size_t iLib,int servercollatefunc)382 const gchar * poGetWord(glong iIndex,size_t iLib, int servercollatefunc) const { 383 return oLib[iLib]->idx_file->getWord(iIndex, CollationLevel, servercollatefunc); 384 } poGetOrigWord(glong iIndex,size_t iLib)385 const gchar * poGetOrigWord(glong iIndex,size_t iLib) const { 386 return oLib[iLib]->idx_file->getWord(iIndex, CollationLevel_NONE, 0); 387 } poGetSynonymWord(glong iSynonymIndex,size_t iLib,int servercollatefunc)388 const gchar * poGetSynonymWord(glong iSynonymIndex,size_t iLib, int servercollatefunc) const { 389 return oLib[iLib]->syn_file->getWord(iSynonymIndex, CollationLevel, servercollatefunc); 390 } poGetOrigSynonymWord(glong iSynonymIndex,size_t iLib)391 const gchar * poGetOrigSynonymWord(glong iSynonymIndex,size_t iLib) const { 392 return oLib[iLib]->syn_file->getWord(iSynonymIndex, CollationLevel_NONE, 0); 393 } poGetOrigSynonymWordIdx(glong iSynonymIndex,size_t iLib)394 glong poGetOrigSynonymWordIdx(glong iSynonymIndex, size_t iLib) const { 395 oLib[iLib]->syn_file->getWord(iSynonymIndex, CollationLevel_NONE, 0); 396 return oLib[iLib]->syn_file->wordentry_index; 397 } 398 glong CltIndexToOrig(glong cltidx, size_t iLib, int servercollatefunc); 399 glong CltSynIndexToOrig(glong cltidx, size_t iLib, int servercollatefunc); poGetOrigWordData(glong iIndex,size_t iLib)400 gchar * poGetOrigWordData(glong iIndex,size_t iLib) { 401 if (iIndex==INVALID_INDEX) 402 return NULL; 403 return oLib[iLib]->get_data(iIndex); 404 } 405 const gchar *GetSuggestWord(const gchar *sWord, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc); 406 const gchar *poGetCurrentWord(CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc); 407 const gchar *poGetNextWord(const gchar *word, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc); 408 const gchar *poGetPreWord(const gchar *word, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc); LookupWord(const gchar * sWord,glong & iWordIndex,glong & idx_suggest,size_t iLib,int servercollatefunc)409 bool LookupWord(const gchar* sWord, glong& iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc) { 410 return oLib[iLib]->Lookup(sWord, iWordIndex, idx_suggest, CollationLevel, servercollatefunc); 411 } LookupSynonymWord(const gchar * sWord,glong & iSynonymIndex,glong & synidx_suggest,size_t iLib,int servercollatefunc)412 bool LookupSynonymWord(const gchar* sWord, glong& iSynonymIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc) { 413 return oLib[iLib]->LookupSynonym(sWord, iSynonymIndex, synidx_suggest, CollationLevel, servercollatefunc); 414 } 415 bool LookupSimilarWord(const gchar* sWord, glong &iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc); 416 bool LookupSynonymSimilarWord(const gchar* sWord, glong &iSynonymWordIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc); 417 bool SimpleLookupWord(const gchar* sWord, glong &iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc); 418 bool SimpleLookupSynonymWord(const gchar* sWord, glong &iWordIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc); GetOrigWordCount(glong & iWordIndex,size_t iLib,bool isidx)419 gint GetOrigWordCount(glong& iWordIndex, size_t iLib, bool isidx) { 420 return oLib[iLib]->GetOrigWordCount(iWordIndex, isidx); 421 } GetWordPrev(glong iWordIndex,glong & pidx,size_t iLib,bool isidx,int servercollatefunc)422 bool GetWordPrev(glong iWordIndex, glong &pidx, size_t iLib, bool isidx, int servercollatefunc) { 423 return oLib[iLib]->GetWordPrev(iWordIndex, pidx, isidx, CollationLevel, servercollatefunc); 424 } GetWordNext(glong & iWordIndex,size_t iLib,bool isidx,int servercollatefunc)425 void GetWordNext(glong &iWordIndex, size_t iLib, bool isidx, int servercollatefunc) { 426 oLib[iLib]->GetWordNext(iWordIndex, isidx, CollationLevel, servercollatefunc); 427 } 428 429 bool LookupWithFuzzy(const gchar *sWord, gchar *reslist[], gint reslist_size, std::vector<InstantDictIndex> &dictmask); 430 gint LookupWithRule(const gchar *sWord, gchar *reslist[], std::vector<InstantDictIndex> &dictmask); 431 gint LookupWithRegex(const gchar *sWord, gchar *reslist[], std::vector<InstantDictIndex> &dictmask); 432 433 typedef void (*updateSearchDialog_func)(gpointer data, gdouble fraction); 434 bool LookupData(const gchar *sWord, std::vector<gchar *> *reslist, updateSearchDialog_func func, gpointer data, bool *cancel, std::vector<InstantDictIndex> &dictmask); 435 StorageType GetStorageType(size_t iLib); 436 FileHolder GetStorageFilePath(size_t iLib, const std::string &key); 437 const char *GetStorageFileContent(size_t iLib, const std::string &key); 438 private: 439 void init_collations(); 440 void free_collations(); 441 bool LookupSimilarWordTryWord(const gchar *sTryWord, const gchar *sWord, 442 int servercollatefunc, size_t iLib, 443 glong &iIndex, glong &idx_suggest, gint &best_match); 444 /* Validate and fix collate parameters */ 445 static void ValidateCollateParams(CollationLevelType& level, CollateFunctions& func); 446 447 std::vector<Dict *> oLib; 448 int iMaxFuzzyDistance; 449 show_progress_t *show_progress; 450 bool CreateCacheFile; 451 CollationLevelType CollationLevel; 452 CollateFunctions CollateFunction; 453 static show_progress_t default_show_progress; 454 455 #ifdef SD_SERVER_CODE 456 struct DictInfoItem; 457 struct DictInfoDirItem { ~DictInfoDirItemDictInfoDirItem458 ~DictInfoDirItem() { 459 for (std::list<DictInfoItem *>::iterator i = info_item_list.begin(); i!= info_item_list.end(); ++i) { 460 delete (*i); 461 } 462 } 463 std::string info_string; 464 std::string name; 465 std::string dirname; 466 unsigned int dictcount; 467 std::list<DictInfoItem *> info_item_list; 468 }; 469 struct DictInfoDictItem { 470 std::string info_string; 471 std::string short_info_string; 472 std::string uid; 473 std::string download; 474 std::string from; 475 std::string to; 476 unsigned int level; 477 unsigned int id; 478 }; 479 struct DictInfoItem { ~DictInfoItemDictInfoItem480 ~DictInfoItem() { 481 if (isdir == 1) 482 delete dir; 483 else if (isdir == 0) 484 delete dict; 485 } 486 int isdir; 487 union { 488 DictInfoDirItem *dir; 489 DictInfoDictItem *dict; 490 std::string *linkuid; 491 }; 492 }; 493 DictInfoItem *root_info_item; 494 std::map<std::string, DictInfoDictItem *> uidmap; 495 void LoadXMLDir(const char *dir, DictInfoItem *info_item); 496 void GenLinkDict(DictInfoItem *info_item); 497 498 struct ParseUserData { 499 Libs *oLibs; 500 const char *dir; 501 DictInfoItem *info_item; 502 bool indict; 503 std::string path; 504 std::string uid; 505 std::string level; 506 std::string download; 507 std::string from; 508 std::string to; 509 bool inlinkdict; 510 std::string linkuid; 511 }; 512 static void func_parse_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error); 513 static void func_parse_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error); 514 static void func_parse_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error); 515 516 struct FromToInfo { 517 std::string uid; 518 std::string bookname; 519 }; 520 struct FromTo { 521 std::string to; 522 std::list<FromToInfo> fromto_info; 523 }; 524 std::string cache_fromto; 525 void gen_fromto_info(struct DictInfoItem *info_item, std::map<std::string, std::list<FromTo> > &map_fromto); 526 #endif 527 }; 528 529 530 #endif//!_STDDICT_HPP_ 531