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