Changed include/yaz/diagbib1.h and added include/yaz/diagsrw.h with
[yaz-moved-to-github.git] / src / xcqlutil.c
1 /* $Id: xcqlutil.c,v 1.5 2005-01-15 19:47:14 adam Exp $
2    Copyright (C) 1995-2005, 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("<relation>", pr, client_data, level+4);
108                 pr_cdata(m->u.st.relation, pr, client_data);
109                 pr_n("</relation>\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         pr_n("</searchClause>\n", pr, client_data, level);
167         break;
168     case CQL_NODE_BOOL:
169         pr_n("<triple>\n", pr, client_data, level);
170         if (cn->u.boolean.value)
171         {
172             pr_n("<boolean>\n", pr, client_data, level+2);
173
174             pr_n("<value>", pr, client_data, level+4);
175             pr_cdata(cn->u.boolean.value, pr, client_data);
176             pr_n("</value>\n", pr, client_data, 0);
177
178             cql_to_xml_mod(cn->u.boolean.modifiers,
179                            pr, client_data, level+4);
180
181             pr_n("</boolean>\n", pr, client_data, level+2);
182         }
183         if (cn->u.boolean.left)
184         {
185             printf ("%*s<leftOperand>\n", level+2, "");
186             cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4);
187             printf ("%*s</leftOperand>\n", level+2, "");
188         }
189         if (cn->u.boolean.right)
190         {
191             printf ("%*s<rightOperand>\n", level+2, "");
192             cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4);
193             printf ("%*s</rightOperand>\n", level+2, "");
194         }
195         pr_n("</triple>\n", pr, client_data, level);
196     }
197 }
198
199 void cql_to_xml(struct cql_node *cn, 
200                 void (*pr)(const char *buf, void *client_data),
201                 void *client_data)
202 {
203     cql_to_xml_r(cn, pr, client_data, 0);
204 }
205
206 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
207 {
208     cql_to_xml(cn, cql_fputs, f);
209 }
210
211 void cql_buf_write_handler (const char *b, void *client_data)
212 {
213     struct cql_buf_write_info *info = (struct cql_buf_write_info *)client_data;
214     int l = strlen(b);
215     if (info->off < 0 || (info->off + l >= info->max))
216     {
217         info->off = -1;
218         return;
219     }
220     memcpy (info->buf + info->off, b, l);
221     info->off += l;
222 }
223
224 int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
225 {
226     struct cql_buf_write_info info;
227     info.off = 0;
228     info.max = max;
229     info.buf = out;
230     cql_to_xml(cn, cql_buf_write_handler, &info);
231     if (info.off >= 0)
232         info.buf[info.off] = '\0';
233     return info.off;
234 }
235