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