25951fe98a2e83d7971a32a19b56e6f1768a14e8
[pazpar2-moved-to-github.git] / src / icu_I18N.c
1 /* $Id: icu_I18N.c,v 1.3 2007-05-01 13:16:09 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 #if HAVE_CONFIG_H
23 #include "cconfig.h"
24 #endif
25
26 #define USE_TIMING 0
27 #if USE_TIMING
28 #include <yaz/timing.h>
29 #endif
30
31
32 #ifdef HAVE_ICU
33 #include "icu_I18N.h"
34
35 #include <yaz/log.h>
36
37 #include <string.h>
38
39 #include <unicode/ustring.h>  /* some more string fcns*/
40 #include <unicode/uchar.h>    /* char names           */
41
42
43 //#include <unicode/ustdio.h>
44 //#include <unicode/utypes.h>   /* Basic ICU data types */
45 #include <unicode/ucol.h> 
46 //#include <unicode/ucnv.h>     /* C   Converter API    */
47 //#include <unicode/uloc.h>
48 //#include <unicode/ubrk.h>
49 /* #include <unicode/unistr.h> */
50
51
52 // forward declarations for helper functions
53
54 int icu_check_status (UErrorCode status);
55
56 UChar* icu_utf16_from_utf8(UChar *utf16,
57                            int32_t utf16_cap,
58                            int32_t *utf16_len,
59                            const char *utf8);
60
61 UChar* icu_utf16_from_utf8n(UChar *utf16,
62                             int32_t utf16_cap,
63                             int32_t *utf16_len,
64                             const char *utf8, 
65                             size_t utf8_len);
66
67
68 char* icu_utf16_to_utf8(char *utf8,           
69                         size_t utf8_cap,
70                         size_t *utf8_len,
71                         const UChar *utf16, 
72                         int32_t utf16_len);
73
74
75 int32_t icu_utf16_casemap(UChar *dest16, int32_t dest16_cap,
76                           const UChar *src16, int32_t src16_len,
77                           const char *locale, char action);
78
79
80 // source code of all functions
81
82 int icu_check_status (UErrorCode status)
83 {
84   if(U_FAILURE(status))
85       yaz_log(YLOG_WARN, 
86               "ICU Error: %d %s\n", status, u_errorName(status));
87   return status;
88 }
89
90
91 UChar* icu_utf16_from_utf8(UChar *utf16,             
92                            int32_t utf16_cap,
93                            int32_t *utf16_len,
94                            const char *utf8)
95 {
96     size_t utf8_len = strlen(utf8);
97     return icu_utf16_from_utf8n(utf16, utf16_cap, utf16_len,
98                                   utf8, utf8_len);    
99 }
100
101
102 UChar* icu_utf16_from_utf8n(UChar *utf16,             
103                             int32_t utf16_cap,
104                             int32_t *utf16_len,
105                             const char *utf8, 
106                             size_t utf8_len)
107 {
108     UErrorCode status = U_ZERO_ERROR;
109     u_strFromUTF8(utf16, utf16_cap, utf16_len, utf8, (int32_t) utf8_len,
110                   &status);
111     if (U_ZERO_ERROR != icu_check_status(status))
112         return 0;
113     else
114         return utf16;
115 }
116
117
118 char* icu_utf16_to_utf8(char *utf8,           
119                         size_t utf8_cap,
120                         size_t *utf8_len,
121                         const UChar *utf16, 
122                         int32_t utf16_len)
123 {
124     UErrorCode status = U_ZERO_ERROR;
125     u_strToUTF8(utf8, (int32_t) utf8_cap, (int32_t *)utf8_len, 
126                 utf16, utf16_len, &status);
127     if (U_ZERO_ERROR != icu_check_status(status))
128         return 0;
129     else
130         return utf8;
131 }
132
133
134 int32_t icu_utf16_casemap(UChar *dest16, int32_t dest16_cap,
135                           const UChar *src16, int32_t src16_len,
136                           const char *locale, char action)
137 {
138     UErrorCode status = U_ZERO_ERROR;
139     int32_t dest16_len = 0;
140     
141     switch(action) {    
142     case 'l':    
143         dest16_len = u_strToLower(dest16, dest16_cap, src16, src16_len, 
144                                   locale, &status);
145         break;
146     case 'u':    
147         dest16_len = u_strToUpper(dest16, dest16_cap, src16, src16_len, 
148                                   locale, &status);
149         break;
150     case 't':    
151         dest16_len = u_strToTitle(dest16, dest16_cap, src16, src16_len,
152                                   0, locale, &status);
153         break;
154     case 'f':    
155         dest16_len = u_strFoldCase(dest16, dest16_cap, src16, src16_len,
156                                    U_FOLD_CASE_DEFAULT, &status);
157         break;
158         
159     default:
160         return 0;
161         break;
162     }
163
164     if (U_ZERO_ERROR != icu_check_status(status))
165         return 0;
166     else
167         return dest16_len;
168 }
169
170
171 char * icu_casemap(NMEM nmem, char *buf, size_t buf_cap, 
172                    size_t *dest8_len,  const char *src8,
173                    const char *locale, char action)
174 {
175     size_t src8_len = strlen(src8);
176     int32_t buf_len = 0;
177     char * dest8 = 0;
178     
179     if (dest8_len)
180         *dest8_len = 0;
181
182     if (!buf || !(buf_cap > 0) || !src8_len)
183         return 0;
184
185     // converting buf to utf16
186     buf = (char *)icu_utf16_from_utf8n((UChar *) buf, 
187                                        (int32_t) buf_cap, &buf_len,
188                                        src8, src8_len);
189     
190     // case mapping
191     buf_len = (size_t) icu_utf16_casemap((UChar *)buf, (int32_t) buf_cap,
192                                          (const UChar *)buf, (int32_t) buf_len,
193                                          locale, action);
194
195     // converting buf to utf8
196     buf = icu_utf16_to_utf8(buf, buf_cap, (size_t *) &buf_len,
197                             (const UChar *) buf, (int32_t) buf_len);
198
199     
200     // copying out to nmem
201     buf[buf_len] = '\0';
202
203     if(dest8_len)
204         *dest8_len = buf_len;
205
206     dest8 =  nmem_strdup(nmem, buf);
207     return dest8;
208 }
209
210
211 struct icu_termmap * icu_termmap_create(NMEM nmem)
212 {
213     struct icu_termmap *itmp =  nmem_malloc(nmem, sizeof(*itmp));
214     itmp->sort_len = 0;
215     itmp->sort_key = 0;
216     itmp->norm_term = 0;
217     itmp->disp_term = 0;
218     return itmp;
219 };
220
221 int icu_termmap_cmp(const void *vp1, const void *vp2)
222 {
223     struct icu_termmap *itmp1 = *(struct icu_termmap **) vp1;
224     struct icu_termmap *itmp2 = *(struct icu_termmap **) vp2;
225     int cmp = 0;
226
227 #if 0
228     size_t len = itmp1->sort_len;
229     // minimum sortkey length
230     if (itmp2->sort_len < len)
231         len = itmp2->sort_len;
232
233     cmp = strncmp(itmp1->sort_key, itmp2->sort_key, len);
234     
235     if (cmp == 0 && (itmp1->sort_len < itmp2->sort_len))
236         cmp = -1;
237     
238     if (cmp == 0 && (itmp1->sort_len > itmp2->sort_len))
239         cmp = 1;
240 #else   
241     cmp = strcmp(itmp1->sort_key, itmp2->sort_key);
242 #endif
243     return cmp;
244 }
245
246
247
248 char * icu_sortmap(NMEM nmem, char *buf, size_t buf_cap, 
249                    size_t *dest8_len,  const char *src8,
250                    const char *locale)
251 {
252     size_t src8_len = strlen(src8);
253     int32_t buf_len = 0;
254     char * dest8 = 0;
255     
256     if (dest8_len)
257         *dest8_len = 0;
258
259     if (!buf || !(buf_cap > 0) || !src8_len)
260         return 0;
261
262     // converting buf to utf16
263     buf = (char *)icu_utf16_from_utf8n((UChar *) buf, 
264                                        (int32_t) buf_cap, &buf_len,
265                                        src8, src8_len);
266     
267     // sort mapping
268     //buf_len = (size_t) icu_utf16_casemap((UChar *)buf, (int32_t) buf_cap,
269     //                                     (const UChar *)buf, (int32_t) buf_len,
270     //                                      locale, action);
271     
272     
273     {
274         UErrorCode status = U_ZERO_ERROR;
275
276         UCollator * coll = ucol_open (locale, &status);
277         if (U_ZERO_ERROR != icu_check_status(status))
278             buf_len = 0;
279
280         ucol_getSortKey(coll, (const UChar *) buf, (int32_t) buf_len, 
281                         (uint8_t *) buf, (int32_t) buf_cap);
282         
283         ucol_close(coll);
284     }
285     
286
287     // copying out to nmem
288     buf[buf_len] = '\0';
289
290     if(dest8_len)
291         *dest8_len = buf_len;
292
293     dest8 =  nmem_strdup(nmem, buf);
294     return dest8;
295 }
296
297
298
299
300 #endif // HAVE_ICU    
301
302
303
304
305 /*
306  * Local variables:
307  * c-basic-offset: 4
308  * indent-tabs-mode: nil
309  * End:
310  * vim: shiftwidth=4 tabstop=8 expandtab
311  */