Changed license of CCL module to 'Revised BSD'.
[yaz-moved-to-github.git] / src / cclqual.c
1 /*
2  * Copyright (C) 1995-2008, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: cclqual.c,v 1.13 2008-01-09 21:32:28 adam Exp $
6  */
7 /** 
8  * \file cclqual.c
9  * \brief Implements CCL qualifier utilities
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <yaz/snprintf.h>
15 #include <yaz/tokenizer.h>
16 #include "cclp.h"
17
18 /** CCL Qualifier */
19 struct ccl_qualifier {
20     char *name;
21     int no_sub;
22     struct ccl_qualifier **sub;
23     struct ccl_rpn_attr *attr_list;
24     struct ccl_qualifier *next;
25 };
26
27
28 /** Definition of CCL_bibset pointer */
29 struct ccl_qualifiers {
30     struct ccl_qualifier *list;
31     struct ccl_qualifier_special *special;
32 };
33
34
35 /** CCL Qualifier special */
36 struct ccl_qualifier_special {
37     char *name;
38     const char **values;
39     struct ccl_qualifier_special *next;
40 };
41
42
43 static struct ccl_qualifier *ccl_qual_lookup(CCL_bibset b,
44                                              const char *n, size_t len)
45 {
46     struct ccl_qualifier *q;
47     for (q = b->list; q; q = q->next)
48         if (len == strlen(q->name) && !memcmp(q->name, n, len))
49             break;
50     return q;
51 }
52
53 void ccl_qual_add_special_ar(CCL_bibset bibset, const char *n,
54                              const char **values)
55 {
56     struct ccl_qualifier_special *p;
57     for (p = bibset->special; p && strcmp(p->name, n); p = p->next)
58         ;
59     if (p)
60     {
61         if (p->values)
62         {
63             int i;
64             for (i = 0; p->values[i]; i++)
65                 xfree((char *) p->values[i]);
66             xfree((char **)p->values);
67         }
68     }
69     else
70     {
71         p = (struct ccl_qualifier_special *) xmalloc(sizeof(*p));
72         p->name = xstrdup(n);
73         p->next = bibset->special;
74         bibset->special = p;
75     }
76     p->values = values;
77 }
78
79 void ccl_qual_add_special(CCL_bibset bibset, const char *n, const char *cp)
80 {
81     size_t no = 2;
82     char **vlist = (char **) xmalloc(no * sizeof(*vlist));
83     yaz_tok_cfg_t yt = yaz_tok_cfg_create();
84     int t;
85     size_t i = 0;
86     
87     yaz_tok_parse_t tp = yaz_tok_parse_buf(yt, cp);
88     
89     yaz_tok_cfg_destroy(yt);
90     
91     t = yaz_tok_move(tp);
92     while (t == YAZ_TOK_STRING)
93     {
94         if (i >= no-1)
95             vlist = (char **) xrealloc(vlist, (no = no * 2) * sizeof(*vlist));
96         vlist[i++] = xstrdup(yaz_tok_parse_string(tp));
97         t = yaz_tok_move(tp); 
98     }
99     vlist[i] = 0;
100     ccl_qual_add_special_ar(bibset, n, (const char **) vlist);
101     
102     yaz_tok_parse_destroy(tp);
103 }
104
105
106 /** \brief adds specifies qualifier aliases
107     
108     \param b bibset
109     \param n qualifier name
110     \param names list of qualifier aliases
111 */
112 void ccl_qual_add_combi(CCL_bibset b, const char *n, const char **names)
113 {
114     int i;
115     struct ccl_qualifier *q;
116     for (q = b->list; q && strcmp(q->name, n); q = q->next)
117         ;
118     if (q)
119         return ;
120     q = (struct ccl_qualifier *) xmalloc(sizeof(*q));
121     q->name = xstrdup(n);
122     q->attr_list = 0;
123     q->next = b->list;
124     b->list = q;
125     
126     for (i = 0; names[i]; i++)
127         ;
128     q->no_sub = i;
129     q->sub = (struct ccl_qualifier **)
130         xmalloc(sizeof(*q->sub) * (1+q->no_sub));
131     for (i = 0; names[i]; i++)
132         q->sub[i] = ccl_qual_lookup(b, names[i], strlen(names[i]));
133 }
134
135 /** \brief adds specifies attributes for qualifier
136     
137     \param b bibset
138     \param name qualifier name
139     \param no number of attribute type+value pairs
140     \param type_ar attributes type of size no
141     \param value_ar attribute value of size no
142     \param svalue_ar attribute string values ([i] only used  if != NULL)
143     \param attsets attribute sets of size no
144 */
145
146 void ccl_qual_add_set(CCL_bibset b, const char *name, int no,
147                        int *type_ar, int *value_ar, char **svalue_ar,
148                        char **attsets)
149 {
150     struct ccl_qualifier *q;
151     struct ccl_rpn_attr **attrp;
152
153     ccl_assert(b);
154     for (q = b->list; q; q = q->next)
155         if (!strcmp(name, q->name))
156             break;
157     if (!q)
158     {
159         q = (struct ccl_qualifier *)xmalloc(sizeof(*q));
160         ccl_assert(q);
161         
162         q->next = b->list;
163         b->list = q;
164         
165         q->name = xstrdup(name);
166         q->attr_list = 0;
167
168         q->no_sub = 0;
169         q->sub = 0;
170     }
171     attrp = &q->attr_list;
172     while (*attrp)
173         attrp = &(*attrp)->next;
174     while (--no >= 0)
175     {
176         struct ccl_rpn_attr *attr;
177
178         attr = (struct ccl_rpn_attr *)xmalloc(sizeof(*attr));
179         ccl_assert(attr);
180         attr->set = *attsets++;
181         attr->type = *type_ar++;
182         if (*svalue_ar)
183         {
184             attr->kind = CCL_RPN_ATTR_STRING;
185             attr->value.str = *svalue_ar;
186         }
187         else
188         {
189             attr->kind = CCL_RPN_ATTR_NUMERIC;
190             attr->value.numeric = *value_ar;
191         }
192         svalue_ar++;
193         value_ar++;
194         *attrp = attr;
195         attrp = &attr->next;
196     }
197     *attrp = NULL;
198 }
199
200 /** \brief creates Bibset
201     \returns bibset
202  */
203 CCL_bibset ccl_qual_mk(void)
204 {
205     CCL_bibset b = (CCL_bibset)xmalloc(sizeof(*b));
206     ccl_assert(b);
207     b->list = NULL;     
208     b->special = NULL;
209     return b;
210 }
211
212 /** \brief destroys Bibset
213     \param b pointer to Bibset
214     
215     *b will be set to NULL.
216  */
217 void ccl_qual_rm(CCL_bibset *b)
218 {
219     struct ccl_qualifier *q, *q1;
220     struct ccl_qualifier_special *sp, *sp1;
221
222     if (!*b)
223         return;
224     for (q = (*b)->list; q; q = q1)
225     {
226         struct ccl_rpn_attr *attr, *attr1;
227
228         for (attr = q->attr_list; attr; attr = attr1)
229         {
230             attr1 = attr->next;
231             if (attr->set)
232                 xfree(attr->set);
233             if (attr->kind == CCL_RPN_ATTR_STRING)
234                 xfree(attr->value.str);
235             xfree(attr);
236         }
237         q1 = q->next;
238         xfree(q->name);
239         if (q->sub)
240             xfree(q->sub);
241         xfree(q);
242     }
243     for (sp = (*b)->special; sp; sp = sp1)
244     {
245         sp1 = sp->next;
246         xfree(sp->name);
247         if (sp->values)
248         {
249             int i;
250             for (i = 0; sp->values[i]; i++)
251                 xfree((char*) sp->values[i]);
252             xfree((char **)sp->values);
253         }
254         xfree(sp);
255     }
256     xfree(*b);
257     *b = NULL;
258 }
259
260 ccl_qualifier_t ccl_qual_search(CCL_parser cclp, const char *name, 
261                                 size_t name_len, int seq)
262 {
263     struct ccl_qualifier *q = 0;
264     const char **aliases;
265     int case_sensitive = cclp->ccl_case_sensitive;
266
267     ccl_assert(cclp);
268     if (!cclp->bibset)
269         return 0;
270
271     aliases = ccl_qual_search_special(cclp->bibset, "case");
272     if (aliases)
273         case_sensitive = atoi(aliases[0]);
274
275     for (q = cclp->bibset->list; q; q = q->next)
276         if (strlen(q->name) == name_len)
277         {
278             if (case_sensitive)
279             {
280                 if (!memcmp(name, q->name, name_len))
281                     break;
282             }
283             else
284             {
285                 if (!ccl_memicmp(name, q->name, name_len))
286                     break;
287             }
288         }
289     if (q)
290     {
291         if (q->no_sub)
292         {
293             if (seq < q->no_sub)
294                 q = q->sub[seq];
295             else
296                 q = 0;
297         }
298         else if (seq)
299             q = 0;
300     }
301     return q;
302 }
303
304 struct ccl_rpn_attr *ccl_qual_get_attr(ccl_qualifier_t q)
305 {
306     return q->attr_list;
307 }
308
309 const char *ccl_qual_get_name(ccl_qualifier_t q)
310 {
311     return q->name;
312 }
313
314 const char **ccl_qual_search_special(CCL_bibset b, const char *name)
315 {
316     struct ccl_qualifier_special *q;
317     if (!b)
318         return 0;
319     for (q = b->special; q && strcmp(q->name, name); q = q->next)
320         ;
321     if (q)
322         return q->values;
323     return 0;
324 }
325
326 int ccl_search_stop(CCL_bibset bibset, const char *qname,
327                     const char *src_str, size_t src_len)
328 {
329     const char **slist = 0;
330     if (qname)
331     {
332         char qname_buf[80];
333         yaz_snprintf(qname_buf, sizeof(qname_buf)-1, "stop.%s",
334                      qname);
335         slist = ccl_qual_search_special(bibset, qname_buf);
336     }
337     if (!slist)
338         slist = ccl_qual_search_special(bibset, "stop.*");
339     if (slist)
340     {
341         int i;
342         for (i = 0; slist[i]; i++)
343             if (src_len == strlen(slist[i]) 
344                 && ccl_memicmp(slist[i], src_str, src_len) == 0)
345                 return 1;
346     }
347     return 0;
348 }
349
350 /*
351  * Local variables:
352  * c-basic-offset: 4
353  * indent-tabs-mode: nil
354  * End:
355  * vim: shiftwidth=4 tabstop=8 expandtab
356  */
357