checked in test for ICU uppercase lowercase, title and foldcase char mapping
[pazpar2-moved-to-github.git] / src / icu_I18N.c
1 /* $Id: icu_I18N.c,v 1.1 2007-04-30 13:56:52 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 <unicode/ustring.h>  /* some more string fcns*/
39
40 //#include <unicode/ustdio.h>
41 //#include <unicode/utypes.h>   /* Basic ICU data types */
42 //#include <unicode/ucol.h> 
43 //#include <unicode/ucnv.h>     /* C   Converter API    */
44 //#include <unicode/uchar.h>    /* char names           */
45 //#include <unicode/uloc.h>
46 //#include <unicode/ubrk.h>
47 /* #include <unicode/unistr.h> */
48
49
50
51 int icu_check_status (UErrorCode status)
52 {
53   if(U_FAILURE(status))
54       yaz_log(YLOG_WARN, 
55               "ICU Error: %d %s\n", status, u_errorName(status));
56   return status;
57 }
58
59
60 UChar* icu_utf16_from_utf8(UChar *utf16,             
61                            int32_t utf16_cap,
62                            int32_t *utf16_len,
63                            const char *utf8)
64 {
65     size_t utf8_len = strlen(utf8);
66     return icu_utf16_from_utf8n(utf16, utf16_cap, utf16_len,
67                                   utf8, utf8_len);    
68 }
69
70
71 UChar* icu_utf16_from_utf8n(UChar *utf16,             
72                             int32_t utf16_cap,
73                             int32_t *utf16_len,
74                             const char *utf8, 
75                             size_t utf8_len)
76 {
77     UErrorCode status = U_ZERO_ERROR;
78     u_strFromUTF8(utf16, utf16_cap, utf16_len, utf8, (int32_t) utf8_len,
79                   &status);
80     if (U_ZERO_ERROR != icu_check_status(status))
81         return 0;
82     else
83         return utf16;
84 }
85
86
87 char* icu_utf16_to_utf8(char *utf8,           
88                         size_t utf8_cap,
89                         size_t *utf8_len,
90                         const UChar *utf16, 
91                         int32_t utf16_len)
92 {
93     UErrorCode status = U_ZERO_ERROR;
94     u_strToUTF8(utf8, (int32_t) utf8_cap, (int32_t *)utf8_len, 
95                 utf16, utf16_len, &status);
96     if (U_ZERO_ERROR != icu_check_status(status))
97         return 0;
98     else
99         return utf8;
100 }
101
102
103 int32_t icu_utf16_casemap(UChar *dest16, int32_t dest16_cap,
104                           const UChar *src16, int32_t src16_len,
105                           const char *locale, char action)
106 {
107     UErrorCode status = U_ZERO_ERROR;
108     int32_t dest16_len = 0;
109     
110     switch(action) {    
111     case 'l':    
112         dest16_len = u_strToLower(dest16, dest16_cap, src16, src16_len, 
113                                   locale, &status);
114         break;
115     case 'u':    
116         dest16_len = u_strToUpper(dest16, dest16_cap, src16, src16_len, 
117                                   locale, &status);
118         break;
119     case 't':    
120         dest16_len = u_strToTitle(dest16, dest16_cap, src16, src16_len,
121                                   0, locale, &status);
122         break;
123     case 'f':    
124         dest16_len = u_strFoldCase(dest16, dest16_cap, src16, src16_len,
125                                    U_FOLD_CASE_DEFAULT, &status);
126         break;
127         
128     default:
129         return 0;
130         break;
131     }
132
133     if (U_ZERO_ERROR != icu_check_status(status))
134         return 0;
135     else
136         return dest16_len;
137 }
138
139
140 char * icu_casemap(NMEM nmem, char *buf, size_t buf_cap, 
141                    size_t *dest8_len,  const char *src8,
142                    const char *locale, char action)
143 {
144     size_t src8_len = strlen(src8);
145     int32_t buf_len = 0;
146     char * dest8 = 0;
147     
148     if (dest8_len)
149         *dest8_len = 0;
150
151     if (!buf || !(buf_cap > 0) || !src8_len)
152         return 0;
153
154     // converting buf to utf16
155     buf = (char *)icu_utf16_from_utf8n((UChar *) buf, 
156                                        (int32_t) buf_cap, &buf_len,
157                                        src8, src8_len);
158     
159     // case mapping
160     buf_len = (size_t) icu_utf16_casemap((UChar *)buf, (int32_t) buf_cap,
161                                          (const UChar *)buf, (int32_t) buf_len,
162                                          locale, action);
163
164     // converting buf to utf8
165     buf = icu_utf16_to_utf8(buf, buf_cap, (size_t *) &buf_len,
166                             (const UChar *) buf, (int32_t) buf_len);
167
168     
169     // copying out to nmem
170     buf[buf_len] = '\0';
171
172     if(dest8_len)
173         *dest8_len = buf_len;
174
175     dest8 =  nmem_strdup(nmem, buf);
176     return dest8;
177 }
178
179
180
181
182 #endif // HAVE_ICU    
183
184
185
186
187 /*
188  * Local variables:
189  * c-basic-offset: 4
190  * indent-tabs-mode: nil
191  * End:
192  * vim: shiftwidth=4 tabstop=8 expandtab
193  */