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