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