SRW, CQL, 2003
[yaz-moved-to-github.git] / cql / xcqlutil.c
1 /* $Id: xcqlutil.c,v 1.1 2003-01-06 08:20:27 adam Exp $
2    Copyright (C) 2002-2003
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.mod.next)
61         {
62             pr_n("<prefix>\n", pr, client_data, level+2);
63             if (cn->u.mod.name)
64             {
65                 pr_n("<name>", pr, client_data, level+4);
66                 pr_cdata(cn->u.mod.name, pr, client_data);
67                 pr_n("</name>\n", pr, client_data, 0);
68             }
69             if (cn->u.mod.value)
70             {
71                 pr_n("<identifier>", pr, client_data, level+4);
72                 pr_cdata(cn->u.mod.value, 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_r(struct cql_node *cn,
82                          void (*pr)(const char *buf, void *client_data),
83                          void *client_data, int level)
84 {
85     if (!cn)
86         return;
87     switch (cn->which)
88     {
89     case CQL_NODE_ST:
90         pr_n("<searchClause>\n", pr, client_data, level);
91         prefixes(cn->u.st.prefixes, pr, client_data, level+2);
92         if (cn->u.st.index)
93         {
94             pr_n("<index>", pr, client_data, level+2);
95             pr_cdata(cn->u.st.index, pr, client_data);
96             pr_n("</index>\n", pr, client_data, 0);
97         }
98         if (cn->u.st.relation)
99         {
100             struct cql_node *m = cn->u.st.modifiers;
101             pr_n("<relation>\n", pr, client_data, level+2);
102             pr_n("<value>", pr, client_data, level+4);
103             pr_cdata(cn->u.st.relation, pr, client_data);
104             pr_n("</value>\n", pr, client_data, 0);
105             if (m)
106             {
107                 pr_n("<modifiers>\n", pr, client_data, level+4);
108                 for (; m; m = m->u.mod.next)
109                 {
110                     pr_n("<modifier><value>", pr, client_data, level+6);
111                     pr_cdata(m->u.mod.value, pr, client_data);
112                     pr_n("</value></modifier>\n", pr, client_data, 0);
113                 }
114                 pr_n("</modifiers>\n", pr, client_data, level+4);
115             }
116             pr_n("</relation>\n", pr, client_data, level+2);
117         }
118         if (cn->u.st.term)
119         {
120             pr_n("<term>", pr, client_data, level+2);
121             pr_cdata(cn->u.st.term, pr, client_data);
122             pr_n("</term>\n", pr, client_data, 0);
123         }
124         pr_n("</searchClause>\n", pr, client_data, level);
125         break;
126     case CQL_NODE_BOOL:
127         pr_n("<triple>\n", pr, client_data, level);
128         prefixes(cn->u.st.prefixes, pr, client_data, level+2);
129         if (cn->u.bool.value)
130         {
131             struct cql_node *m = cn->u.bool.modifiers;
132             pr_n("<boolean>\n", pr, client_data, level+2);
133
134             pr_n("<value>", pr, client_data, level+4);
135             pr_cdata(cn->u.bool.value, pr, client_data);
136             pr_n("</value>\n", pr, client_data, 0);
137
138             if (m)
139             {
140                 pr_n("<modifiers>\n", pr, client_data, level+4);
141                 for (; m; m = m->u.mod.next)
142                 {
143                     pr_n("<modifier><type>", pr, client_data, level+6);
144                     pr_cdata(m->u.mod.name, pr, client_data);
145                     pr_n("</type>", pr, client_data, 0);
146                     if (m->u.mod.value)
147                     {
148                         pr_n("<value>", pr, client_data, 0);
149                         pr_cdata(m->u.mod.value, pr, client_data);
150                         pr_n("</value>", pr, client_data, 0);
151                     }
152                     pr_n("</modifier>\n", pr, client_data, 0);
153                 }
154                 pr_n("</modifiers>\n", pr, client_data, level+4);
155             }
156             pr_n("</boolean>\n", pr, client_data, level+2);
157         }
158         if (cn->u.bool.left)
159         {
160             printf ("%*s<leftOperand>\n", level+2, "");
161             cql_to_xml_r(cn->u.bool.left, pr, client_data, level+4);
162             printf ("%*s</leftOperand>\n", level+2, "");
163         }
164         if (cn->u.bool.right)
165         {
166             printf ("%*s<rightOperand>\n", level+2, "");
167             cql_to_xml_r(cn->u.bool.right, pr, client_data, level+4);
168             printf ("%*s</rightOperand>\n", level+2, "");
169         }
170         pr_n("</triple>\n", pr, client_data, level);
171     }
172 }
173
174 void cql_to_xml(struct cql_node *cn, 
175                 void (*pr)(const char *buf, void *client_data),
176                 void *client_data)
177 {
178     cql_to_xml_r(cn, pr, client_data, 0);
179 }
180
181 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
182 {
183     cql_to_xml(cn, cql_fputs, f);
184 }
185
186 void cql_buf_write_handler (const char *b, void *client_data)
187 {
188     struct cql_buf_write_info *info = client_data;
189     int l = strlen(b);
190     if (info->off < 0 || (info->off + l >= info->max))
191     {
192         info->off = -1;
193         return;
194     }
195     memcpy (info->buf + info->off, b, l);
196     info->off += l;
197 }
198
199 int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
200 {
201     struct cql_buf_write_info info;
202     info.off = 0;
203     info.max = max;
204     info.buf = out;
205     cql_to_xml(cn, cql_buf_write_handler, &info);
206     if (info.off >= 0)
207         info.buf[info.off] = '\0';
208     return info.off;
209 }
210