Ups... memory leak
[yaz-moved-to-github.git] / src / querytowrbuf.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5 /** \file querytowrbuf.c
6     \brief Convert Z39.50 Z_Query to PQF (as WRBUF string)
7  */
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <assert.h>
14
15 #include <yaz/logrpn.h>
16 #include <yaz/querytowrbuf.h>
17 #include <yaz/oid_db.h>
18
19 void yaz_encode_pqf_term(WRBUF b, const char *term, int len)
20 {
21     int i;
22     for (i = 0; i < len; i++)
23         if (strchr(" \"{", term[i]))
24             break;
25     if (i == len && i)
26         wrbuf_printf(b, "%.*s ", len, term);
27     else
28     {
29         wrbuf_putc(b, '"');
30         for (i = 0; i<len; i++)
31         {
32             if (term[i] == '"')
33                 wrbuf_putc(b, '\\');
34             wrbuf_putc(b, term[i]);
35         }
36         wrbuf_printf(b, "\" ");
37     }
38 }
39
40 static void yaz_attribute_element_to_wrbuf(WRBUF b,
41                                            const Z_AttributeElement *element)
42 {
43     int i;
44
45     wrbuf_puts(b, "@attr ");
46     if (element->attributeSet)
47     {
48         char oid_name_str[OID_STR_MAX];
49         const char *setname = yaz_oid_to_string_buf(element->attributeSet, 
50                                                     0, oid_name_str);
51         if (setname)
52         {
53             wrbuf_puts(b, setname);
54             wrbuf_puts(b, " ");
55         }
56     }
57     wrbuf_printf(b, ODR_INT_PRINTF "=", *element->attributeType);
58     switch (element->which) 
59     {
60     case Z_AttributeValue_numeric:
61         wrbuf_printf(b, ODR_INT_PRINTF, *element->value.numeric);
62         break;
63     case Z_AttributeValue_complex:
64         for (i = 0; i<element->value.complex->num_list; i++)
65         {
66             if (i)
67                 wrbuf_printf(b, ",");
68             if (element->value.complex->list[i]->which ==
69                 Z_StringOrNumeric_string)
70                 wrbuf_printf(b, "%s",
71                              element->value.complex->list[i]->u.string);
72             else if (element->value.complex->list[i]->which ==
73                      Z_StringOrNumeric_numeric)
74                 wrbuf_printf(b, ODR_INT_PRINTF, 
75                              *element->value.complex->list[i]->u.numeric);
76         }
77         break;
78     default:
79         wrbuf_printf (b, "@attr 1=unknown");
80     }
81     wrbuf_puts(b, " ");
82 }
83
84 static const char *complex_op_name(const Z_Operator *op)
85 {
86     switch (op->which)
87     {
88     case Z_Operator_and:
89         return "and";
90     case Z_Operator_or:
91         return "or";
92     case Z_Operator_and_not:
93         return "not";
94     case Z_Operator_prox:
95         return "prox";
96     default:
97         return "unknown complex operator";
98     }
99 }
100
101 static void yaz_apt_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt)
102 {
103     int num_attributes = zapt->attributes->num_attributes;
104     int i;
105     for (i = 0; i<num_attributes; i++)
106         yaz_attribute_element_to_wrbuf(b,zapt->attributes->attributes[i]);
107     
108     switch (zapt->term->which)
109     {
110     case Z_Term_general:
111         yaz_encode_pqf_term(b, (const char *)zapt->term->u.general->buf,
112                             zapt->term->u.general->len);
113         break;
114     case Z_Term_characterString:
115         wrbuf_printf(b, "@term string ");
116         yaz_encode_pqf_term(b, zapt->term->u.characterString,
117                             strlen(zapt->term->u.characterString));
118         break;
119     case Z_Term_numeric:
120         wrbuf_printf(b, "@term numeric " ODR_INT_PRINTF " ",
121                      *zapt->term->u.numeric);
122         break;
123     case Z_Term_null:
124         wrbuf_printf(b, "@term null x");
125         break;
126     default:
127         wrbuf_printf(b, "@term null unknown%d ", zapt->term->which);
128     }
129 }
130
131 static void yaz_rpnstructure_to_wrbuf(WRBUF b, const Z_RPNStructure *zs)
132 {
133     if (zs->which == Z_RPNStructure_complex)
134     {
135         Z_Operator *op = zs->u.complex->roperator;
136         wrbuf_printf(b, "@%s ", complex_op_name(op) );
137         if (op->which== Z_Operator_prox)
138         {
139             if (!op->u.prox->exclusion)
140                 wrbuf_putc(b, 'n');
141             else if (*op->u.prox->exclusion)
142                 wrbuf_putc(b, '1');
143             else
144                 wrbuf_putc(b, '0');
145
146             wrbuf_printf(b, " " ODR_INT_PRINTF " %d " 
147                          ODR_INT_PRINTF " ", *op->u.prox->distance,
148                          *op->u.prox->ordered,
149                          *op->u.prox->relationType);
150
151             switch(op->u.prox->which)
152             {
153             case Z_ProximityOperator_known:
154                 wrbuf_putc(b, 'k');
155                 break;
156             case Z_ProximityOperator_private:
157                 wrbuf_putc(b, 'p');
158                 break;
159             default:
160                 wrbuf_printf(b, "%d", op->u.prox->which);
161             }
162             if (op->u.prox->u.known)
163                 wrbuf_printf(b, " " ODR_INT_PRINTF " ", *op->u.prox->u.known);
164             else
165                 wrbuf_printf(b, " 0 ");
166         }
167         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
168         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
169     }
170     else if (zs->which == Z_RPNStructure_simple)
171     {
172         if (zs->u.simple->which == Z_Operand_APT)
173             yaz_apt_to_wrbuf(b, zs->u.simple->u.attributesPlusTerm);
174         else if (zs->u.simple->which == Z_Operand_resultSetId)
175         {
176             wrbuf_printf(b, "@set ");
177             yaz_encode_pqf_term(b, zs->u.simple->u.resultSetId,
178                                 strlen(zs->u.simple->u.resultSetId));
179         }
180         else
181             wrbuf_printf (b, "(unknown simple structure)");
182     }
183     else
184         wrbuf_puts(b, "(unknown structure)");
185 }
186
187 void yaz_rpnquery_to_wrbuf(WRBUF b, const Z_RPNQuery *rpn)
188 {
189     if (rpn->attributeSetId)
190     {
191         char oid_name_str[OID_STR_MAX];
192         const char *oid_name = yaz_oid_to_string_buf(rpn->attributeSetId,
193                                                      0, oid_name_str);
194         if (oid_name)
195             wrbuf_printf(b, "@attrset %s ", oid_name);
196     } 
197     yaz_rpnstructure_to_wrbuf(b, rpn->RPNStructure);
198     wrbuf_chop_right(b);
199 }
200
201 void yaz_query_to_wrbuf(WRBUF b, const Z_Query *q)
202 {
203     assert(q);
204     assert(b);
205     switch (q->which)
206     {
207     case Z_Query_type_1: 
208     case Z_Query_type_101:
209         wrbuf_printf(b,"RPN ");
210         yaz_rpnquery_to_wrbuf(b, q->u.type_1);
211         break;
212     case Z_Query_type_2:
213         wrbuf_printf(b, "CCL %.*s", q->u.type_2->len, q->u.type_2->buf);
214         break;
215     case Z_Query_type_100:
216         wrbuf_printf(b, "Z39.58 %.*s", q->u.type_100->len,
217                      q->u.type_100->buf);
218         break;
219     case Z_Query_type_104:
220         if (q->u.type_104->which == Z_External_CQL)
221             wrbuf_printf(b, "CQL %s", q->u.type_104->u.cql);
222         else
223             wrbuf_printf(b,"UNKNOWN type 104 query %d", q->u.type_104->which);
224     }
225 }
226
227 void yaz_scan_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt,
228                        const Odr_oid *attrbute_set)
229 {
230     /* should print attr set here */
231     wrbuf_printf(b, "RPN ");
232     yaz_apt_to_wrbuf(b, zapt);
233 }
234
235 void wrbuf_diags(WRBUF b, int num_diagnostics, Z_DiagRec **diags)
236 {
237     /* we only dump the first diag - that keeps the log cleaner. */
238     wrbuf_printf(b," ERROR ");
239     if (diags[0]->which != Z_DiagRec_defaultFormat)
240         wrbuf_printf(b,"(diag not in default format?)");
241     else
242     {
243         Z_DefaultDiagFormat *e=diags[0]->u.defaultFormat;
244         if (e->condition)
245             wrbuf_printf(b, ODR_INT_PRINTF " ",*e->condition);
246         else
247             wrbuf_printf(b, "?? ");
248         if ((e->which==Z_DefaultDiagFormat_v2Addinfo) && (e->u.v2Addinfo))
249             wrbuf_printf(b,"%s ",e->u.v2Addinfo);
250         else if ((e->which==Z_DefaultDiagFormat_v3Addinfo) && (e->u.v3Addinfo))
251             wrbuf_printf(b,"%s ",e->u.v3Addinfo);
252     }
253 }
254
255 /*
256  * Local variables:
257  * c-basic-offset: 4
258  * c-file-style: "Stroustrup"
259  * indent-tabs-mode: nil
260  * End:
261  * vim: shiftwidth=4 tabstop=8 expandtab
262  */
263