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