OSDN Git Service

Merge branch 'master' of git://repo.or.cz/TortoiseGit
[tortoisegit/TortoiseGitJp.git] / ext / hunspell / mythes.cxx
1 #include <stdio.h>\r
2 #include <string.h>\r
3 #include <stdlib.h>\r
4 #include <errno.h>\r
5 \r
6 #include "mythes.hxx"\r
7 \r
8 \r
9 \r
10 MyThes::MyThes(const char* idxpath, const char * datpath)\r
11 {\r
12     nw = 0;\r
13     encoding = NULL;\r
14     list = NULL;\r
15     offst = NULL;\r
16 \r
17     if (thInitialize(idxpath, datpath) != 1) {\r
18         fprintf(stderr,"Error - can't open %s or %s\n",idxpath, datpath);\r
19         fflush(stderr);\r
20         if (encoding) free((void*)encoding);\r
21         if (list)  free((void*)list);\r
22         if (offst) free((void*)offst);\r
23         // did not initialize properly - throw exception?\r
24     }\r
25 }\r
26 \r
27 \r
28 MyThes::~MyThes()\r
29 {\r
30     if (thCleanup() != 1) {\r
31         /* did not cleanup properly - throw exception? */\r
32     }\r
33     if (encoding) free((void*)encoding);\r
34     encoding = NULL;\r
35     list = NULL;\r
36     offst = NULL;\r
37 }\r
38 \r
39 \r
40 int MyThes::thInitialize(const char* idxpath, const char* datpath)\r
41 {\r
42 \r
43     // open the index file\r
44     FILE * pifile = fopen(idxpath,"r");\r
45     if (!pifile) {\r
46         pifile = NULL;\r
47         return 0;\r
48     } \r
49 \r
50     // parse in encoding and index size */    \r
51     char * wrd;\r
52     wrd = (char *)calloc(1, MAX_WD_LEN);\r
53     int len = readLine(pifile,wrd,MAX_WD_LEN);\r
54     encoding = mystrdup(wrd);\r
55     len = readLine(pifile,wrd,MAX_WD_LEN);\r
56     int idxsz = atoi(wrd); \r
57     \r
58 \r
59     // now allocate list, offst for the given size\r
60     list = (char**)   calloc(idxsz,sizeof(char*));\r
61     offst = (unsigned int*) calloc(idxsz,sizeof(unsigned int));\r
62 \r
63     if ( (!(list)) || (!(offst)) ) {\r
64        fprintf(stderr,"Error - bad memory allocation\n");\r
65        fflush(stderr);\r
66        return 0;\r
67     }\r
68 \r
69     // now parse the remaining lines of the index\r
70     len = readLine(pifile,wrd,MAX_WD_LEN);\r
71     while (len > 0)\r
72     { \r
73         int np = mystr_indexOfChar(wrd,'|');\r
74         if (nw < idxsz) {\r
75            if (np >= 0) {          \r
76               *(wrd+np) = '\0';\r
77               list[nw] = (char *)calloc(1,(np+1));\r
78               memcpy((list[nw]),wrd,np);\r
79               offst[nw] = atoi(wrd+np+1);\r
80               nw++;\r
81            }\r
82         }\r
83         len = readLine(pifile,wrd,MAX_WD_LEN);\r
84     }\r
85 \r
86     free((void *)wrd);\r
87     fclose(pifile);\r
88     pifile=NULL;\r
89 \r
90     /* next open the data file */\r
91     pdfile = fopen(datpath,"r");\r
92     if (!pdfile) {\r
93         pdfile = NULL;\r
94         return 0;\r
95     } \r
96         \r
97     return 1;        \r
98 }\r
99 \r
100 \r
101 int MyThes::thCleanup()\r
102 {\r
103     /* first close the data file */\r
104     if (pdfile) {\r
105         fclose(pdfile);\r
106         pdfile=NULL;\r
107     }\r
108 \r
109     /* now free up all the allocated strings on the list */\r
110     for (int i=0; i < nw; i++) \r
111     {\r
112         if (list[i]) {\r
113             free(list[i]);\r
114             list[i] = 0;\r
115         }\r
116     }\r
117 \r
118     if (list)  free((void*)list);\r
119     if (offst) free((void*)offst);\r
120 \r
121     nw = 0;\r
122     return 1;\r
123 }\r
124 \r
125 \r
126 \r
127 // lookup text in index and count of meanings and a list of meaning entries\r
128 // with each entry having a synonym count and pointer to an \r
129 // array of char * (i.e the synonyms)\r
130 // \r
131 // note: calling routine should call CleanUpAfterLookup with the original\r
132 // meaning point and count to properly deallocate memory\r
133 \r
134 int MyThes::Lookup(const char * pText, int len, mentry** pme)\r
135\r
136 \r
137     *pme = NULL;\r
138 \r
139     // handle the case of missing file or file related errors\r
140     if (! pdfile) return 0;\r
141 \r
142     long offset = 0;\r
143 \r
144     /* copy search word and make sure null terminated */\r
145     char * wrd = (char *) calloc(1,(len+1));\r
146     memcpy(wrd,pText,len);\r
147   \r
148     /* find it in the list */\r
149     int idx = binsearch(wrd,list,nw);\r
150     free(wrd);  \r
151     if (idx < 0) return 0;\r
152 \r
153     // now seek to the offset\r
154     offset = (long) offst[idx];\r
155     int rc = fseek(pdfile,offset,SEEK_SET);\r
156     if (rc) {\r
157        return 0;\r
158     }\r
159 \r
160     // grab the count of the number of meanings\r
161     // and allocate a list of meaning entries\r
162     char * buf = NULL;\r
163     buf  = (char *) malloc( MAX_LN_LEN );\r
164     if (!buf) return 0;\r
165     readLine(pdfile, buf, (MAX_LN_LEN-1));\r
166     int np = mystr_indexOfChar(buf,'|');\r
167     if (np < 0) {\r
168          free(buf);\r
169          return 0;\r
170     }          \r
171     int nmeanings = atoi(buf+np+1);\r
172     *pme = (mentry*) malloc( nmeanings * sizeof(mentry) );\r
173     if (!(*pme)) {\r
174         free(buf);\r
175         return 0;\r
176     }\r
177 \r
178     // now read in each meaning and parse it to get defn, count and synonym lists\r
179     mentry* pm = *(pme);\r
180     char dfn[MAX_WD_LEN];\r
181 \r
182     for (int j = 0; j < nmeanings; j++) {\r
183         readLine(pdfile, buf, (MAX_LN_LEN-1));\r
184 \r
185         pm->count = 0;\r
186         pm->psyns = NULL;\r
187         pm->defn = NULL;\r
188 \r
189         // store away the part of speech for later use\r
190         char * p = buf;\r
191         char * pos = NULL;\r
192         np = mystr_indexOfChar(p,'|');\r
193         if (np >= 0) {\r
194            *(buf+np) = '\0';\r
195            pos = mystrdup(p);\r
196            p = p + np + 1;\r
197         } else {\r
198           pos = mystrdup("");\r
199         }\r
200         \r
201         // count the number of fields in the remaining line\r
202         int nf = 1;\r
203         char * d = p;\r
204         np = mystr_indexOfChar(d,'|');        \r
205         while ( np >= 0 ) {\r
206           nf++;\r
207           d = d + np + 1;\r
208           np = mystr_indexOfChar(d,'|');          \r
209         }\r
210         pm->count = nf;\r
211         pm->psyns = (char **) malloc(nf*sizeof(char*)); \r
212         \r
213         // fill in the synonym list\r
214         d = p;\r
215         for (int j = 0; j < nf; j++) {\r
216             np = mystr_indexOfChar(d,'|');\r
217             if (np > 0) {\r
218               *(d+np) = '\0';\r
219               pm->psyns[j] = mystrdup(d);\r
220               d = d + np + 1;\r
221             } else {\r
222               pm->psyns[j] = mystrdup(d);\r
223             }            \r
224         }\r
225 \r
226         // add pos to first synonym to create the definition\r
227         int k = strlen(pos);\r
228         int m = strlen(pm->psyns[0]);\r
229         if ((k+m) < (MAX_WD_LEN - 1)) {\r
230              strncpy(dfn,pos,k);\r
231              *(dfn+k) = ' ';\r
232              strncpy((dfn+k+1),(pm->psyns[0]),m+1);\r
233              pm->defn = mystrdup(dfn);\r
234         } else {\r
235              pm->defn = mystrdup(pm->psyns[0]);\r
236         }\r
237         free(pos);\r
238         pm++;\r
239 \r
240     }\r
241     free(buf);\r
242    \r
243     return nmeanings;\r
244\r
245 \r
246 \r
247 \r
248 void MyThes::CleanUpAfterLookup(mentry ** pme, int nmeanings)\r
249\r
250 \r
251     if (nmeanings == 0) return;\r
252     if ((*pme) == NULL) return;\r
253 \r
254     mentry * pm = *pme;\r
255        \r
256     for (int i = 0; i < nmeanings; i++) {\r
257        int count = pm->count;\r
258        for (int j = 0; j < count; j++) {\r
259           if (pm->psyns[j]) free(pm->psyns[j]);\r
260           pm->psyns[j] = NULL;\r
261        }\r
262        if (pm->psyns) free(pm->psyns);\r
263        pm->psyns = NULL;\r
264        if (pm->defn) free(pm->defn);\r
265        pm->defn = NULL;\r
266        pm->count = 0;\r
267        pm++;\r
268     }\r
269     pm = *pme;\r
270     free(pm);\r
271     *pme = NULL;\r
272     return;\r
273 }\r
274 \r
275 \r
276 // read a line of text from a text file stripping\r
277 // off the line terminator and replacing it with\r
278 // a null string terminator.\r
279 // returns:  -1 on error or the number of characters in\r
280 //             in the returning string\r
281 \r
282 // A maximum of nc characters will be returned\r
283 \r
284 int MyThes::readLine(FILE * pf, char * buf, int nc)\r
285 {\r
286     \r
287   if (fgets(buf,nc,pf)) {\r
288     mychomp(buf);\r
289     return strlen(buf);\r
290   }\r
291   return -1;\r
292 }\r
293 \r
294 \r
295  \r
296 //  performs a binary search on null terminated character\r
297 //  strings\r
298 //\r
299 //  returns: -1 on not found\r
300 //           index of wrd in the list[]\r
301 \r
302 int MyThes::binsearch(char * sw, char* list[], int nlst) \r
303 {\r
304     int lp, up, mp, j, indx;\r
305     lp = 0;\r
306     up = nlst-1;\r
307     indx = -1;\r
308     if (strcmp(sw,list[lp]) < 0) return -1;\r
309     if (strcmp(sw,list[up]) > 0) return -1;\r
310     while (indx < 0 ) {\r
311         mp = (int)((lp+up) >> 1);\r
312         j = strcmp(sw,list[mp]);\r
313         if ( j > 0) {\r
314             lp = mp + 1;\r
315         } else if (j < 0 ) {\r
316             up = mp - 1;\r
317         } else {\r
318             indx = mp;\r
319         }\r
320         if (lp > up) return -1;      \r
321     }\r
322     return indx;\r
323 }\r
324 \r
325 char * MyThes::get_th_encoding()\r
326 {\r
327   if (encoding) return encoding;\r
328   return NULL;\r
329 }\r
330 \r
331 \r
332 // string duplication routine\r
333 char * MyThes::mystrdup(const char * p)\r
334 {\r
335   int sl = strlen(p) + 1;\r
336   char * d = (char *)malloc(sl);\r
337   if (d) {\r
338     memcpy(d,p,sl);\r
339     return d;\r
340   }\r
341   return NULL;\r
342 }\r
343 \r
344 // remove cross-platform text line end characters\r
345 void MyThes::mychomp(char * s)\r
346 {\r
347   int k = strlen(s);\r
348   if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0';\r
349   if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0';\r
350 }\r
351 \r
352 \r
353 // return index of char in string\r
354 int MyThes::mystr_indexOfChar(const char * d, int c)\r
355 {\r
356   char * p = strchr((char *)d,c);\r
357   if (p) return (int)(p-d);\r
358   return -1;\r
359 }\r
360 \r