Split ICU wrapper library into several sources
[yaz-moved-to-github.git] / src / icu_casemap.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2009 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file
8  * \brief ICU character case (u_strToUpper, etc)
9  */
10
11 #if HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #if YAZ_HAVE_ICU
16 #include <yaz/xmalloc.h>
17
18 #include <yaz/icu_I18N.h>
19
20 #include <yaz/log.h>
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 struct icu_casemap
27 {
28     char action;
29 };
30
31 struct icu_casemap * icu_casemap_create(char action, UErrorCode *status)
32 {    
33     struct icu_casemap * casemap
34         = (struct icu_casemap *) xmalloc(sizeof(struct icu_casemap));
35     casemap->action = action;
36
37     switch (casemap->action)
38     {
39     case 'l':   
40     case 'L':   
41     case 'u':   
42     case 'U':   
43     case 't':  
44     case 'T':  
45     case 'f':  
46     case 'F':  
47         break;
48     default:
49         icu_casemap_destroy(casemap);
50         return 0;
51     }
52     return casemap;
53 }
54
55 void icu_casemap_destroy(struct icu_casemap * casemap)
56 {
57     xfree(casemap);
58 }
59
60 int icu_casemap_casemap(struct icu_casemap * casemap,
61                         struct icu_buf_utf16 * dest16,
62                         struct icu_buf_utf16 * src16,
63                         UErrorCode *status,
64                         const char *locale)
65 {
66     if(!casemap)
67         return 0;
68     
69     return icu_utf16_casemap(dest16, src16, locale,
70                              casemap->action, status);
71 }
72
73 int icu_utf16_casemap(struct icu_buf_utf16 * dest16,
74                       struct icu_buf_utf16 * src16,
75                       const char *locale, char action,
76                       UErrorCode *status)
77 {
78     int32_t dest16_len = 0;
79
80     if (!src16->utf16_len)
81     {           /* guarding for empty source string */
82         if (dest16->utf16)
83             dest16->utf16[0] = (UChar) 0;
84         dest16->utf16_len = 0;
85         return U_ZERO_ERROR;
86     }
87     
88     switch (action)
89     {
90     case 'l':    
91     case 'L':    
92         dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
93                                   src16->utf16, src16->utf16_len, 
94                                   locale, status);
95         break;
96     case 'u':    
97     case 'U':    
98         dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
99                                   src16->utf16, src16->utf16_len, 
100                                   locale, status);
101         break;
102     case 't':    
103     case 'T':    
104         dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
105                                   src16->utf16, src16->utf16_len,
106                                   0, locale, status);
107         break;
108     case 'f':    
109     case 'F':    
110         dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
111                                    src16->utf16, src16->utf16_len,
112                                    U_FOLD_CASE_DEFAULT, status);
113         break;
114         
115     default:
116         return U_UNSUPPORTED_ERROR;
117         break;
118     }
119
120     /* check for buffer overflow, resize and retry */
121     if (*status == U_BUFFER_OVERFLOW_ERROR
122         && dest16 != src16        /* do not resize if in-place conversion */
123         )
124     {
125         icu_buf_utf16_resize(dest16, dest16_len * 2);
126         *status = U_ZERO_ERROR;
127
128         switch (action) {    
129         case 'l':    
130         case 'L':    
131             dest16_len = u_strToLower(dest16->utf16, dest16->utf16_cap,
132                                       src16->utf16, src16->utf16_len, 
133                                       locale, status);
134             break;
135         case 'u':    
136         case 'U':    
137             dest16_len = u_strToUpper(dest16->utf16, dest16->utf16_cap,
138                                       src16->utf16, src16->utf16_len, 
139                                       locale, status);
140             break;
141         case 't':    
142         case 'T':    
143             dest16_len = u_strToTitle(dest16->utf16, dest16->utf16_cap,
144                                       src16->utf16, src16->utf16_len,
145                                       0, locale, status);
146             break;
147         case 'f':    
148         case 'F':    
149             dest16_len = u_strFoldCase(dest16->utf16, dest16->utf16_cap,
150                                        src16->utf16, src16->utf16_len,
151                                        U_FOLD_CASE_DEFAULT, status);
152             break;
153         
154         default:
155             return U_UNSUPPORTED_ERROR;
156             break;
157         }
158     }
159     
160     if (U_SUCCESS(*status)
161         && dest16_len <= dest16->utf16_cap)
162         dest16->utf16_len = dest16_len;
163     else
164     {
165         if (dest16->utf16)
166             dest16->utf16[0] = (UChar) 0;
167         dest16->utf16_len = 0;
168     }
169   
170     return *status;
171 }
172
173
174 #endif /* YAZ_HAVE_ICU */
175
176 /*
177  * Local variables:
178  * c-basic-offset: 4
179  * c-file-style: "Stroustrup"
180  * indent-tabs-mode: nil
181  * End:
182  * vim: shiftwidth=4 tabstop=8 expandtab
183  */
184