fa170e5ee4238fd8d89f9ce8e27eda48e64b9d66
[idzebra-moved-to-github.git] / util / zebramap.c
1 /*
2  * Copyright (C) 1994-1998, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zebramap.c,v $
7  * Revision 1.6  1998-01-29 13:36:01  adam
8  * Structure word-list, free-form-text and document-text all
9  * trigger ranked search.
10  *
11  * Revision 1.5  1997/11/19 10:22:14  adam
12  * Bug fix (introduced by previous commit).
13  *
14  * Revision 1.4  1997/11/18 10:05:08  adam
15  * Changed character map facility so that admin can specify character
16  * mapping files for each register type, w, p, etc.
17  *
18  * Revision 1.3  1997/11/17 15:35:26  adam
19  * Bug fix. Relation=relevance wasn't observed.
20  *
21  * Revision 1.2  1997/10/31 12:39:30  adam
22  * Changed log message.
23  *
24  * Revision 1.1  1997/10/27 14:33:06  adam
25  * Moved towards generic character mapping depending on "structure"
26  * field in abstract syntax file. Fixed a few memory leaks. Fixed
27  * bug with negative integers when doing searches with relational
28  * operators.
29  *
30  */
31
32 #include <assert.h>
33 #include <ctype.h>
34
35 #include <yaz-util.h>
36 #include <charmap.h>
37 #include <zebramap.h>
38
39 struct zebra_map {
40     int reg_type;
41     int completeness;
42     chrmaptab maptab;
43     const char *maptab_name;
44     struct zebra_map *next;
45 };
46
47 struct zebra_maps {
48     char *tabpath;
49     NMEM nmem;
50     struct zebra_map *map_list;
51     char temp_map_str[2];
52     const char *temp_map_ptr[2];
53 };
54
55 void zebra_maps_close (ZebraMaps zms)
56 {
57     struct zebra_map *zm = zms->map_list;
58     while (zm)
59     {
60         if (zm->maptab)
61             chrmaptab_destroy (zm->maptab);
62         zm = zm->next;
63     }
64     nmem_destroy (zms->nmem);
65     xfree (zms);
66 }
67
68 static void zebra_map_read (ZebraMaps zms, const char *name)
69 {
70     FILE *f;
71     char line[512];
72     char *argv[10];
73     int argc;
74     struct zebra_map **zm = 0;
75
76     if (!(f = yaz_path_fopen(zms->tabpath, name, "r")))
77     {
78         logf(LOG_WARN|LOG_ERRNO, "%s", name);
79         return ;
80     }
81     while ((argc = readconf_line(f, line, 512, argv, 10)))
82     {
83         if (!strcmp (argv[0], "index") && argc == 2)
84         {
85             if (!zm)
86                 zm = &zms->map_list;
87             else
88                 zm = &(*zm)->next;
89             *zm = nmem_malloc (zms->nmem, sizeof(**zm));
90             (*zm)->reg_type = argv[1][0];
91             (*zm)->maptab_name = NULL;
92             (*zm)->maptab = NULL;
93             (*zm)->completeness = 0;
94         }
95         else if (zm && !strcmp (argv[0], "charmap") && argc == 2)
96         {
97             (*zm)->maptab_name = nmem_strdup (zms->nmem, argv[1]);
98         }
99         else if (zm && !strcmp (argv[0], "completeness") && argc == 2)
100         {
101             (*zm)->completeness = atoi (argv[1]);
102         }
103     }
104     if (zm)
105         (*zm)->next = NULL;
106     fclose (f);
107 }
108 static void zms_map_handle (void *p, const char *name, const char *value)
109 {
110     ZebraMaps zms = p;
111     
112     zebra_map_read (zms, value);
113 }
114
115 ZebraMaps zebra_maps_open (const char *tabpath, Res res)
116 {
117     ZebraMaps zms = xmalloc (sizeof(*zms));
118
119     zms->nmem = nmem_create ();
120     zms->tabpath = nmem_strdup (zms->nmem, tabpath);
121     zms->map_list = NULL;
122
123     zms->temp_map_str[0] = '\0';
124     zms->temp_map_str[1] = '\0';
125
126     zms->temp_map_ptr[0] = zms->temp_map_str;
127     zms->temp_map_ptr[1] = NULL;
128     
129     if (!res_trav (res, "index", zms, zms_map_handle))
130         zebra_map_read (zms, "default.idx");
131     return zms;
132 }
133
134 chrmaptab zebra_map_get (ZebraMaps zms, int reg_type)
135 {
136     struct zebra_map *zm;
137     
138     for (zm = zms->map_list; zm; zm = zm->next)
139         if (reg_type == zm->reg_type)
140             break;
141     if (!zm)
142     {
143         logf (LOG_WARN, "Unknown register type: %c", reg_type);
144         return NULL;
145     }
146     if (!zm->maptab)
147     {
148         if (!strcmp (zm->maptab_name, "@"))
149             return NULL;
150         if (!(zm->maptab = chrmaptab_create (zms->tabpath,
151                                              zm->maptab_name, 0)))
152             logf(LOG_WARN, "Failed to read character table %s",
153                  zm->maptab_name);
154         else
155             logf(LOG_DEBUG, "Read character table %s", zm->maptab_name);
156     }
157     return zm->maptab;
158 }
159
160 const char **zebra_maps_input (ZebraMaps zms, int reg_type,
161                                const char **from, int len)
162 {
163     chrmaptab maptab;
164
165     maptab = zebra_map_get (zms, reg_type);
166     if (maptab)
167         return chr_map_input(maptab, from, len);
168     
169     zms->temp_map_str[0] = **from;
170
171     (*from)++;
172     return zms->temp_map_ptr;
173 }
174
175 const char *zebra_maps_output(ZebraMaps zms, int reg_type, const char **from)
176 {
177     chrmaptab maptab;
178     unsigned char i = (unsigned char) **from;
179     static char buf[2] = {0,0};
180
181     maptab = zebra_map_get (zms, reg_type);
182     if (maptab)
183         return chr_map_output (maptab, from, 1);
184     (*from)++;
185     buf[0] = i;
186     return buf;
187 }
188
189
190 /* ------------------------------------ */
191
192 typedef struct {
193     int type;
194     int major;
195     int minor;
196     Z_AttributesPlusTerm *zapt;
197 } AttrType;
198
199 static int attr_find (AttrType *src, oid_value *attributeSetP)
200 {
201     while (src->major < src->zapt->num_attributes)
202     {
203         Z_AttributeElement *element;
204
205         element = src->zapt->attributeList[src->major];
206         if (src->type == *element->attributeType)
207         {
208             switch (element->which) 
209             {
210             case Z_AttributeValue_numeric:
211                 ++(src->major);
212                 if (element->attributeSet && attributeSetP)
213                 {
214                     oident *attrset;
215
216                     attrset = oid_getentbyoid (element->attributeSet);
217                     *attributeSetP = attrset->value;
218                 }
219                 return *element->value.numeric;
220                 break;
221             case Z_AttributeValue_complex:
222                 if (src->minor >= element->value.complex->num_list ||
223                     element->value.complex->list[src->minor]->which !=  
224                     Z_StringOrNumeric_numeric)
225                     break;
226                 ++(src->minor);
227                 if (element->attributeSet && attributeSetP)
228                 {
229                     oident *attrset;
230
231                     attrset = oid_getentbyoid (element->attributeSet);
232                     *attributeSetP = attrset->value;
233                 }
234                 return *element->value.complex->list[src->minor-1]->u.numeric;
235             default:
236                 assert (0);
237             }
238         }
239         ++(src->major);
240     }
241     return -1;
242 }
243
244 static void attr_init (AttrType *src, Z_AttributesPlusTerm *zapt,
245                        int type)
246 {
247     src->zapt = zapt;
248     src->type = type;
249     src->major = 0;
250     src->minor = 0;
251 }
252
253 /* ------------------------------------ */
254
255 int zebra_maps_is_complete (ZebraMaps zms, int reg_type)
256
257     struct zebra_map *zm;
258     
259     for (zm = zms->map_list; zm; zm = zm->next)
260         if (reg_type == zm->reg_type)
261             return zm->completeness;
262     return 0;
263 }
264
265 int zebra_maps_attr (ZebraMaps zms, Z_AttributesPlusTerm *zapt,
266                      int *reg_type, char **search_type, int *complete_flag)
267 {
268     AttrType completeness;
269     AttrType structure;
270     AttrType relation;
271     int completeness_value;
272     int structure_value;
273     int relation_value;
274
275     attr_init (&structure, zapt, 4);
276     attr_init (&completeness, zapt, 6);
277     attr_init (&relation, zapt, 2);
278
279     completeness_value = attr_find (&completeness, NULL);
280     structure_value = attr_find (&structure, NULL);
281     relation_value = attr_find (&relation, NULL);
282
283     if (completeness_value == 2 || completeness_value == 3)
284         *complete_flag = 1;
285     else
286         *complete_flag = 0;
287     *reg_type = 0;
288
289     *search_type = "phrase";
290     if (relation_value == 102)
291         *search_type = "ranked";
292     
293     switch (structure_value)
294     {
295     case 6:   /* word list */
296     case 105: /* free-form-text */
297     case 106: /* document-text */
298         *search_type = "ranked";
299         *reg_type = 'w';
300         break;
301     case -1:
302     case 1:   /* phrase */
303     case 2:   /* word */
304     case 3:   /* key */
305     case 108: /* string */ 
306         if (*complete_flag)
307             *reg_type = 'p';
308         else
309             *reg_type = 'w';
310         break;
311     case 107: /* local-number */
312         *search_type = "local";
313         *reg_type = 0;
314     case 109: /* numeric string */
315         *reg_type = 'n';
316         break;
317     case 104: /* urx */
318         *reg_type = 'u';
319         break;
320     default:
321         return -1;
322     }
323     return 0;
324 }