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