First ICU chain integration in relevance ranking of pazpar2.
[pazpar2-moved-to-github.git] / src / charsets.c
1 /* $Id: charsets.c,v 1.2 2007-05-23 14:44:18 marc Exp $
2    Copyright (c) 2006-2007, Index Data.
3
4 This file is part of Pazpar2.
5
6 Pazpar2 is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Pazpar2; see the file LICENSE.  If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20  */
21
22 /** \file charsets.c
23     \brief Pazpar2 Character set facilities
24 */
25
26 #if HAVE_CONFIG_H
27 #include "cconfig.h"
28 #endif
29
30 #include <yaz/xmalloc.h>
31 #include <yaz/wrbuf.h>
32 #include <yaz/log.h>
33 #include <ctype.h>
34 #include <assert.h>
35
36 #include "charsets.h"
37 //#include "config.h"
38 //#include "parameters.h"
39
40 #ifdef HAVE_ICU
41 #include "icu_I18N.h"
42 #endif // HAVE_ICU
43
44 /* charset handle */
45 struct pp2_charset_s {
46     const char *(*token_next_handler)(pp2_relevance_token_t prt);
47     /* other handlers will come as we see fit */
48 #ifdef HAVE_ICU
49     struct icu_chain * icu_chn;
50     UErrorCode icu_sts;
51 #endif // HAVE_ICU
52 };
53
54 static const char *pp2_relevance_token_a_to_z(pp2_relevance_token_t prt);
55
56 #ifdef HAVE_ICU
57 static const char *pp2_relevance_token_icu(pp2_relevance_token_t prt);
58 #endif // HAVE_ICU
59
60 /* tokenzier handle */
61 struct pp2_relevance_token_s {
62     const char *cp;     /* unnormalized buffer we're tokenizing */
63     pp2_charset_t pct;  /* our main charset handle (type+config) */
64     WRBUF norm_str;     /* normized string we return (temporarily) */
65 };
66
67 pp2_charset_t pp2_charset_create(struct icu_chain * icu_chn)
68 {
69     pp2_charset_t pct = xmalloc(sizeof(*pct));
70
71 #ifdef HAVE_ICU
72     if (icu_chn){
73         pct->icu_chn = icu_chn;
74         pct->icu_sts = U_ZERO_ERROR;
75         pct->token_next_handler = pp2_relevance_token_icu;
76     }
77     else {
78         pct->icu_chn = 0;
79         pct->token_next_handler = pp2_relevance_token_a_to_z;
80     }
81 #else // HAVE_ICU
82     pct->token_next_handler = pp2_relevance_token_a_to_z;
83 #endif // HAVE_ICU
84
85     return pct;
86 }
87
88 void pp2_charset_destroy(pp2_charset_t pct)
89 {
90     xfree(pct);
91 }
92
93 pp2_relevance_token_t pp2_relevance_tokenize(pp2_charset_t pct,
94                                              const char *buf)
95 {
96     pp2_relevance_token_t prt = xmalloc(sizeof(*prt));
97
98     assert(pct);
99
100 #ifdef HAVE_ICU
101     if (pct->icu_chn){
102         pct->icu_sts = U_ZERO_ERROR;
103         int ok = 0;
104         ok = icu_chain_assign_cstr(pct->icu_chn, buf, &pct->icu_sts);
105         printf("\nfield ok: %d '%s'\n", ok, buf);
106         //prt->cp = buf;
107         prt->pct = pct;
108         prt->norm_str = 0;
109         return prt;
110     }
111     else {
112 #endif // HAVE_ICU
113
114     prt->norm_str = wrbuf_alloc();
115     prt->cp = buf;
116     prt->pct = pct;
117     return prt;
118
119 #ifdef HAVE_ICU
120     }
121 #endif // HAVE_ICU
122 }
123
124
125 void pp2_relevance_token_destroy(pp2_relevance_token_t prt)
126 {
127     assert(prt);
128     if(prt->norm_str) 
129         wrbuf_destroy(prt->norm_str);
130     xfree(prt);
131 }
132
133 const char *pp2_relevance_token_next(pp2_relevance_token_t prt)
134 {
135     assert(prt);
136     return (prt->pct->token_next_handler)(prt);
137 }
138
139 #define raw_char(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 1 : -1)
140 /* original tokenizer with our tokenize interface, but we
141    add +1 to ensure no '\0' are in our string (except for EOF)
142 */
143 static const char *pp2_relevance_token_a_to_z(pp2_relevance_token_t prt)
144 {
145     const char *cp = prt->cp;
146     int c;
147
148     /* skip white space */
149     while (*cp && (c = raw_char(tolower(*cp))) < 0)
150         cp++;
151     if (*cp == '\0')
152     {
153         prt->cp = cp;
154         return 0;
155     }
156     /* now read the term itself */
157     wrbuf_rewind(prt->norm_str);
158     while (*cp && (c = raw_char(tolower(*cp))) >= 0)
159     {
160         wrbuf_putc(prt->norm_str, c);
161         cp++;
162     }
163     prt->cp = cp;
164     return wrbuf_cstr(prt->norm_str);
165 }
166
167
168 #ifdef HAVE_ICU
169 static const char *pp2_relevance_token_icu(pp2_relevance_token_t prt)
170 {
171     //&& U_SUCCESS(pct->icu_sts))
172     if (icu_chain_next_token(prt->pct->icu_chn, &prt->pct->icu_sts)){
173         printf("'%s' ",  icu_chain_get_norm(prt->pct->icu_chn)); 
174         if (U_FAILURE(prt->pct->icu_sts))
175         {
176             printf("ICU status failure\n "); 
177             return 0;
178         }
179             
180         return icu_chain_get_norm(prt->pct->icu_chn);
181     }
182     
183     return 0;
184 };
185 #endif // HAVE_ICU
186
187
188
189 /*
190  * Local variables:
191  * c-basic-offset: 4
192  * indent-tabs-mode: nil
193  * End:
194  * vim: shiftwidth=4 tabstop=8 expandtab
195  */