tweaking, still no good results with danish sorting
[pazpar2-moved-to-github.git] / src / icu_I18N.c
1 /* $Id: icu_I18N.c,v 1.4 2007-05-02 14:01:36 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     if(!U_SUCCESS(status))
86       yaz_log(YLOG_WARN, 
87               "ICU: %d %s\n", status, u_errorName(status));
88   return status;
89 }
90
91
92 UChar* icu_utf16_from_utf8(UChar *utf16,             
93                            int32_t utf16_cap,
94                            int32_t *utf16_len,
95                            const char *utf8)
96 {
97     size_t utf8_len = strlen(utf8);
98     return icu_utf16_from_utf8n(utf16, utf16_cap, utf16_len,
99                                   utf8, utf8_len);    
100 }
101
102
103 UChar* icu_utf16_from_utf8n(UChar *utf16,             
104                             int32_t utf16_cap,
105                             int32_t *utf16_len,
106                             const char *utf8, 
107                             size_t utf8_len)
108 {
109     UErrorCode status = U_ZERO_ERROR;
110     u_strFromUTF8(utf16, utf16_cap, utf16_len, utf8, (int32_t) utf8_len,
111                   &status);
112     if (U_ZERO_ERROR != icu_check_status(status))
113         return 0;
114     else
115         return utf16;
116 }
117
118
119 char* icu_utf16_to_utf8(char *utf8,           
120                         size_t utf8_cap,
121                         size_t *utf8_len,
122                         const UChar *utf16, 
123                         int32_t utf16_len)
124 {
125     UErrorCode status = U_ZERO_ERROR;
126     u_strToUTF8(utf8, (int32_t) utf8_cap, (int32_t *)utf8_len, 
127                 utf16, utf16_len, &status);
128     if (U_ZERO_ERROR != icu_check_status(status))
129         return 0;
130     else
131         return utf8;
132 }
133
134
135 int32_t icu_utf16_casemap(UChar *dest16, int32_t dest16_cap,
136                           const UChar *src16, int32_t src16_len,
137                           const char *locale, char action)
138 {
139     UErrorCode status = U_ZERO_ERROR;
140     int32_t dest16_len = 0;
141     
142     switch(action) {    
143     case 'l':    
144         dest16_len = u_strToLower(dest16, dest16_cap, src16, src16_len, 
145                                   locale, &status);
146         break;
147     case 'u':    
148         dest16_len = u_strToUpper(dest16, dest16_cap, src16, src16_len, 
149                                   locale, &status);
150         break;
151     case 't':    
152         dest16_len = u_strToTitle(dest16, dest16_cap, src16, src16_len,
153                                   0, locale, &status);
154         break;
155     case 'f':    
156         dest16_len = u_strFoldCase(dest16, dest16_cap, src16, src16_len,
157                                    U_FOLD_CASE_DEFAULT, &status);
158         break;
159         
160     default:
161         return 0;
162         break;
163     }
164
165     if (U_ZERO_ERROR != icu_check_status(status))
166         return 0;
167     else
168         return dest16_len;
169 }
170
171
172 char * icu_casemap(NMEM nmem, char *buf, size_t buf_cap, 
173                    size_t *dest8_len,  const char *src8,
174                    const char *locale, char action)
175 {
176     size_t src8_len = strlen(src8);
177     int32_t buf_len = 0;
178     char * dest8 = 0;
179     
180     if (dest8_len)
181         *dest8_len = 0;
182
183     if (!buf || !(buf_cap > 0) || !src8_len)
184         return 0;
185
186     // converting buf to utf16
187     buf = (char *)icu_utf16_from_utf8n((UChar *) buf, 
188                                        (int32_t) buf_cap, &buf_len,
189                                        src8, src8_len);
190     
191     // case mapping
192     buf_len = (size_t) icu_utf16_casemap((UChar *)buf, (int32_t) buf_cap,
193                                          (const UChar *)buf, (int32_t) buf_len,
194                                          locale, action);
195
196     // converting buf to utf8
197     buf = icu_utf16_to_utf8(buf, buf_cap, (size_t *) &buf_len,
198                             (const UChar *) buf, (int32_t) buf_len);
199
200     
201     // copying out to nmem
202     buf[buf_len] = '\0';
203
204     if(dest8_len)
205         *dest8_len = buf_len;
206
207     dest8 =  nmem_strdup(nmem, buf);
208     return dest8;
209 }
210
211
212 struct icu_termmap * icu_termmap_create(NMEM nmem)
213 {
214     struct icu_termmap *itmp =  nmem_malloc(nmem, sizeof(*itmp));
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
226     return strcmp(itmp1->sort_key, itmp2->sort_key);
227 }
228
229
230
231 char * icu_sortmap(NMEM nmem, char *buf, size_t buf_cap, 
232                    size_t *dest8_len,  const char *src8,
233                    const char *locale)
234 {
235     size_t src8_len = strlen(src8);
236     int32_t buf_len = 0;
237     char * dest8 = 0;
238     
239     if (dest8_len)
240         *dest8_len = 0;
241
242     if (!buf || !(buf_cap > 0) || !src8_len)
243         return 0;
244
245     // converting buf to utf16
246     buf = (char *)icu_utf16_from_utf8n((UChar *) buf, 
247                                        (int32_t) buf_cap, &buf_len,
248                                        src8, src8_len);
249     
250     // sort mapping
251     //buf_len = (size_t) icu_utf16_casemap((UChar *)buf, (int32_t) buf_cap,
252     //                                     (const UChar *)buf, (int32_t) buf_len,
253     //                                      locale, action);
254     
255     
256     {
257         UErrorCode status = U_ZERO_ERROR;
258
259         UCollator * coll = ucol_open (locale, &status);
260         if (U_ZERO_ERROR != icu_check_status(status))
261             buf_len = 0;
262
263         ucol_getSortKey(coll, (const UChar *) buf, (int32_t) buf_len, 
264                         (uint8_t *) buf, (int32_t) buf_cap);
265         
266         ucol_close(coll);
267     }
268     
269
270     // copying out to nmem
271     buf[buf_len] = '\0';
272
273     if(dest8_len)
274         *dest8_len = buf_len;
275
276     dest8 =  nmem_strdup(nmem, buf);
277     return dest8;
278 }
279
280
281
282
283 #endif // HAVE_ICU    
284
285
286
287
288 /*
289  * Local variables:
290  * c-basic-offset: 4
291  * indent-tabs-mode: nil
292  * End:
293  * vim: shiftwidth=4 tabstop=8 expandtab
294  */