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