aa0b276fe461a4740eadebef286992425d1ea217
[mstardict] / src / lib / stddict.hpp
1 #ifndef _STDDICT_HPP_
2 #define _STDDICT_HPP_
3
4 #include "stardict_libconfig.h"
5
6 #include <glib.h>
7 #include <string>
8 #include <vector>
9 #include <list>
10 #include <map>
11
12 #include "data.hpp"
13 #include "collation.h"
14 #include "dictmask.h"
15 #include "storage.h"
16
17 const int MAX_FUZZY_DISTANCE= 3; // at most MAX_FUZZY_DISTANCE-1 differences allowed when find similar words
18 const int MAX_MATCH_ITEM_PER_LIB=100;
19
20 extern gint stardict_casecmp(const gchar *s1, const gchar *s2, bool isClt, CollateFunctions func);
21 extern bool bIsPureEnglish(const gchar *str);
22 extern gint stardict_server_collate(const gchar *str1, const gchar *str2, int EnableCollationLevel, CollateFunctions func, int servercollatefunc);
23
24 class show_progress_t {
25 public:
26         virtual ~show_progress_t() {}
27         virtual void notify_about_start(const std::string& title) {}
28         virtual void notify_about_work() {}
29 };
30
31 enum CacheFileType {
32         CacheFileType_oft,
33         CacheFileType_clt,
34         CacheFileType_server_clt,
35 };
36
37 class cache_file {
38 public:
39         guint32 *wordoffset;
40
41         cache_file(CacheFileType _cachefiletype);
42         ~cache_file();
43         bool load_cache(const std::string& url, const std::string& saveurl, CollateFunctions cltfunc, glong filedatasize);
44         bool save_cache(const std::string& url, CollateFunctions cltfunc, gulong npages);
45 private:
46         CacheFileType cachefiletype;
47         MapFile *mf;
48         bool get_cache_filename(const std::string& url, std::string &cachefilename, bool create, CollateFunctions cltfunc);
49         MapFile* get_cache_loadfile(const gchar *filename, const std::string &url, const std::string &saveurl, CollateFunctions cltfunc, glong filedatasize, int next);
50         FILE* get_cache_savefile(const gchar *filename, const std::string &url, int next, std::string &cfilename, CollateFunctions cltfunc);
51 };
52
53 class idxsyn_file;
54 class collation_file : public cache_file {
55 public:
56         CollateFunctions CollateFunction;
57
58         collation_file(idxsyn_file *_idx_file, CacheFileType _cachefiletype);
59         bool lookup(const char *str, glong &idx, glong &idx_suggest);
60         const gchar *GetWord(glong idx);
61         glong GetOrigIndex(glong cltidx);
62 private:
63         idxsyn_file *idx_file;
64 };
65
66 class idxsyn_file {
67 public:
68         glong wordcount;
69         collation_file *clt_file;
70         collation_file *clt_files[COLLATE_FUNC_NUMS];
71         std::string url;
72         std::string saveurl;
73
74         idxsyn_file();
75         const gchar *getWord(glong idx, int EnableCollationLevel, int servercollatefunc);
76         bool Lookup(const char *str, glong &idx, glong &idx_suggest, int EnableCollationLevel, int servercollatefunc);
77         virtual const gchar *get_key(glong idx) = 0;
78         virtual bool lookup(const char *str, glong &idx, glong &idx_suggest) = 0;
79         virtual ~idxsyn_file() {}
80         void collate_sort(const std::string& url, const std::string& saveurl,
81                           CollateFunctions collf, show_progress_t *sp);
82         void collate_save_info(const std::string& _url, const std::string& _saveurl);
83         void collate_load(CollateFunctions collf);
84 };
85
86 class index_file : public idxsyn_file {
87 public:
88         guint32 wordentry_offset;
89         guint32 wordentry_size;
90
91         virtual bool load(const std::string& url, gulong wc, gulong fsize,
92                           bool CreateCacheFile, int EnableCollationLevel,
93                           CollateFunctions _CollateFunction, show_progress_t *sp) = 0;
94         virtual void get_data(glong idx) = 0;
95         virtual  const gchar *get_key_and_data(glong idx) = 0;
96 private:
97         virtual bool lookup(const char *str, glong &idx, glong &idx_suggest) = 0;
98 };
99
100 class synonym_file : public idxsyn_file {
101 public:
102         guint32 wordentry_index;
103
104         synonym_file();
105         ~synonym_file();
106         bool load(const std::string& url, gulong wc, bool CreateCacheFile,
107                   int EnableCollationLevel, CollateFunctions _CollateFunction,
108                   show_progress_t *sp);
109 private:
110         const gchar *get_key(glong idx);
111         bool lookup(const char *str, glong &idx, glong &idx_suggest);
112
113         static const gint ENTR_PER_PAGE=32;
114         gulong npages;
115
116         cache_file oft_file;
117         FILE *synfile;
118
119         gchar wordentry_buf[256+sizeof(guint32)];
120         struct index_entry {
121                 glong idx;
122                 std::string keystr;
123                 void assign(glong i, const std::string& str) {
124                         idx=i;
125                         keystr.assign(str);
126                 }
127         };
128         index_entry first, last, middle, real_last;
129
130         struct page_entry {
131                 gchar *keystr;
132                 guint32 index;
133         };
134         std::vector<gchar> page_data;
135         struct page_t {
136                 glong idx;
137                 page_entry entries[ENTR_PER_PAGE];
138
139                 page_t(): idx(-1) {}
140                 void fill(gchar *data, gint nent, glong idx_);
141         } page;
142         gulong load_page(glong page_idx);
143         const gchar *read_first_on_page_key(glong page_idx);
144         const gchar *get_first_on_page_key(glong page_idx);
145 };
146
147 class Dict : public DictBase {
148 private:
149         std::string ifo_file_name;
150         std::string bookname;
151         std::string dicttype;
152
153         bool load_ifofile(const std::string& ifofilename, gulong &idxfilesize, glong &wordcount, glong &synwordcount);
154 public:
155         std::auto_ptr<index_file> idx_file;
156         std::auto_ptr<synonym_file> syn_file;
157         ResourceStorage *storage;
158
159         Dict();
160         ~Dict();
161         bool load(const std::string&, bool CreateCacheFile, int EnableCollationLevel, CollateFunctions,
162                   show_progress_t *);
163
164         glong narticles() { return idx_file->wordcount; }
165         glong nsynarticles();
166         const std::string& dict_name() { return bookname; }
167         const std::string& dict_type() { return dicttype; }
168         const std::string& ifofilename() { return ifo_file_name; }
169
170         gchar *get_data(glong index)
171         {
172                 idx_file->get_data(index);
173                 return DictBase::GetWordData(idx_file->wordentry_offset, idx_file->wordentry_size);
174         }
175         void get_key_and_data(glong index, const gchar **key, guint32 *offset, guint32 *size)
176         {
177                 *key = idx_file->get_key_and_data(index);
178                 *offset = idx_file->wordentry_offset;
179                 *size = idx_file->wordentry_size;
180         }
181         bool Lookup(const char *str, glong &idx, glong &idx_suggest, int EnableCollationLevel, int servercollatefunc)
182         {
183                 return idx_file->Lookup(str, idx, idx_suggest, EnableCollationLevel, servercollatefunc);
184         }
185         bool LookupSynonym(const char *str, glong &synidx, glong &synidx_suggest, int EnableCollationLevel, int servercollatefunc);
186         bool LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen);
187         bool LookupWithRuleSynonym(GPatternSpec *pspec, glong *aIndex, int iBuffLen);
188         bool LookupWithRegex(GRegex *regex, glong *aIndex, int iBuffLen);
189         bool LookupWithRegexSynonym(GRegex *regex, glong *aIndex, int iBuffLen);
190         gint GetOrigWordCount(glong& iWordIndex, bool isidx);
191         bool GetWordPrev(glong iWordIndex, glong &pidx, bool isidx, int EnableCollationLevel, int servercollatefunc);
192         void GetWordNext(glong &iWordIndex, bool isidx, int EnableCollationLevel, int servercollatefunc);
193 };
194
195 struct CurrentIndex {
196         glong idx;
197         glong idx_suggest;
198         glong synidx;
199         glong synidx_suggest;
200 };
201
202 class Libs {
203 public:
204         static show_progress_t default_show_progress;
205         int EnableCollationLevel;
206         CollateFunctions CollateFunction;
207
208         Libs(show_progress_t *sp, bool create, int enablelevel, int function);
209         ~Libs();
210         void set_show_progress(show_progress_t *sp) {
211                 if (sp)
212                         show_progress = sp;
213                 else
214                         show_progress = &default_show_progress;
215         }
216         bool load_dict(const std::string& url, show_progress_t *sp);
217 #ifdef SD_SERVER_CODE
218         void LoadFromXML();
219         void SetServerDictMask(std::vector<InstantDictIndex> &dictmask, const char *dicts, int max, int level);
220         void LoadCollateFile(std::vector<InstantDictIndex> &dictmask, CollateFunctions cltfuc);
221         const std::string *get_dir_info(const char *path);
222         const std::string *get_dict_info(const char *uid, bool is_short);
223         const std::string &get_fromto_info();
224         std::string get_dicts_list(const char *dicts, int max_dict_count, int userLevel);
225         int get_dict_level(const char *uid);
226 #endif
227 #ifdef SD_CLIENT_CODE
228         bool find_lib_by_filename(const char *filename, size_t &iLib);
229         void load(std::list<std::string> &load_list);
230         void reload(std::list<std::string> &load_list, int is_coll_enb, int collf);
231 #endif
232
233         glong narticles(size_t idict) { return oLib[idict]->narticles(); }
234         glong nsynarticles(size_t idict) { return oLib[idict]->nsynarticles(); }
235         const std::string& dict_name(size_t idict) { return oLib[idict]->dict_name(); }
236         const std::string& dict_type(size_t idict) { return oLib[idict]->dict_type(); }
237         bool has_dict() { return !oLib.empty(); }
238         gint ndicts() { return oLib.size(); }
239
240         const gchar * poGetWord(glong iIndex,size_t iLib, int servercollatefunc) {
241                 return oLib[iLib]->idx_file->getWord(iIndex, EnableCollationLevel, servercollatefunc);
242         }
243         const gchar * poGetOrigWord(glong iIndex,size_t iLib) {
244                 return oLib[iLib]->idx_file->getWord(iIndex, 0, 0);
245         }
246         const gchar * poGetSynonymWord(glong iSynonymIndex,size_t iLib, int servercollatefunc) {
247                 return oLib[iLib]->syn_file->getWord(iSynonymIndex, EnableCollationLevel, servercollatefunc);
248         }
249         const gchar * poGetOrigSynonymWord(glong iSynonymIndex,size_t iLib) {
250                 return oLib[iLib]->syn_file->getWord(iSynonymIndex, 0, 0);
251         }
252         glong poGetOrigSynonymWordIdx(glong iSynonymIndex, size_t iLib) {
253                 oLib[iLib]->syn_file->getWord(iSynonymIndex, 0, 0);
254                 return oLib[iLib]->syn_file->wordentry_index;
255         }
256         glong CltIndexToOrig(glong cltidx, size_t iLib, int servercollatefunc);
257         glong CltSynIndexToOrig(glong cltidx, size_t iLib, int servercollatefunc);
258         gchar * poGetOrigWordData(glong iIndex,size_t iLib) {
259                 if (iIndex==INVALID_INDEX)
260                         return NULL;
261                 return oLib[iLib]->get_data(iIndex);
262         }
263         const gchar *GetSuggestWord(const gchar *sWord, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc);
264         const gchar *poGetCurrentWord(CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc);
265         const gchar *poGetNextWord(const gchar *word, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc);
266         const gchar *poGetPreWord(const gchar *word, CurrentIndex *iCurrent, std::vector<InstantDictIndex> &dictmask, int servercollatefunc);
267         bool LookupWord(const gchar* sWord, glong& iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc) {
268                 return oLib[iLib]->Lookup(sWord, iWordIndex, idx_suggest, EnableCollationLevel, servercollatefunc);
269         }
270         bool LookupSynonymWord(const gchar* sWord, glong& iSynonymIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc) {
271                 return oLib[iLib]->LookupSynonym(sWord, iSynonymIndex, synidx_suggest, EnableCollationLevel, servercollatefunc);
272         }
273         bool LookupSimilarWord(const gchar* sWord, glong &iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc);
274         bool LookupSynonymSimilarWord(const gchar* sWord, glong &iSynonymWordIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc);
275         bool SimpleLookupWord(const gchar* sWord, glong &iWordIndex, glong &idx_suggest, size_t iLib, int servercollatefunc);
276         bool SimpleLookupSynonymWord(const gchar* sWord, glong &iWordIndex, glong &synidx_suggest, size_t iLib, int servercollatefunc);
277         gint GetOrigWordCount(glong& iWordIndex, size_t iLib, bool isidx) {
278                 return oLib[iLib]->GetOrigWordCount(iWordIndex, isidx);
279         }
280         bool GetWordPrev(glong iWordIndex, glong &pidx, size_t iLib, bool isidx, int servercollatefunc) {
281                 return oLib[iLib]->GetWordPrev(iWordIndex, pidx, isidx, EnableCollationLevel, servercollatefunc);
282         }
283         void GetWordNext(glong &iWordIndex, size_t iLib, bool isidx, int servercollatefunc) {
284                 oLib[iLib]->GetWordNext(iWordIndex, isidx, EnableCollationLevel, servercollatefunc);
285         }
286
287         bool LookupWithFuzzy(const gchar *sWord, gchar *reslist[], gint reslist_size, std::vector<InstantDictIndex> &dictmask);
288         gint LookupWithRule(const gchar *sWord, gchar *reslist[], std::vector<InstantDictIndex> &dictmask);
289         gint LookupWithRegex(const gchar *sWord, gchar *reslist[], std::vector<InstantDictIndex> &dictmask);
290
291         typedef void (*updateSearchDialog_func)(gpointer data, gdouble fraction);
292         bool LookupData(const gchar *sWord, std::vector<gchar *> *reslist, updateSearchDialog_func func, gpointer data, bool *cancel, std::vector<InstantDictIndex> &dictmask);
293         int GetStorageType(size_t iLib);
294         const char *GetStorageFilePath(size_t iLib, const char *key);
295         const char *GetStorageFileContent(size_t iLib, const char *key);
296 private:
297         std::vector<Dict *> oLib; // word Libs.
298         int iMaxFuzzyDistance;
299         show_progress_t *show_progress;
300         bool CreateCacheFile;
301
302 #ifdef SD_SERVER_CODE
303         struct DictInfoItem;
304         struct DictInfoDirItem {
305                 ~DictInfoDirItem() {
306                         for (std::list<DictInfoItem *>::iterator i = info_item_list.begin(); i!= info_item_list.end(); ++i) {
307                                 delete (*i);
308                         }
309                 }
310                 std::string info_string;
311                 std::string name;
312                 std::string dirname;
313                 unsigned int dictcount;
314                 std::list<DictInfoItem *> info_item_list;
315         };
316         struct DictInfoDictItem {
317                 std::string info_string;
318                 std::string short_info_string;
319                 std::string uid;
320                 std::string download;
321                 std::string from;
322                 std::string to;
323                 unsigned int level;
324                 unsigned int id;
325         };
326         struct DictInfoItem {
327                 ~DictInfoItem() {
328                         if (isdir == 1)
329                                 delete dir;
330                         else if (isdir == 0)
331                                 delete dict;
332                 }
333                 int isdir;
334                 union {
335                         DictInfoDirItem *dir;
336                         DictInfoDictItem *dict;
337                         std::string *linkuid;
338                 };
339         };
340         DictInfoItem *root_info_item;
341         std::map<std::string, DictInfoDictItem *> uidmap;
342         void LoadXMLDir(const char *dir, DictInfoItem *info_item);
343         void GenLinkDict(DictInfoItem *info_item);
344
345         struct ParseUserData {
346                 Libs *oLibs;
347                 const char *dir;
348                 DictInfoItem *info_item;
349                 bool indict;
350                 std::string path;
351                 std::string uid;
352                 std::string level;
353                 std::string download;
354                 std::string from;
355                 std::string to;
356                 bool inlinkdict;
357                 std::string linkuid;
358         };
359         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);
360         static void func_parse_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error);
361         static void func_parse_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error);
362
363         struct FromToInfo {
364                 std::string uid;
365                 std::string bookname;
366         };
367         struct FromTo {
368                 std::string to;
369                 std::list<FromToInfo> fromto_info;
370         };
371         std::string cache_fromto;
372         void gen_fromto_info(struct DictInfoItem *info_item, std::map<std::string, std::list<FromTo> > &map_fromto);
373 #endif
374
375         friend class DictLoader;
376         friend class DictReLoader;
377 };
378
379
380 #endif//!_STDDICT_HPP_