Introducing namespace yazpp_1 for all YAZ++ functions. This will
[yazpp-moved-to-github.git] / src / yaz-z-query.cpp
1 /*
2  * Copyright (c) 1998-2003, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-z-query.cpp,v 1.16 2005-06-02 06:40:21 adam Exp $
6  */
7
8 #include <yaz++/z-query.h>
9 #include <yaz/pquery.h>
10
11 using namespace yazpp_1;
12
13 Yaz_Z_Query::Yaz_Z_Query()
14 {
15     odr_encode = odr_createmem (ODR_ENCODE);
16     odr_decode = odr_createmem (ODR_DECODE);
17     odr_print = odr_createmem (ODR_PRINT);
18 }
19
20 int Yaz_Z_Query::set_rpn (const char *rpn)
21 {
22     m_buf = 0;
23     odr_reset (odr_encode);
24     Z_Query *query = (Z_Query*) odr_malloc (odr_encode, sizeof(*query));
25     query->which = Z_Query_type_1;
26     query->u.type_1 = p_query_rpn (odr_encode, PROTO_Z3950, rpn);
27     if (!query->u.type_1)
28         return -1;
29     if (!z_Query (odr_encode, &query, 0, 0))
30         return -1;
31     // z_Query(odr_print, &query, 0, 0);
32     m_buf = odr_getbuf (odr_encode, &m_len, 0);
33     return m_len;
34 }
35
36 void Yaz_Z_Query::set_Z_Query(Z_Query *z_query)
37 {
38     m_buf = 0;
39     odr_reset (odr_encode);
40     if (!z_Query (odr_encode, &z_query, 0, 0))
41         return;
42     m_buf = odr_getbuf (odr_encode, &m_len, 0);
43 }
44
45 Yaz_Z_Query::~Yaz_Z_Query()
46 {
47     odr_destroy (odr_encode);
48     odr_destroy (odr_decode);
49     odr_destroy (odr_print);
50 }
51
52 Z_Query *Yaz_Z_Query::get_Z_Query ()
53 {
54     Z_Query *query;
55     if (!m_buf)
56         return 0;
57     odr_reset(odr_decode);
58     odr_setbuf(odr_decode, m_buf, m_len, 0);
59     if (!z_Query(odr_decode, &query, 0, 0))
60         return 0;
61     return query;
62 }
63
64 void Yaz_Z_Query::print(char *str, int len)
65 {
66     Z_Query *query;
67     *str = 0;
68     if (!m_buf)
69         return;
70     odr_setbuf (odr_decode, m_buf, m_len, 0);
71     if (!z_Query(odr_decode, &query, 0, 0))
72         return;
73     WRBUF wbuf = zquery2pquery(query);
74     if (wbuf)
75     {
76         if (wrbuf_len(wbuf) > len-1)
77         {
78             memcpy(str, wrbuf_buf(wbuf), len-1);
79             str[len-1] = '\0';
80         }
81         else
82             strcpy(str, wrbuf_buf(wbuf));
83         wrbuf_free(wbuf,1);
84     }
85     odr_reset(odr_decode);
86 }
87
88 int Yaz_Z_Query::match(Yaz_Z_Query *other)
89 {
90     if (m_len != other->m_len)
91         return 0;
92     if (!m_buf || !other->m_buf)
93         return 0;
94     if (memcmp(m_buf, other->m_buf, m_len))
95         return 0;
96     return 1;
97 }
98
99 void Yaz_Z_Query::oid2str(Odr_oid *o, WRBUF buf)
100 {
101     for (; *o >= 0; o++) {
102         char ibuf[16];
103         sprintf(ibuf, "%d", *o);
104         wrbuf_puts(buf, ibuf);
105         if (o[1] > 0)
106             wrbuf_putc(buf, '.');
107     }
108 }
109
110 void Yaz_Z_Query::pr_term(WRBUF wbuf, char *buf, int len)
111 {
112     int i;
113     wrbuf_putc(wbuf, '"');
114     for (i = 0; i<len; i++)
115     {
116         int ch = buf[i];
117         if (ch == '"')
118             wrbuf_putc(wbuf, '\\');
119         wrbuf_putc(wbuf, ch);
120     }
121     wrbuf_puts(wbuf, "\" ");
122 }
123
124 int Yaz_Z_Query::rpn2pquery(Z_RPNStructure *s, WRBUF buf)
125 {
126     if (s->which == Z_RPNStructure_simple)
127     {
128         Z_Operand *o = s->u.simple;
129         
130         if (o->which == Z_Operand_APT) 
131         {
132             Z_AttributesPlusTerm *at = s->u.simple->u.attributesPlusTerm;
133             if (at->attributes) {
134                 int i;
135                 for (i = 0; i < at->attributes->num_attributes; i++) {
136                     wrbuf_puts(buf, "@attr ");
137                     if (at->attributes->attributes[i]->attributeSet) {
138                         oid2str(at->attributes->attributes[i]->attributeSet, buf);
139                         wrbuf_putc(buf, ' ');
140                     }
141                     wrbuf_printf(buf, "%d=", *at->attributes->attributes[i]->attributeType);
142                     wrbuf_printf(buf, "%d ", *at->attributes->attributes[i]->value.numeric);
143                 }
144             }
145             if (at->term->which == Z_Term_general)
146             {
147                 pr_term(buf, (char*) at->term->u.general->buf,
148                         at->term->u.general->len);
149             }
150             else if (at->term->which == Z_Term_characterString)
151             {
152                 wrbuf_puts(buf, "@term string ");
153                 pr_term(buf, at->term->u.characterString,
154                         strlen(at->term->u.characterString));
155
156             }
157         }
158         else if (o->which == Z_Operand_resultSetId)
159         {
160             wrbuf_printf(buf, "@set %s ", o->u.resultSetId);
161         }
162     }
163     else if (s->which == Z_RPNStructure_complex)
164     {
165         Z_Complex *c = s->u.complex;
166         
167         switch (c->roperator->which) {
168         case Z_Operator_and: wrbuf_puts(buf, "@and "); break;
169         case Z_Operator_or: wrbuf_puts(buf, "@or "); break;
170         case Z_Operator_and_not: wrbuf_puts(buf, "@not "); break;
171         case Z_Operator_prox: wrbuf_puts(buf, "@prox "); break;
172         default: wrbuf_puts(buf, "@unknown ");
173         }
174         if (!rpn2pquery(c->s1, buf))
175             return 0;
176         if (!rpn2pquery(c->s2, buf))
177             return 0;
178     }
179     return 1;
180 }
181
182 WRBUF Yaz_Z_Query::zquery2pquery(Z_Query *q)
183 {
184     if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101) 
185         return 0;
186     WRBUF buf = wrbuf_alloc();
187     if (q->u.type_1->attributeSetId) {
188         /* Output attribute set ID */
189         wrbuf_puts(buf, "@attrset ");
190         oid2str(q->u.type_1->attributeSetId, buf);
191         wrbuf_putc(buf, ' ');
192     }
193     return rpn2pquery(q->u.type_1->RPNStructure, buf) ? buf : 0;
194 }
195
196