704416056345e3bbe6294713cf7ec7fc58bbb1ce
[pazpar2-moved-to-github.git] / src / icu_I18N.c
1 /* $Id: icu_I18N.c,v 1.2 2007-05-01 08:17:05 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
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
212
213 #endif // HAVE_ICU    
214
215
216
217
218 /*
219  * Local variables:
220  * c-basic-offset: 4
221  * indent-tabs-mode: nil
222  * End:
223  * vim: shiftwidth=4 tabstop=8 expandtab
224  */