7dba5a766b733ffbd29f395d33d1d2ee92d9d603
[yaz-moved-to-github.git] / src / cqlutil.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file cqlutil.c
7  * \brief Implements CQL tree node utilities.
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <yaz/cql.h>
17
18 void cql_fputs(const char *buf, void *client_data)
19 {
20     FILE *f = (FILE *) client_data;
21     fputs(buf, f);
22 }
23
24 struct cql_node *cql_node_dup (NMEM nmem, struct cql_node *cp)
25 {
26     struct cql_node *cn = 0;
27
28     if (!cp)
29         return 0;
30     switch (cp->which)
31     {
32     case CQL_NODE_ST:
33         cn = cql_node_mk_sc(nmem, cp->u.st.index,
34                             cp->u.st.relation,
35                             cp->u.st.term);
36         cn->u.st.modifiers = cql_node_dup(nmem, cp->u.st.modifiers);
37         cn->u.st.index_uri = cp->u.st.index_uri ? 
38             nmem_strdup(nmem, cp->u.st.index_uri) : 0;
39         cn->u.st.relation_uri = cp->u.st.relation_uri ?
40             nmem_strdup(nmem, cp->u.st.relation_uri) : 0;
41         break;
42     case CQL_NODE_BOOL:
43         cn = cql_node_mk_boolean(nmem, cp->u.boolean.value);
44         cn->u.boolean.left = cql_node_dup(nmem, cp->u.boolean.left);
45         cn->u.boolean.right = cql_node_dup(nmem, cp->u.boolean.right);
46     }
47     return cn;
48 }
49
50 struct cql_node *cql_node_mk_sc(NMEM nmem,
51                                 const char *index,
52                                 const char *relation,
53                                 const char *term)
54 {
55     struct cql_node *p = (struct cql_node *) nmem_malloc(nmem, sizeof(*p));
56     p->which = CQL_NODE_ST;
57     p->u.st.index = 0;
58     if (index)
59         p->u.st.index = nmem_strdup(nmem, index);
60     p->u.st.index_uri = 0;
61     p->u.st.term = 0;
62     if (term)
63         p->u.st.term = nmem_strdup(nmem, term);
64     p->u.st.relation = 0;
65     if (relation)
66         p->u.st.relation = nmem_strdup(nmem, relation);
67     p->u.st.relation_uri = 0;
68     p->u.st.modifiers = 0;
69     p->u.st.extra_terms = 0;
70     return p;
71 }
72
73 struct cql_node *cql_node_mk_boolean(NMEM nmem, const char *op)
74 {
75     struct cql_node *p = (struct cql_node *) nmem_malloc(nmem, sizeof(*p));
76     p->which = CQL_NODE_BOOL;
77     p->u.boolean.value = 0;
78     if (op)
79         p->u.boolean.value = nmem_strdup(nmem, op);
80     p->u.boolean.left = 0;
81     p->u.boolean.right = 0;
82     p->u.boolean.modifiers = 0;
83     return p;
84 }
85
86 struct cql_node *cql_node_mk_sort(NMEM nmem, const char *index,
87     struct cql_node *modifiers)
88 {
89     struct cql_node *p = (struct cql_node *) nmem_malloc(nmem, sizeof(*p));
90     p->which = CQL_NODE_SORT;
91     p->u.sort.index = 0;
92     if (index)
93         p->u.sort.index = nmem_strdup(nmem, index);
94     p->u.sort.modifiers = modifiers;
95     p->u.sort.next = 0;
96     return p;
97 }
98
99 const char *cql_uri(void)
100 {
101     return "info:srw/cql-context-set/1/cql-v1.2";
102 }
103
104 struct cql_node *cql_apply_prefix(NMEM nmem,
105                                   struct cql_node *n, const char *prefix,
106                                   const char *uri)
107 {
108     if (n->which == CQL_NODE_ST)
109     {
110         if (!n->u.st.index_uri && n->u.st.index)
111         {   /* not yet resolved.. */
112             const char *cp = strchr(n->u.st.index, '.');
113             if (prefix && cp && 
114                 strlen(prefix) == (size_t) (cp - n->u.st.index) &&
115                 !cql_strncmp(n->u.st.index, prefix, strlen(prefix)))
116             {
117                 char *nval = nmem_strdup(nmem, cp+1);
118                 n->u.st.index_uri = nmem_strdup(nmem, uri);
119                 n->u.st.index = nval;
120             }
121             else if (!prefix && !cp)
122             {
123                 n->u.st.index_uri = nmem_strdup(nmem, uri);
124             }
125         }
126         if (!n->u.st.relation_uri && n->u.st.relation)
127         {
128             const char *cp = strchr(n->u.st.relation, '.');
129             if (prefix && cp &&
130                 strlen(prefix) == (size_t)(cp - n->u.st.relation) &&
131                 !cql_strncmp(n->u.st.relation, prefix, strlen(prefix)))
132             {
133                 char *nval = nmem_strdup(nmem, cp+1);
134                 n->u.st.relation_uri = nmem_strdup(nmem, uri);
135                 n->u.st.relation = nval;
136             }
137         }
138     }
139     else if (n->which == CQL_NODE_BOOL)
140     {
141         cql_apply_prefix(nmem, n->u.boolean.left, prefix, uri);
142         cql_apply_prefix(nmem, n->u.boolean.right, prefix, uri);
143     }
144     return n;
145 }
146
147 void cql_node_destroy(struct cql_node *cn)
148 {
149     if (!cn)
150         return;
151     switch (cn->which)
152     {
153     case CQL_NODE_ST:
154         cql_node_destroy(cn->u.st.modifiers);
155         break;
156     case CQL_NODE_BOOL:
157         cql_node_destroy(cn->u.boolean.left);
158         cql_node_destroy(cn->u.boolean.right);
159         cql_node_destroy(cn->u.boolean.modifiers);
160         break;
161     case CQL_NODE_SORT:
162         cql_node_destroy(cn->u.sort.search);
163         cql_node_destroy(cn->u.sort.next);
164         cql_node_destroy(cn->u.sort.modifiers);
165     }
166 }
167
168 int cql_strcmp(const char *s1, const char *s2)
169 {
170     while (*s1 && *s2)
171     {
172         int c1 = *s1++;
173         int c2 = *s2++;
174         if (c1 >= 'A' && c1 <= 'Z')
175             c1 = c1 + ('a' - 'A');
176         if (c2 >= 'A' && c2 <= 'Z')
177             c2 = c2 + ('a' - 'A');
178         if (c1 != c2)
179             return c1 - c2;
180     }
181     return *s1 - *s2;
182 }
183
184 int cql_strncmp(const char *s1, const char *s2, size_t n)
185 {
186     while (*s1 && *s2 && n)
187     {
188         int c1 = *s1++;
189         int c2 = *s2++;
190         if (c1 >= 'A' && c1 <= 'Z')
191             c1 = c1 + ('a' - 'A');
192         if (c2 >= 'A' && c2 <= 'Z')
193             c2 = c2 + ('a' - 'A');
194         if (c1 != c2)
195             return c1 - c2;
196         --n;
197     }
198     if (!n)
199         return 0;
200     return *s1 - *s2;
201 }
202
203 /*
204  * Local variables:
205  * c-basic-offset: 4
206  * c-file-style: "Stroustrup"
207  * indent-tabs-mode: nil
208  * End:
209  * vim: shiftwidth=4 tabstop=8 expandtab
210  */
211