Moved towards generic character mapping depending on "structure"
[idzebra-moved-to-github.git] / util / zebramap.c
1 /*
2  * Copyright (C) 1994-1997, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zebramap.c,v $
7  * Revision 1.1  1997-10-27 14:33:06  adam
8  * Moved towards generic character mapping depending on "structure"
9  * field in abstract syntax file. Fixed a few memory leaks. Fixed
10  * bug with negative integers when doing searches with relational
11  * operators.
12  *
13  */
14
15 #include <assert.h>
16 #include <ctype.h>
17
18 #include <yaz-util.h>
19 #include <charmap.h>
20 #include <zebramap.h>
21
22 struct zebra_map {
23     int reg_type;
24     chrmaptab maptab;
25     struct zebra_map *next;
26 };
27
28 struct zebra_maps {
29     char *tabpath;
30     NMEM nmem;
31     struct zebra_map *map_list;
32 };
33
34 void zebra_maps_close (ZebraMaps zms)
35 {
36     struct zebra_map *zm = zms->map_list;
37     while (zm)
38     {
39         struct zebra_map *zm_next = zm->next;
40
41         chrmaptab_destroy (zm->maptab);
42         xfree (zm);
43         zm = zm_next;
44     }
45     nmem_destroy (zms->nmem);
46     xfree (zms);
47 }
48
49 ZebraMaps zebra_maps_open (const char *tabpath)
50 {
51     ZebraMaps zms = xmalloc (sizeof(*zms));
52
53     zms->nmem = nmem_create ();
54     zms->tabpath = nmem_strdup (zms->nmem, tabpath);
55     zms->map_list = NULL;
56     return zms;
57 }
58
59 chrmaptab zebra_map_get (ZebraMaps zms, int reg_type)
60 {
61     char name[512];
62     struct zebra_map *zm;
63
64     for (zm = zms->map_list; zm; zm = zm->next)
65     {
66         if (reg_type == zm->reg_type)
67             return zm->maptab;
68     }
69     *name = '\0';
70     switch (reg_type)
71     {
72     case 'w':
73     case 'p':
74         strcat (name, "string");
75         break;
76     case 'n':
77         strcat (name, "numeric");
78         break;
79     case 'u':
80         strcat (name, "urx");
81         break;
82     default:
83         strcat (name, "null");
84     }
85     strcat (name, ".chr");
86
87     zm = xmalloc (sizeof(*zm));
88     zm->reg_type = reg_type;
89     zm->next = zms->map_list;
90     zms->map_list = zm;
91     if (!(zm->maptab = chrmaptab_create (zms->tabpath, name, 0)))
92         logf(LOG_WARN, "Failed to read character table %s", name);
93     else
94         logf(LOG_LOG, "Read table %s", name);
95     return zm->maptab;
96 }
97
98 const char **zebra_maps_input (ZebraMaps zms, int reg_type,
99                                const char **from, int len)
100 {
101     static char str[2] = {0,0};
102     static const char *buf[2] = {0,0};
103     chrmaptab maptab;
104
105     maptab = zebra_map_get (zms, reg_type);
106     if (maptab)
107         return chr_map_input(maptab, from, len);
108         
109     if (isalnum(**from))
110     {
111         str[0] = isupper(**from) ? tolower(**from) : **from;
112         buf[0] = str;
113     }
114     else
115         buf[0] = (char*) CHR_SPACE;
116     (*from)++;
117     return buf;
118 }
119
120 const char *zebra_maps_output(ZebraMaps zms, int reg_type, const char **from)
121 {
122     chrmaptab maptab;
123     unsigned char i = (unsigned char) **from;
124     static char buf[2] = {0,0};
125
126     maptab = zebra_map_get (zms, reg_type);
127     if (maptab)
128         return chr_map_output (maptab, from, 1);
129     (*from)++;
130     buf[0] = i;
131     return buf;
132 }
133
134
135 /* ------------------------------------ */
136
137 typedef struct {
138     int type;
139     int major;
140     int minor;
141     Z_AttributesPlusTerm *zapt;
142 } AttrType;
143
144 static int attr_find (AttrType *src, oid_value *attributeSetP)
145 {
146     while (src->major < src->zapt->num_attributes)
147     {
148         Z_AttributeElement *element;
149
150         element = src->zapt->attributeList[src->major];
151         if (src->type == *element->attributeType)
152         {
153             switch (element->which) 
154             {
155             case Z_AttributeValue_numeric:
156                 ++(src->major);
157                 if (element->attributeSet && attributeSetP)
158                 {
159                     oident *attrset;
160
161                     attrset = oid_getentbyoid (element->attributeSet);
162                     *attributeSetP = attrset->value;
163                 }
164                 return *element->value.numeric;
165                 break;
166             case Z_AttributeValue_complex:
167                 if (src->minor >= element->value.complex->num_list ||
168                     element->value.complex->list[src->minor]->which !=  
169                     Z_StringOrNumeric_numeric)
170                     break;
171                 ++(src->minor);
172                 if (element->attributeSet && attributeSetP)
173                 {
174                     oident *attrset;
175
176                     attrset = oid_getentbyoid (element->attributeSet);
177                     *attributeSetP = attrset->value;
178                 }
179                 return *element->value.complex->list[src->minor-1]->u.numeric;
180             default:
181                 assert (0);
182             }
183         }
184         ++(src->major);
185     }
186     return -1;
187 }
188
189 static void attr_init (AttrType *src, Z_AttributesPlusTerm *zapt,
190                        int type)
191 {
192     src->zapt = zapt;
193     src->type = type;
194     src->major = 0;
195     src->minor = 0;
196 }
197
198 /* ------------------------------------ */
199
200 int zebra_maps_is_complete (ZebraMaps zms, int reg_type)
201 {
202     if (reg_type == 'p')
203         return 1;
204     return 0;
205 }
206
207 int zebra_maps_attr (ZebraMaps zms, Z_AttributesPlusTerm *zapt,
208                      int *reg_type, char **search_type, int *complete_flag)
209 {
210     AttrType completeness;
211     AttrType structure;
212     AttrType relation;
213     int completeness_value;
214     int structure_value;
215     int relation_value;
216
217     attr_init (&structure, zapt, 4);
218     attr_init (&completeness, zapt, 6);
219     attr_init (&relation, zapt, 2);
220
221     completeness_value = attr_find (&completeness, NULL);
222     structure_value = attr_find (&structure, NULL);
223
224     if (completeness_value == 2 || completeness_value == 3)
225         *complete_flag = 1;
226     else
227         *complete_flag = 0;
228     *reg_type = 0;
229
230     *search_type = "phrase";
231     if (relation_value == 102)
232         *search_type = "ranked";
233     
234     switch (structure_value)
235     {
236     case -1:
237     case 1:   /* phrase */
238     case 2:   /* word */
239     case 3:   /* key */
240     case 6:   /* word list */
241     case 105: /* free-form-text */
242     case 106: /* document-text */
243     case 108: /* string */ 
244         if (*complete_flag)
245             *reg_type = 'p';
246         else
247             *reg_type = 'w';
248         break;
249     case 107: /* local-number */
250         *search_type = "local";
251         *reg_type = 0;
252     case 109: /* numeric string */
253         *reg_type = 'n';
254         break;
255     case 104: /* urx */
256         *reg_type = 'u';
257         break;
258     default:
259         return -1;
260     }
261     return 0;
262 }