Optimized resultSetInsert{Rank,Sort}.
[idzebra-moved-to-github.git] / dict / dicttest.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: dicttest.c,v $
7  * Revision 1.23  2000-07-07 12:49:20  adam
8  * Optimized resultSetInsert{Rank,Sort}.
9  *
10  * Revision 1.22  1999/02/02 14:50:19  adam
11  * Updated WIN32 code specific sections. Changed header.
12  *
13  * Revision 1.21  1996/10/29 14:00:03  adam
14  * Page size given by DICT_DEFAULT_PAGESIZE in dict.h.
15  *
16  * Revision 1.20  1996/03/20 09:35:16  adam
17  * Function dict_lookup_grep got extra parameter, init_pos, which marks
18  * from which position in pattern approximate pattern matching should occur.
19  *
20  * Revision 1.19  1996/02/02  13:43:50  adam
21  * The public functions simply use char instead of Dict_char to represent
22  * search strings. Dict_char is used internally only.
23  *
24  * Revision 1.18  1996/02/01  20:39:52  adam
25  * Bug fix: insert didn't work on 8-bit characters due to unsigned char
26  * compares in dict_strcmp (strcmp) and signed Dict_char. Dict_char is
27  * unsigned now.
28  *
29  * Revision 1.17  1995/12/06  17:48:30  adam
30  * Bug fix: delete didn't work.
31  *
32  * Revision 1.16  1995/10/09  16:18:31  adam
33  * Function dict_lookup_grep got extra client data parameter.
34  *
35  * Revision 1.15  1995/09/04  12:33:31  adam
36  * Various cleanup. YAZ util used instead.
37  *
38  * Revision 1.14  1994/10/04  17:46:55  adam
39  * Function options now returns arg with error option.
40  *
41  * Revision 1.13  1994/10/04  12:08:05  adam
42  * Some bug fixes and some optimizations.
43  *
44  * Revision 1.12  1994/10/03  17:23:03  adam
45  * First version of dictionary lookup with regular expressions and errors.
46  *
47  * Revision 1.11  1994/09/28  13:07:09  adam
48  * Use log_mask_str now.
49  *
50  * Revision 1.10  1994/09/26  10:17:24  adam
51  * Minor changes.
52  *
53  * Revision 1.9  1994/09/22  14:43:56  adam
54  * First functional version of lookup with error correction. A 'range'
55  * specified the maximum number of insertions+deletions+substitutions.
56  *
57  * Revision 1.8  1994/09/22  10:43:44  adam
58  * Two versions of depend. Type 1 is the tail-type compatible with
59  * all make programs. Type 2 is the GNU make with include facility.
60  * Type 2 is default. depend rule chooses current rule.
61  *
62  * Revision 1.7  1994/09/19  16:34:26  adam
63  * Depend rule change. Minor changes in dicttest.c
64  *
65  * Revision 1.6  1994/09/16  15:39:12  adam
66  * Initial code of lookup - not tested yet.
67  *
68  * Revision 1.5  1994/09/06  13:05:14  adam
69  * Further development of insertion. Some special cases are
70  * not properly handled yet! assert(0) are put here. The
71  * binary search in each page definitely reduce usr CPU.
72  *
73  * Revision 1.4  1994/09/01  17:49:37  adam
74  * Removed stupid line. Work on insertion in dictionary. Not finished yet.
75  *
76  * Revision 1.3  1994/09/01  17:44:06  adam
77  * depend include change.
78  *
79  * Revision 1.2  1994/08/18  12:40:54  adam
80  * Some development of dictionary. Not finished at all!
81  *
82  * Revision 1.1  1994/08/16  16:26:47  adam
83  * Added dict.
84  *
85  */
86
87 #include <stdlib.h>
88 #include <string.h>
89 #include <stdio.h>
90 #include <ctype.h>
91
92 #include <dict.h>
93 #include <zebrautl.h>
94
95 char *prog;
96 static Dict dict;
97
98 static int look_hits;
99
100 static int grep_handle (char *name, const char *info, void *client)
101 {
102     look_hits++;
103     printf ("%s\n", name);
104     return 0;
105 }
106
107 int main (int argc, char **argv)
108 {
109     Res my_resource = 0;
110     BFiles bfs;
111     const char *name = NULL;
112     const char *inputfile = NULL;
113     const char *config = NULL;
114     int do_delete = 0;
115     int range = -1;
116     int srange = 0;
117     int rw = 0;
118     int infosize = 4;
119     int cache = 10;
120     int ret;
121     int unique = 0;
122     char *grep_pattern = NULL;
123     char *arg;
124     int no_of_iterations = 0;
125     int no_of_new = 0, no_of_same = 0, no_of_change = 0;
126     int no_of_hits = 0, no_of_misses = 0, no_not_found = 0, no_of_deleted = 0;
127     int max_pos;
128     
129     prog = argv[0];
130     if (argc < 2)
131     {
132         fprintf (stderr, "usage:\n "
133                  " %s [-d] [-r n] [-p n] [-u] [-g pat] [-s n] [-v n] [-i f]"
134                  " [-w] [-c n] config file\n\n",
135                  prog);
136         fprintf (stderr, "  -d      delete instead of insert\n");
137         fprintf (stderr, "  -r n    set regular match range\n");
138         fprintf (stderr, "  -p n    set regular match start range\n");
139         fprintf (stderr, "  -u      report if keys change during insert\n");
140         fprintf (stderr, "  -g p    try pattern n (see -r)\n");
141         fprintf (stderr, "  -s n    set info size to n (instead of 4)\n");
142         fprintf (stderr, "  -v n    set logging level\n");
143         fprintf (stderr, "  -i f    read file with words\n");
144         fprintf (stderr, "  -w      insert/delete instead of lookup\n");
145         fprintf (stderr, "  -c n    cache size (number of pages)\n");
146         exit (1);
147     }
148     while ((ret = options ("dr:p:ug:s:v:i:wc:", argv, argc, &arg)) != -2)
149     {
150         if (ret == 0)
151         {
152             if (!config)
153                 config = arg;
154             else if (!name)
155                 name = arg;
156             else
157             {
158                 logf (LOG_FATAL, "too many files specified\n");
159                 exit (1);
160             }
161         }
162         else if (ret == 'd')
163             do_delete = 1;
164         else if (ret == 'g')
165         {
166             grep_pattern = arg;
167         }
168         else if (ret == 'r')
169         {
170             range = atoi (arg);
171         }
172         else if (ret == 'p')
173         {
174             srange = atoi (arg);
175         }
176         else if (ret == 'u')
177         {
178             unique = 1;
179         }
180         else if (ret == 'c')
181         {
182             cache = atoi(arg);
183             if (cache<2)
184                 cache = 2;
185         }
186         else if (ret == 'w')
187             rw = 1;
188         else if (ret == 'i')
189             inputfile = arg;
190         else if (ret == 's')
191         {
192             infosize = atoi(arg);
193         }
194         else if (ret == 'v')
195         {
196             log_init (log_mask_str(arg), prog, NULL);
197         }
198         else
199         {
200             logf (LOG_FATAL, "Unknown option '-%s'", arg);
201             exit (1);
202         }
203     }
204     if (!config || !name)
205     {
206         logf (LOG_FATAL, "no config and/or dictionary specified");
207         exit (1);
208     }
209     my_resource = res_open (config);
210     if (!my_resource)
211     {
212         logf (LOG_FATAL, "cannot open resource `%s'", config);
213         exit (1);
214     }
215     bfs = bfs_create (res_get(my_resource, "register"));
216     if (!bfs)
217     {
218         logf (LOG_FATAL, "bfs_create fail");
219         exit (1);
220     }
221     dict = dict_open (bfs, name, cache, rw, 0);
222     if (!dict)
223     {
224         logf (LOG_FATAL, "dict_open fail of `%s'", name);
225         exit (1);
226     }
227     if (inputfile)
228     {
229         FILE *ipf;
230         char ipf_buf[1024];
231         int line = 1;
232         char infobytes[120];
233         memset (infobytes, 0, 120);
234
235         if (!(ipf = fopen(inputfile, "r")))
236         {
237             logf (LOG_FATAL|LOG_ERRNO, "cannot open %s", inputfile);
238             exit (1);
239         }
240         
241         while (fgets (ipf_buf, 1023, ipf))
242         {
243             char *ipf_ptr = ipf_buf;
244             sprintf (infobytes, "%d", line);
245             for (;*ipf_ptr && *ipf_ptr != '\n';ipf_ptr++)
246             {
247                 if (isalpha(*ipf_ptr) || *ipf_ptr == '_')
248                 {
249                     int i = 1;
250                     while (ipf_ptr[i] && (isalnum(ipf_ptr[i]) ||
251                                           ipf_ptr[i] == '_'))
252                         i++;
253                     if (ipf_ptr[i])
254                         ipf_ptr[i++] = '\0';
255                     if (rw)
256                     {
257                         if (do_delete)
258                             switch (dict_delete (dict, ipf_ptr))
259                             {
260                             case 0:
261                                 no_not_found++;
262                                 break;
263                             case 1:
264                                 no_of_deleted++;
265                             }
266                         else
267                             switch(dict_insert (dict, ipf_ptr,
268                                                 infosize, infobytes))
269                             {
270                             case 0:
271                                 no_of_new++;
272                                 break;
273                             case 1:
274                                 no_of_change++;
275                                 if (unique)
276                                     logf (LOG_LOG, "%s change\n", ipf_ptr);
277                                 break;
278                             case 2:
279                                 if (unique)
280                                     logf (LOG_LOG, "%s duplicate\n", ipf_ptr);
281                                 no_of_same++;
282                                 break;
283                             }
284                     }
285                     else if(range < 0)
286                     {
287                         char *cp;
288
289                         cp = dict_lookup (dict, ipf_ptr);
290                         if (cp && *cp)
291                             no_of_hits++;
292                         else
293                             no_of_misses++;
294                     }
295                     else
296                     {
297                         look_hits = 0;
298                         dict_lookup_grep (dict, ipf_ptr, range, NULL,
299                                           &max_pos, srange, grep_handle);
300                         if (look_hits)
301                             no_of_hits++;
302                         else
303                             no_of_misses++;
304                     }
305                     ++no_of_iterations;
306                     if ((no_of_iterations % 10000) == 0)
307                     {
308                         printf ("."); fflush(stdout);
309                     }
310                     ipf_ptr += (i-1);
311                 }
312             }
313             ++line;
314         }
315         fclose (ipf);
316     }
317     if (grep_pattern)
318     {
319         if (range < 0)
320             range = 0;
321         logf (LOG_LOG, "Grepping '%s'", grep_pattern);
322         dict_lookup_grep (dict, grep_pattern, range, NULL, &max_pos,
323                           srange, grep_handle);
324     }
325     if (rw)
326     {
327         logf (LOG_LOG, "Iterations.... %d", no_of_iterations);            
328         if (do_delete)
329         {
330             logf (LOG_LOG, "No of deleted. %d", no_of_deleted);
331             logf (LOG_LOG, "No not found.. %d", no_not_found);
332         }
333         else
334         {
335             logf (LOG_LOG, "No of new..... %d", no_of_new);
336             logf (LOG_LOG, "No of change.. %d", no_of_change);
337         }
338     }
339     else
340     {
341         logf (LOG_LOG, "Lookups....... %d", no_of_iterations);
342         logf (LOG_LOG, "No of hits.... %d", no_of_hits);
343         logf (LOG_LOG, "No of misses.. %d", no_of_misses);
344     }
345     dict_close (dict);
346     bfs_destroy (bfs);
347     res_close (my_resource);
348     return 0;
349 }