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