Code updates which makes things compile as C++. Mostly type casts were
[yaz-moved-to-github.git] / src / ccl_stop_words.c
1 /*
2  * Copyright (c) 1995, the EUROPAGATE consortium (see below).
3  *
4  * The EUROPAGATE consortium members are:
5  *
6  *    University College Dublin
7  *    Danmarks Teknologiske Videnscenter
8  *    An Chomhairle Leabharlanna
9  *    Consejo Superior de Investigaciones Cientificas
10  *
11  * Permission to use, copy, modify, distribute, and sell this software and
12  * its documentation, in whole or in part, for any purpose, is hereby granted,
13  * provided that:
14  *
15  * 1. This copyright and permission notice appear in all copies of the
16  * software and its documentation. Notices of copyright or attribution
17  * which appear at the beginning of any file must remain unchanged.
18  *
19  * 2. The names of EUROPAGATE or the project partners may not be used to
20  * endorse or promote products derived from this software without specific
21  * prior written permission.
22  *
23  * 3. Users of this software (implementors and gateway operators) agree to
24  * inform the EUROPAGATE consortium of their use of the software. This
25  * information will be used to evaluate the EUROPAGATE project and the
26  * software, and to plan further developments. The consortium may use
27  * the information in later publications.
28  * 
29  * 4. Users of this software agree to make their best efforts, when
30  * documenting their use of the software, to acknowledge the EUROPAGATE
31  * consortium, and the role played by the software in their work.
32  *
33  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
34  * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
35  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
36  * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE
37  * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
38  * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
39  * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
40  * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
41  * USE OR PERFORMANCE OF THIS SOFTWARE.
42  *
43  */
44
45 /** 
46  * \file ccl_stop_words.c
47  * \brief Removes stop words from terms in RPN tree
48  */
49
50 #include <stdio.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <yaz/ccl.h>
54 #include <yaz/nmem.h>
55
56 struct ccl_stop_info {
57     char *qualname;
58     char *term;
59     struct ccl_stop_info *next;
60 };
61
62 struct ccl_stop_words {
63     char *blank_chars;
64     NMEM nmem; /* memory for removed items */
65     struct ccl_stop_info *removed_items;
66 };
67     
68 static void append_removed_item(ccl_stop_words_t csw,
69                                 const char *qname,
70                                 const char *t, size_t len)
71 {
72     struct ccl_stop_info *csi = (struct ccl_stop_info *)
73         nmem_malloc(csw->nmem, sizeof(*csi));
74     struct ccl_stop_info **csip = &csw->removed_items;
75     if (qname)
76         csi->qualname = nmem_strdup(csw->nmem, qname);
77     else
78         csi->qualname = 0;
79
80     csi->term = (char *) nmem_malloc(csw->nmem, len+1);
81     memcpy(csi->term, t, len);
82     csi->term[len] = '\0';
83     csi->next = 0;
84
85     while (*csip)
86         csip = &(*csip)->next;
87     
88     *csip = csi;
89 }
90
91 ccl_stop_words_t ccl_stop_words_create(void)
92 {
93     NMEM nmem = nmem_create();
94     ccl_stop_words_t csw = (ccl_stop_words_t) xmalloc(sizeof(*csw));
95     csw->nmem = nmem;
96     csw->removed_items = 0;
97     csw->blank_chars = xstrdup(" \r\n\t");
98     return csw;
99 }
100
101 void ccl_stop_words_destroy(ccl_stop_words_t csw)
102 {
103     if (csw)
104     {
105         nmem_destroy(csw->nmem);
106         xfree(csw->blank_chars);
107         xfree(csw);
108     }
109 }
110
111 struct ccl_rpn_node *ccl_remove_stop_r(ccl_stop_words_t csw,
112                                        CCL_bibset bibset,
113                                        struct ccl_rpn_node *p)
114 {
115     struct ccl_rpn_node *left, *right;
116     switch (p->kind)
117     {
118     case CCL_RPN_AND:
119     case CCL_RPN_OR:
120     case CCL_RPN_NOT:
121     case CCL_RPN_PROX:
122         left = ccl_remove_stop_r(csw, bibset, p->u.p[0]);
123         right = ccl_remove_stop_r(csw, bibset, p->u.p[1]);
124         if (!left || !right)
125         {
126             /* we must delete our binary node and return child (if any) */
127             p->u.p[0] = 0;
128             p->u.p[1] = 0;
129             ccl_rpn_delete(p);
130             if (left)
131                 return left;
132             else
133                 return right;
134         }
135         break;
136     case CCL_RPN_SET:
137         break;
138     case CCL_RPN_TERM:
139         if (p->u.t.term)
140         {
141             int found = 1;
142             while (found)
143             {
144                 char *cp = p->u.t.term;
145                 found = 0;
146                 while (1)
147                 {
148                     while (*cp && strchr(csw->blank_chars, *cp))
149                         cp++;
150                     if (!*cp)
151                         break;
152                     else
153                     {
154                         char *cp0 = cp;
155                         while (*cp && !strchr(csw->blank_chars, *cp))
156                             cp++;
157                         if (cp != cp0)
158                         {
159                             size_t len = cp - cp0;
160                             if (ccl_search_stop(bibset, p->u.t.qual,
161                                                 cp0, len))
162                             {
163                                 append_removed_item(csw, p->u.t.qual,
164                                                     cp0, len);
165                                 while (*cp && strchr(csw->blank_chars, *cp))
166                                     cp++;
167                                 memmove(cp0, cp, strlen(cp)+1);
168                                 found = 1;
169                                 break;
170                             }
171                         }
172                     }
173                 }
174             }
175         }
176         /* chop right blanks .. and see if term it gets empty */
177         if (p->u.t.term && csw->removed_items)
178         {
179             char *cp = p->u.t.term + strlen(p->u.t.term);
180             while (1)
181             {
182                 if (cp == p->u.t.term)
183                 {
184                     /* term is empty / blank */
185                     ccl_rpn_delete(p);
186                     return 0;
187                 }
188                 if (!strchr(csw->blank_chars, cp[-1]))
189                     break;
190                 /* chop right */
191                 cp[-1] = 0;
192                 --cp;
193             }
194         }
195         break;
196     }
197     return p;
198 }
199
200 int ccl_stop_words_tree(ccl_stop_words_t csw,
201                         CCL_bibset bibset, struct ccl_rpn_node **t)
202 {
203     struct ccl_rpn_node *r;
204     
205     /* remove list items */
206     nmem_reset(csw->nmem);
207     csw->removed_items = 0;
208     
209     r = ccl_remove_stop_r(csw, bibset, *t);
210     *t = r;
211     if (csw->removed_items)
212         return 1;
213     return 0;
214 }
215
216 int ccl_stop_words_info(ccl_stop_words_t csw, int idx,
217                         const char **qualname, const char **term)
218 {
219     struct ccl_stop_info *csi = csw->removed_items;
220     int i = 0;
221     while (csi && i < idx)
222     {
223         csi = csi->next;
224         i++;
225     }
226     if (csi)
227     {
228         *qualname = csi->qualname;
229         *term = csi->term;
230         return 1;
231     }
232     return 0;
233 }
234
235 /*
236  * Local variables:
237  * c-basic-offset: 4
238  * indent-tabs-mode: nil
239  * End:
240  * vim: shiftwidth=4 tabstop=8 expandtab
241  */
242