Fixed bug #2068: pkg-config trouble.
[yaz-moved-to-github.git] / src / xcqlutil.c
1 /* $Id: xcqlutil.c,v 1.9 2008-01-06 16:22:02 adam Exp $
2    Copyright (C) 1995-2007, Index Data ApS
3    Index Data Aps
4
5 This file is part of the YAZ toolkit.
6
7 See the file LICENSE.
8 */
9
10 /**
11  * \file xcqlutil.c
12  * \brief Implements CQL to XCQL conversion.
13  */
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdio.h>
18
19 #include <yaz/cql.h>
20
21 static void pr_n(const char *buf, 
22                 void (*pr)(const char *buf, void *client_data),
23                 void *client_data, int n)
24 {
25     int i;
26     for (i = 0; i<n; i++)
27         (*pr)(" ", client_data);
28     (*pr)(buf, client_data);
29 }
30
31 static void pr_cdata(const char *buf,
32                      void (*pr)(const char *buf, void *client_data),
33                      void *client_data)
34 {
35     const char *src = buf;
36     char bf[2];
37     while (*src)
38     {
39         switch(*src)
40         {
41         case '&':
42             (*pr)("&amp;", client_data);
43             break;
44         case '<':
45             (*pr)("&lt;", client_data);
46             break;
47         case '>':
48             (*pr)("&gt;", client_data);
49             break;
50         default:
51             bf[0] = *src;
52             bf[1] = 0;
53             (*pr)(bf, client_data);
54         }
55         src++;
56     }
57 }
58                     
59 static void prefixes(struct cql_node *cn,
60                      void (*pr)(const char *buf, void *client_data),
61                      void *client_data, int level)
62 {
63     int head = 0;
64     if (cn->u.st.index_uri)
65     {
66         pr_n("<prefixes>\n", pr, client_data, level);
67         head = 1;
68
69         pr_n("<prefix>\n", pr, client_data, level+2);
70         pr_n("<identifier>", pr, client_data, level+4);
71         pr_cdata(cn->u.st.index_uri, pr, client_data);
72         pr_n("</identifier>\n", pr, client_data, 0);
73         pr_n("</prefix>\n", pr, client_data, level+2);
74     }
75     if (cn->u.st.relation_uri && cn->u.st.relation)
76     {
77         if (!head)
78             pr_n("<prefixes>\n", pr, client_data, level);
79         pr_n("<prefix>\n", pr, client_data, level+2);
80         pr_n("<name>", pr, client_data, level+4);
81         pr_cdata("rel", pr, client_data);
82         pr_n("</name>\n", pr, client_data, 0);
83         pr_n("<identifier>", pr, client_data, level+4);
84         pr_cdata(cn->u.st.relation_uri, pr, client_data);
85         pr_n("</identifier>\n", pr, client_data, 0);
86         pr_n("</prefix>\n", pr, client_data, level+2);
87     }
88     if (head)
89         pr_n("</prefixes>\n", pr, client_data, level);
90 }
91                      
92 static void cql_to_xml_mod(struct cql_node *m,
93                            void (*pr)(const char *buf, void *client_data),
94                            void *client_data, int level)
95 {
96     if (m)
97     {
98         pr_n("<modifiers>\n", pr, client_data, level);
99         for (; m; m = m->u.st.modifiers)
100         {
101             pr_n("<modifier>\n", pr, client_data, level+2);
102             pr_n("<type>", pr, client_data, level+4);
103             pr_cdata(m->u.st.index, pr, client_data);
104             pr_n("</type>\n", pr, client_data, 0);
105             if (m->u.st.relation)
106             {
107                 pr_n("<comparison>", pr, client_data, level+4);
108                 pr_cdata(m->u.st.relation, pr, client_data);
109                 pr_n("</comparison>\n", pr, client_data, 0);
110             }
111             if (m->u.st.term)
112             {
113                 pr_n("<value>", pr, client_data, level+4);
114                 pr_cdata(m->u.st.term, pr, client_data);
115                 pr_n("</value>\n", pr, client_data, 0);
116             }
117             pr_n("</modifier>\n", pr, client_data, level+2);
118         }
119         pr_n("</modifiers>\n", pr, client_data, level);
120     }
121 }
122
123 static void cql_to_xml_r(struct cql_node *cn,
124                          void (*pr)(const char *buf, void *client_data),
125                          void *client_data, int level)
126 {
127     if (!cn)
128         return;
129     switch (cn->which)
130     {
131     case CQL_NODE_ST:
132         pr_n("<searchClause>\n", pr, client_data, level);
133         prefixes(cn, pr, client_data, level+2);
134         if (cn->u.st.index)
135         {
136             pr_n("<index>", pr, client_data, level+2);
137             pr_cdata(cn->u.st.index, pr, client_data);
138             pr_n("</index>\n", pr, client_data, 0);
139         }
140         if (cn->u.st.relation)
141         {
142             pr_n("<relation>\n", pr, client_data, level+2);
143             pr_n("<value>", pr, client_data, level+4);
144             if (cn->u.st.relation_uri)
145                 pr_cdata("rel.", pr, client_data);
146             pr_cdata(cn->u.st.relation, pr, client_data);
147             pr_n("</value>\n", pr, client_data, 0);
148
149             if (cn->u.st.relation_uri)
150             {
151                 pr_n("<identifier>", pr, client_data, level+4);
152                 pr_cdata(cn->u.st.relation_uri, pr, client_data);
153                 pr_n("</identifier>\n", pr, client_data, 0);
154             }
155             cql_to_xml_mod(cn->u.st.modifiers,
156                            pr, client_data, level+4);
157
158             pr_n("</relation>\n", pr, client_data, level+2);
159         }
160         if (cn->u.st.term)
161         {
162             pr_n("<term>", pr, client_data, level+2);
163             pr_cdata(cn->u.st.term, pr, client_data);
164             pr_n("</term>\n", pr, client_data, 0);
165         }
166         if (cn->u.st.extra_terms)
167         {
168             struct cql_node *n = cn->u.st.extra_terms;
169             for (; n; n = n->u.st.extra_terms)
170             {
171                 pr_n("<term>", pr, client_data, level+2);
172                 pr_cdata(n->u.st.term, pr, client_data);
173                 pr_n("</term>\n", pr, client_data, 0);
174             }
175         }
176         pr_n("</searchClause>\n", pr, client_data, level);
177         break;
178     case CQL_NODE_BOOL:
179         pr_n("<triple>\n", pr, client_data, level);
180         if (cn->u.boolean.value)
181         {
182             pr_n("<boolean>\n", pr, client_data, level+2);
183
184             pr_n("<value>", pr, client_data, level+4);
185             pr_cdata(cn->u.boolean.value, pr, client_data);
186             pr_n("</value>\n", pr, client_data, 0);
187
188             cql_to_xml_mod(cn->u.boolean.modifiers,
189                            pr, client_data, level+4);
190
191             pr_n("</boolean>\n", pr, client_data, level+2);
192         }
193         if (cn->u.boolean.left)
194         {
195             printf ("%*s<leftOperand>\n", level+2, "");
196             cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4);
197             printf ("%*s</leftOperand>\n", level+2, "");
198         }
199         if (cn->u.boolean.right)
200         {
201             printf ("%*s<rightOperand>\n", level+2, "");
202             cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4);
203             printf ("%*s</rightOperand>\n", level+2, "");
204         }
205         pr_n("</triple>\n", pr, client_data, level);
206     }
207 }
208
209 void cql_to_xml(struct cql_node *cn, 
210                 void (*pr)(const char *buf, void *client_data),
211                 void *client_data)
212 {
213     cql_to_xml_r(cn, pr, client_data, 0);
214 }
215
216 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
217 {
218     cql_to_xml(cn, cql_fputs, f);
219 }
220
221 void cql_buf_write_handler (const char *b, void *client_data)
222 {
223     struct cql_buf_write_info *info = (struct cql_buf_write_info *)client_data;
224     int l = strlen(b);
225     if (info->off < 0 || (info->off + l >= info->max))
226     {
227         info->off = -1;
228         return;
229     }
230     memcpy (info->buf + info->off, b, l);
231     info->off += l;
232 }
233
234 int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
235 {
236     struct cql_buf_write_info info;
237     info.off = 0;
238     info.max = max;
239     info.buf = out;
240     cql_to_xml(cn, cql_buf_write_handler, &info);
241     if (info.off >= 0)
242         info.buf[info.off] = '\0';
243     return info.off;
244 }
245
246 /*
247  * Local variables:
248  * c-basic-offset: 4
249  * indent-tabs-mode: nil
250  * End:
251  * vim: shiftwidth=4 tabstop=8 expandtab
252  */
253