removed now superflous expwerimental file. useful contetn moved to icu_I18N.c
[pazpar2-moved-to-github.git] / src / icu_I18N.c
1 /* $Id: icu_I18N.c,v 1.7 2007-05-07 12:52:04 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 #include <stdlib.h>
39 #include <stdio.h>
40
41 #include <unicode/ustring.h>  /* some more string fcns*/
42 #include <unicode/uchar.h>    /* char names           */
43
44
45 //#include <unicode/ustdio.h>
46 //#include <unicode/utypes.h>   /* Basic ICU data types */
47 #include <unicode/ucol.h> 
48 //#include <unicode/ucnv.h>     /* C   Converter API    */
49 //#include <unicode/uloc.h>
50 //#include <unicode/ubrk.h>
51 /* #include <unicode/unistr.h> */
52
53
54
55
56 int icu_check_status (UErrorCode status)
57 {
58     //if(U_FAILURE(status))
59     if(!U_SUCCESS(status))
60         yaz_log(YLOG_WARN, 
61                 "ICU: %d %s\n", status, u_errorName(status));
62     return status;
63 }
64
65
66
67 struct icu_buf_utf16 * icu_buf_utf16_create(size_t capacity)
68 {
69     struct icu_buf_utf16 * buf16 
70         = (struct icu_buf_utf16 *) malloc(sizeof(struct icu_buf_utf16));
71
72     buf16->utf16 = 0;
73     buf16->utf16_len = 0;
74     buf16->utf16_cap = 0;
75
76     if (capacity > 0){
77         buf16->utf16 = (UChar *) malloc(sizeof(UChar) * capacity);
78         buf16->utf16[0] = (UChar) 0;
79         buf16->utf16_cap = capacity;
80     }
81     return buf16;
82 };
83
84
85 struct icu_buf_utf16 * icu_buf_utf16_resize(struct icu_buf_utf16 * buf16,
86                                             size_t capacity)
87 {
88     if (buf16){
89         if (capacity >  0){
90             if (0 == buf16->utf16)
91                 buf16->utf16 = (UChar *) malloc(sizeof(UChar) * capacity);
92             else
93                 buf16->utf16 
94                     = (UChar *) realloc(buf16->utf16, sizeof(UChar) * capacity);
95             buf16->utf16[0] = (UChar) 0;
96             buf16->utf16_len = 0;
97             buf16->utf16_cap = capacity;
98         } 
99         else { 
100             if (buf16->utf16)
101                 free(buf16->utf16);
102             buf16->utf16 = 0;
103             buf16->utf16_len = 0;
104             buf16->utf16_cap = 0;
105         }
106     }
107
108     return buf16;
109 };
110
111
112 void icu_buf_utf16_destroy(struct icu_buf_utf16 * buf16)
113 {
114     if (buf16){
115         if (buf16->utf16)
116             free(buf16->utf16);
117         free(buf16);
118     }
119 };
120
121
122
123
124
125
126 struct icu_buf_utf8 * icu_buf_utf8_create(size_t capacity)
127 {
128     struct icu_buf_utf8 * buf8 
129         = (struct icu_buf_utf8 *) malloc(sizeof(struct icu_buf_utf8));
130
131     buf8->utf8 = 0;
132     buf8->utf8_len = 0;
133     buf8->utf8_cap = 0;
134
135     if (capacity > 0){
136         buf8->utf8 = (uint8_t *) malloc(sizeof(uint8_t) * capacity);
137         buf8->utf8[0] = (uint8_t) 0;
138         buf8->utf8_cap = capacity;
139     }
140     return buf8;
141 };
142
143
144
145 struct icu_buf_utf8 * icu_buf_utf8_resize(struct icu_buf_utf8 * buf8,
146                                           size_t capacity)
147 {
148     if (buf8){
149         if (capacity >  0){
150             if (0 == buf8->utf8)
151                 buf8->utf8 = (uint8_t *) malloc(sizeof(uint8_t) * capacity);
152             else
153                 buf8->utf8 
154                     = (uint8_t *) realloc(buf8->utf8, sizeof(uint8_t) * capacity);
155             buf8->utf8[0] = (uint8_t) 0;
156             buf8->utf8_len = 0;
157             buf8->utf8_cap = capacity;
158         } 
159         else { 
160             if (buf8->utf8)
161                 free(buf8->utf8);
162             buf8->utf8 = 0;
163             buf8->utf8_len = 0;
164             buf8->utf8_cap = 0;
165         }
166     }
167
168     return buf8;
169 };
170
171
172
173 void icu_buf_utf8_destroy(struct icu_buf_utf8 * buf8)
174 {
175     if (buf8){
176         if (buf8->utf8)
177             free(buf8->utf8);
178         free(buf8);
179     }
180 };
181
182
183
184 UErrorCode icu_utf16_from_utf8(struct icu_buf_utf16 * dest16,
185                                struct icu_buf_utf8 * src8,
186                                UErrorCode * status)
187 {
188     int32_t utf16_len = 0;
189   
190     u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
191                   &utf16_len,
192                   (const char *) src8->utf8, src8->utf8_len, status);
193   
194     // check for buffer overflow, resize and retry
195     if (*status == U_BUFFER_OVERFLOW_ERROR
196         //|| dest16->utf16_len > dest16->utf16_cap
197         ){
198         icu_buf_utf16_resize(dest16, utf16_len * 2);
199         *status = U_ZERO_ERROR;
200         u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
201                       &utf16_len,
202                       (const char *) src8->utf8, src8->utf8_len, status);
203     }
204
205     //if (*status != U_BUFFER_OVERFLOW_ERROR
206     if (U_SUCCESS(*status)  
207         && utf16_len < dest16->utf16_cap)
208         dest16->utf16_len = utf16_len;
209     else {
210         dest16->utf16[0] = (UChar) 0;
211         dest16->utf16_len = 0;
212     }
213   
214     return *status;
215 };
216
217  
218
219 UErrorCode icu_utf16_from_utf8_cstr(struct icu_buf_utf16 * dest16,
220                                     const char * src8cstr,
221                                     UErrorCode * status)
222 {
223     size_t src8cstr_len = 0;
224     int32_t utf16_len = 0;
225
226     src8cstr_len = strlen(src8cstr);
227   
228     u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
229                   &utf16_len,
230                   src8cstr, src8cstr_len, status);
231   
232     // check for buffer overflow, resize and retry
233     if (*status == U_BUFFER_OVERFLOW_ERROR
234         //|| dest16->utf16_len > dest16->utf16_cap
235         ){
236         icu_buf_utf16_resize(dest16, utf16_len * 2);
237         *status = U_ZERO_ERROR;
238         u_strFromUTF8(dest16->utf16, dest16->utf16_cap,
239                       &utf16_len,
240                       src8cstr, src8cstr_len, status);
241     }
242
243     //  if (*status != U_BUFFER_OVERFLOW_ERROR
244     if (U_SUCCESS(*status)  
245         && utf16_len < dest16->utf16_cap)
246         dest16->utf16_len = utf16_len;
247     else {
248         dest16->utf16[0] = (UChar) 0;
249         dest16->utf16_len = 0;
250     }
251   
252     return *status;
253 };
254
255
256
257
258 UErrorCode icu_utf16_to_utf8(struct icu_buf_utf8 * dest8,
259                              struct icu_buf_utf16 * src16,
260                              UErrorCode * status)
261 {
262     int32_t utf8_len = 0;
263   
264     u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
265                 &utf8_len,
266                 src16->utf16, src16->utf16_len, status);
267   
268     // check for buffer overflow, resize and retry
269     if (*status == U_BUFFER_OVERFLOW_ERROR
270         //|| dest8->utf8_len > dest8->utf8_cap
271         ){
272         icu_buf_utf8_resize(dest8, utf8_len * 2);
273         *status = U_ZERO_ERROR;
274         u_strToUTF8((char *) dest8->utf8, dest8->utf8_cap,
275                     &utf8_len,
276                     src16->utf16, src16->utf16_len, status);
277
278     }
279
280     //if (*status != U_BUFFER_OVERFLOW_ERROR
281     if (U_SUCCESS(*status)  
282         && utf8_len < dest8->utf8_cap)
283         dest8->utf8_len = utf8_len;
284     else {
285         dest8->utf8[0] = (uint8_t) 0;
286         dest8->utf8_len = 0;
287     }
288   
289     return *status;
290 };
291
292
293
294 int icu_utf16_casemap(struct icu_buf_utf16 * dest16,
295                       struct icu_buf_utf16 * src16,
296                       const char *locale, char action,
297                       UErrorCode *status)
298 {
299     int32_t dest16_len = 0;
300     
301     switch(action) {    
302     case 'l':    
303         dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
304                                   src16->utf16, src16->utf16_len, 
305                                   locale, status);
306         break;
307     case 'u':    
308         dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
309                                   src16->utf16, src16->utf16_len, 
310                                   locale, status);
311         break;
312     case 't':    
313         dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
314                                   src16->utf16, src16->utf16_len,
315                                   0, locale, status);
316         break;
317     case 'f':    
318         dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
319                                    src16->utf16, src16->utf16_len,
320                                    U_FOLD_CASE_DEFAULT, status);
321         break;
322         
323     default:
324         return U_UNSUPPORTED_ERROR;
325         break;
326     }
327
328     // check for buffer overflow, resize and retry
329     if (*status == U_BUFFER_OVERFLOW_ERROR
330         //|| dest16_len > dest16->utf16_cap
331         ){
332         icu_buf_utf16_resize(dest16, dest16_len * 2);
333         *status = U_ZERO_ERROR;
334
335     
336         switch(action) {    
337         case 'l':    
338             dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
339                                       src16->utf16, src16->utf16_len, 
340                                       locale, status);
341             break;
342         case 'u':    
343             dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
344                                       src16->utf16, src16->utf16_len, 
345                                       locale, status);
346             break;
347         case 't':    
348             dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
349                                       src16->utf16, src16->utf16_len,
350                                       0, locale, status);
351             break;
352         case 'f':    
353             dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
354                                        src16->utf16, src16->utf16_len,
355                                        U_FOLD_CASE_DEFAULT, status);
356             break;
357         
358         default:
359             return U_UNSUPPORTED_ERROR;
360             break;
361         }
362     }
363     
364     if (U_SUCCESS(*status)
365         && dest16_len < dest16->utf16_cap)
366         dest16->utf16_len = dest16_len;
367     else {
368         dest16->utf16[0] = (UChar) 0;
369         dest16->utf16_len = 0;
370     }
371   
372     return *status;
373 };
374
375
376
377 UErrorCode icu_sortkey8_from_utf16(UCollator *coll,
378                                    struct icu_buf_utf8 * dest8, 
379                                    struct icu_buf_utf16 * src16,
380                                    UErrorCode * status)
381
382   
383     int32_t sortkey_len = 0;
384
385     sortkey_len = ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
386                                   dest8->utf8, dest8->utf8_cap);
387
388     // check for buffer overflow, resize and retry
389     if (sortkey_len > dest8->utf8_cap) {
390         icu_buf_utf8_resize(dest8, sortkey_len * 2);
391         sortkey_len = ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
392                                       dest8->utf8, dest8->utf8_cap);
393     }
394
395     if (U_SUCCESS(*status)
396         && sortkey_len > 0)
397         dest8->utf8_len = sortkey_len;
398     else {
399         dest8->utf8[0] = (UChar) 0;
400         dest8->utf8_len = 0;
401     }
402
403     return *status;
404 };
405
406
407
408
409 #endif // HAVE_ICU    
410
411
412
413
414 /*
415  * Local variables:
416  * c-basic-offset: 4
417  * indent-tabs-mode: nil
418  * End:
419  * vim: shiftwidth=4 tabstop=8 expandtab
420  */