YAZ  5.34.0
xcqlutil.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 
17 #include <yaz/cql.h>
18 
19 static void pr_n(const char *buf,
20  void (*pr)(const char *buf, void *client_data),
21  void *client_data, int n)
22 {
23  int i;
24  for (i = 0; i<n; i++)
25  (*pr)(" ", client_data);
26  (*pr)(buf, client_data);
27 }
28 
29 static void pr_cdata(const char *buf,
30  void (*pr)(const char *buf, void *client_data),
31  void *client_data)
32 {
33  const char *src = buf;
34  char bf[2];
35  while (*src)
36  {
37  switch(*src)
38  {
39  case '&':
40  (*pr)("&amp;", client_data);
41  break;
42  case '<':
43  (*pr)("&lt;", client_data);
44  break;
45  case '>':
46  (*pr)("&gt;", client_data);
47  break;
48  default:
49  bf[0] = *src;
50  bf[1] = 0;
51  (*pr)(bf, client_data);
52  }
53  src++;
54  }
55 }
56 
57 static void prefixes(struct cql_node *cn,
58  void (*pr)(const char *buf, void *client_data),
59  void *client_data, int level)
60 {
61  int head = 0;
62  if (cn->u.st.index_uri)
63  {
64  pr_n("<prefixes>\n", pr, client_data, level);
65  head = 1;
66 
67  pr_n("<prefix>\n", pr, client_data, level+2);
68  pr_n("<identifier>", pr, client_data, level+4);
69  pr_cdata(cn->u.st.index_uri, pr, client_data);
70  pr_n("</identifier>\n", pr, client_data, 0);
71  pr_n("</prefix>\n", pr, client_data, level+2);
72  }
73  if (cn->u.st.relation_uri && cn->u.st.relation)
74  {
75  if (!head)
76  pr_n("<prefixes>\n", pr, client_data, level);
77  pr_n("<prefix>\n", pr, client_data, level+2);
78  pr_n("<name>", pr, client_data, level+4);
79  pr_cdata("rel", pr, client_data);
80  pr_n("</name>\n", pr, client_data, 0);
81  pr_n("<identifier>", pr, client_data, level+4);
82  pr_cdata(cn->u.st.relation_uri, pr, client_data);
83  pr_n("</identifier>\n", pr, client_data, 0);
84  pr_n("</prefix>\n", pr, client_data, level+2);
85  }
86  if (head)
87  pr_n("</prefixes>\n", pr, client_data, level);
88 }
89 
90 static void cql_to_xml_mod(struct cql_node *m,
91  void (*pr)(const char *buf, void *client_data),
92  void *client_data, int level)
93 {
94  if (m)
95  {
96  pr_n("<modifiers>\n", pr, client_data, level);
97  for (; m; m = m->u.st.modifiers)
98  {
99  pr_n("<modifier>\n", pr, client_data, level+2);
100  pr_n("<type>", pr, client_data, level+4);
101  pr_cdata(m->u.st.index, pr, client_data);
102  pr_n("</type>\n", pr, client_data, 0);
103  if (m->u.st.relation)
104  {
105  pr_n("<comparison>", pr, client_data, level+4);
106  pr_cdata(m->u.st.relation, pr, client_data);
107  pr_n("</comparison>\n", pr, client_data, 0);
108  }
109  if (m->u.st.term)
110  {
111  pr_n("<value>", pr, client_data, level+4);
112  pr_cdata(m->u.st.term, pr, client_data);
113  pr_n("</value>\n", pr, client_data, 0);
114  }
115  pr_n("</modifier>\n", pr, client_data, level+2);
116  }
117  pr_n("</modifiers>\n", pr, client_data, level);
118  }
119 }
120 
121 static void cql_sort_to_xml(struct cql_node *cn,
122  void (*pr)(const char *buf, void *client_data),
123  void *client_data, int level)
124 {
125  if (cn)
126  {
127  pr_n("<sortKeys>\n", pr, client_data, level);
128  for (; cn; cn = cn->u.sort.next)
129  {
130  pr_n("<key>\n", pr, client_data, level+2);
131 
132  if (cn->u.sort.index)
133  {
134  pr_n("<index>", pr, client_data, level+4);
135  pr_cdata(cn->u.sort.index, pr, client_data);
136  pr_n("</index>\n", pr, client_data, 0);
137 
138  cql_to_xml_mod(cn->u.sort.modifiers,
139  pr, client_data, level+6);
140  }
141  pr_n("</key>\n", pr, client_data, level+2);
142  }
143  pr_n("</sortKeys>\n", pr, client_data, level);
144  }
145 }
146 
147 static void cql_to_xml_r(struct cql_node *cn,
148  void (*pr)(const char *buf, void *client_data),
149  void *client_data, int level,
150  struct cql_node *sort_node)
151 {
152  if (!cn)
153  return;
154  switch (cn->which)
155  {
156  case CQL_NODE_ST:
157  pr_n("<searchClause>\n", pr, client_data, level);
158  prefixes(cn, pr, client_data, level+2);
159  if (cn->u.st.index)
160  {
161  pr_n("<index>", pr, client_data, level+2);
162  pr_cdata(cn->u.st.index, pr, client_data);
163  pr_n("</index>\n", pr, client_data, 0);
164  }
165  if (cn->u.st.relation)
166  {
167  pr_n("<relation>\n", pr, client_data, level+2);
168  pr_n("<value>", pr, client_data, level+4);
169  if (cn->u.st.relation_uri)
170  pr_cdata("rel.", pr, client_data);
171  pr_cdata(cn->u.st.relation, pr, client_data);
172  pr_n("</value>\n", pr, client_data, 0);
173 
174  if (cn->u.st.relation_uri)
175  {
176  pr_n("<identifier>", pr, client_data, level+4);
177  pr_cdata(cn->u.st.relation_uri, pr, client_data);
178  pr_n("</identifier>\n", pr, client_data, 0);
179  }
180  cql_to_xml_mod(cn->u.st.modifiers,
181  pr, client_data, level+4);
182 
183  pr_n("</relation>\n", pr, client_data, level+2);
184  }
185  if (cn->u.st.term)
186  {
187  pr_n("<term>", pr, client_data, level+2);
188  pr_cdata(cn->u.st.term, pr, client_data);
189  pr_n("</term>\n", pr, client_data, 0);
190  }
191  if (cn->u.st.extra_terms)
192  {
193  struct cql_node *n = cn->u.st.extra_terms;
194  for (; n; n = n->u.st.extra_terms)
195  {
196  pr_n("<term>", pr, client_data, level+2);
197  pr_cdata(n->u.st.term, pr, client_data);
198  pr_n("</term>\n", pr, client_data, 0);
199  }
200  }
201  cql_sort_to_xml(sort_node, pr, client_data, level+2);
202  pr_n("</searchClause>\n", pr, client_data, level);
203  break;
204  case CQL_NODE_BOOL:
205  pr_n("<triple>\n", pr, client_data, level);
206  if (cn->u.boolean.value)
207  {
208  pr_n("<boolean>\n", pr, client_data, level+2);
209 
210  pr_n("<value>", pr, client_data, level+4);
211  pr_cdata(cn->u.boolean.value, pr, client_data);
212  pr_n("</value>\n", pr, client_data, 0);
213 
214  cql_to_xml_mod(cn->u.boolean.modifiers,
215  pr, client_data, level+4);
216 
217  pr_n("</boolean>\n", pr, client_data, level+2);
218  }
219  if (cn->u.boolean.left)
220  {
221  printf ("%*s<leftOperand>\n", level+2, "");
222  cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4, 0);
223  printf ("%*s</leftOperand>\n", level+2, "");
224  }
225  if (cn->u.boolean.right)
226  {
227  printf ("%*s<rightOperand>\n", level+2, "");
228  cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4, 0);
229  printf ("%*s</rightOperand>\n", level+2, "");
230  }
231  cql_sort_to_xml(sort_node, pr, client_data, level+2);
232  pr_n("</triple>\n", pr, client_data, level);
233  break;
234  case CQL_NODE_SORT:
235  cql_to_xml_r(cn->u.sort.search, pr, client_data, level, cn);
236  }
237 }
238 
239 void cql_to_xml(struct cql_node *cn,
240  void (*pr)(const char *buf, void *client_data),
241  void *client_data)
242 {
243  cql_to_xml_r(cn, pr, client_data, 0, 0);
244 }
245 
246 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
247 {
248  cql_to_xml(cn, cql_fputs, f);
249 }
250 
251 void cql_buf_write_handler (const char *b, void *client_data)
252 {
253  struct cql_buf_write_info *info = (struct cql_buf_write_info *)client_data;
254  int l = strlen(b);
255  if (info->off < 0 || (info->off + l >= info->max))
256  {
257  info->off = -1;
258  return;
259  }
260  memcpy (info->buf + info->off, b, l);
261  info->off += l;
262 }
263 
264 int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
265 {
266  struct cql_buf_write_info info;
267  info.off = 0;
268  info.max = max;
269  info.buf = out;
270  cql_to_xml(cn, cql_buf_write_handler, &info);
271  if (info.off >= 0)
272  info.buf[info.off] = '\0';
273  return info.off;
274 }
275 
276 /*
277  * Local variables:
278  * c-basic-offset: 4
279  * c-file-style: "Stroustrup"
280  * indent-tabs-mode: nil
281  * End:
282  * vim: shiftwidth=4 tabstop=8 expandtab
283  */
284 
Header with public definitions about CQL.
#define CQL_NODE_SORT
Node type: sortby single spec.
Definition: cql.h:115
#define CQL_NODE_ST
Node type: search term.
Definition: cql.h:111
#define CQL_NODE_BOOL
Node type: boolean.
Definition: cql.h:113
void cql_fputs(const char *buf, void *client_data)
stream handle for file (used by cql_to_xml_stdio)
Definition: cqlutil.c:18
Structure used by cql_buf_write_handler.
Definition: cql.h:170
char * buf
Definition: cql.h:173
CQL parse tree (node)
Definition: cql.h:119
struct cql_node::@10::@12 boolean
struct cql_node::@10::@13 sort
struct cql_node::@10::@11 st
union cql_node::@10 u
int which
Definition: cql.h:121
static void cql_sort_to_xml(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data, int level)
Definition: xcqlutil.c:121
void cql_to_xml(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
converts CQL tree to XCQL and writes to user-defined stream
Definition: xcqlutil.c:239
static void cql_to_xml_r(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data, int level, struct cql_node *sort_node)
Definition: xcqlutil.c:147
static void pr_n(const char *buf, void(*pr)(const char *buf, void *client_data), void *client_data, int n)
Definition: xcqlutil.c:19
static void cql_to_xml_mod(struct cql_node *m, void(*pr)(const char *buf, void *client_data), void *client_data, int level)
Definition: xcqlutil.c:90
static void pr_cdata(const char *buf, void(*pr)(const char *buf, void *client_data), void *client_data)
Definition: xcqlutil.c:29
void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
converts CQL tree to XCQL and writes to file
Definition: xcqlutil.c:246
int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
converts CQL tree to XCQL and writes result to buffer
Definition: xcqlutil.c:264
static void prefixes(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data, int level)
Definition: xcqlutil.c:57
void cql_buf_write_handler(const char *b, void *client_data)
Handler for cql_buf_write_info.
Definition: xcqlutil.c:251