dbba9b90604c76e019b4ba6294dfeeabfd60f90c
[pazpar2-moved-to-github.git] / src / icu_bug_2.c
1 // Make command on debian 64 bit testing dist  
2 /*
3 gcc -g -Wall `icu-config --cppflags`  `icu-config --ldflags` -o icu_bug icu_bug.c
4 snatched from http://www.icu-project.org/userguide/Collate_API.html 
5 and corrected for compile errors
6 added a struct icu_termmap such that I actually can see the output
7 */
8
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12
13 #include <unicode/ustring.h>  /* some more string fcns*/
14 #include <unicode/uchar.h>    /* char names           */
15
16
17 //#include <unicode/ustdio.h>
18 //#include <unicode/utypes.h>   /* Basic ICU data types */
19 #include <unicode/ucol.h> 
20 //#include <unicode/ucnv.h>     /* C   Converter API    */
21 //#include <unicode/uloc.h>
22 //#include <unicode/ubrk.h>
23 //#include <unicode/unistr.h> 
24
25
26 #define MAX_KEY_SIZE 256
27 //#define MAX_BUFFER_SIZE 10000
28 //#define MAX_LIST_LENGTH 5
29  
30
31 struct icu_buf_utf16
32 {
33   UChar * utf16;
34   int32_t utf16_len;
35   int32_t utf16_cap;
36 };
37
38
39 struct icu_buf_utf16 * icu_buf_utf16_create(size_t capacity)
40 {
41   struct icu_buf_utf16 * buf16 
42     = (struct icu_buf_utf16 *) malloc(sizeof(struct icu_buf_utf16));
43
44   buf16->utf16 = 0;
45   buf16->utf16_len = 0;
46   buf16->utf16_cap = 0;
47
48   if (capacity > 0){
49     buf16->utf16 = (UChar *) malloc(sizeof(UChar) * capacity);
50     buf16->utf16_cap = capacity;
51   }
52   return buf16;
53 };
54
55
56 struct icu_buf_utf16 * icu_buf_utf16_resize(struct icu_buf_utf16 * buf16,
57                                             size_t capacity)
58 {
59   printf("buf16 resize: %d\n", (int)capacity);
60   if (buf16){
61     if (capacity >  0){
62       if (0 == buf16->utf16)
63         buf16->utf16 = (UChar *) malloc(sizeof(UChar) * capacity);
64       else
65         buf16->utf16 
66           = (UChar *) realloc(buf16->utf16, sizeof(UChar) * capacity);
67       buf16->utf16_len = 0;
68       buf16->utf16_cap = capacity;
69     } 
70     else { 
71       if (buf16->utf16)
72         free(buf16->utf16);
73       buf16->utf16 = 0;
74       buf16->utf16_len = 0;
75       buf16->utf16_cap = 0;
76     }
77   }
78
79   return buf16;
80 };
81
82
83 void icu_buf_utf16_destroy(struct icu_buf_utf16 * buf16)
84 {
85   if (buf16){
86     if (buf16->utf16)
87       free(buf16->utf16);
88     free(buf16);
89   }
90 };
91
92
93
94 struct icu_buf_utf8
95 {
96   uint8_t * utf8;
97   int32_t utf8_len;
98   int32_t utf8_cap;
99 };
100
101
102
103 struct icu_buf_utf8 * icu_buf_utf8_create(size_t capacity)
104 {
105   struct icu_buf_utf8 * buf8 
106     = (struct icu_buf_utf8 *) malloc(sizeof(struct icu_buf_utf8));
107
108   buf8->utf8 = 0;
109   buf8->utf8_len = 0;
110   buf8->utf8_cap = 0;
111
112   if (capacity > 0){
113     buf8->utf8 = (uint8_t *) malloc(sizeof(uint8_t) * capacity);
114     buf8->utf8_cap = capacity;
115   }
116   return buf8;
117 };
118
119
120
121 struct icu_buf_utf8 * icu_buf_utf8_resize(struct icu_buf_utf8 * buf8,
122                                           size_t capacity)
123 {
124   printf("buf8  resize: %d\n", (int)capacity);
125   if (buf8){
126     if (capacity >  0){
127       if (0 == buf8->utf8)
128         buf8->utf8 = (uint8_t *) malloc(sizeof(uint8_t) * capacity);
129       else
130         buf8->utf8 
131           = (uint8_t *) realloc(buf8->utf8, sizeof(uint8_t) * capacity);
132       buf8->utf8_len = 0;
133       buf8->utf8_cap = capacity;
134     } 
135     else { 
136       if (buf8->utf8)
137         free(buf8->utf8);
138       buf8->utf8 = 0;
139       buf8->utf8_len = 0;
140       buf8->utf8_cap = 0;
141     }
142   }
143
144   return buf8;
145 };
146
147
148
149 void icu_buf_utf8_destroy(struct icu_buf_utf8 * buf8)
150 {
151   if (buf8){
152     if (buf8->utf8)
153       free(buf8->utf8);
154     free(buf8);
155   }
156 };
157
158
159
160 UErrorCode icu_utf16_from_utf8(struct icu_buf_utf16 * dest16,
161                                struct icu_buf_utf8 * src8,
162                                UErrorCode * status)
163 {
164   if(!U_SUCCESS(*status))
165     return *status;
166
167   u_strFromUTF8(dest16->utf16, dest16->utf16_cap, &(dest16->utf16_len),
168                 (const char *) src8->utf8, src8->utf8_len, status);
169
170   // check for buffer overflow, resize and retry
171   if (dest16->utf16_len > dest16->utf16_cap){
172     icu_buf_utf16_resize(dest16, dest16->utf16_len * 2);
173     *status = U_ZERO_ERROR;
174     u_strFromUTF8(dest16->utf16, dest16->utf16_cap, &(dest16->utf16_len),
175                   (const char*) src8->utf8, src8->utf8_len, status);
176   }
177
178   return *status;
179 };
180
181  
182
183 UErrorCode icu_utf16_from_utf8_cstr(struct icu_buf_utf16 * dest16,
184                                     const char * src8cstr,
185                                     UErrorCode * status)
186 {
187   size_t src8cstr_len = 0;
188   
189   if(!U_SUCCESS(status))
190     return *status;
191   
192   src8cstr_len = strlen(src8cstr);
193   
194   u_strFromUTF8(dest16->utf16, dest16->utf16_cap, &(dest16->utf16_len),
195                 src8cstr, src8cstr_len, status);
196   
197   // check for buffer overflow, resize and retry
198   if (dest16->utf16_len > dest16->utf16_cap){
199     icu_buf_utf16_resize(dest16, dest16->utf16_len * 2);
200     *status = U_ZERO_ERROR;
201     u_strFromUTF8(dest16->utf16, dest16->utf16_cap, &(dest16->utf16_len),
202                   src8cstr, src8cstr_len, status);
203   }
204   
205   return *status;
206 };
207
208
209 UErrorCode icu_sortkey8_from_utf16(UCollator *coll,
210                                    struct icu_buf_utf8 * dest8, 
211                                    struct icu_buf_utf16 * src16,
212                                    UErrorCode * status)
213
214   
215   int32_t sortkey_len = 0;
216   if(!U_SUCCESS(status))
217     return *status;
218   
219   sortkey_len = ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
220                                 dest8->utf8, dest8->utf8_len);
221   
222   // check for buffer overflow, resize and retry
223   if (sortkey_len > dest8->utf8_cap) {
224     icu_buf_utf8_resize(dest8, sortkey_len * 2);
225     ucol_getSortKey(coll, src16->utf16, src16->utf16_len,
226                     dest8->utf8, dest8->utf8_len);
227   }
228
229   return *status;
230 };
231
232  
233
234
235 struct icu_termmap
236 {
237   uint8_t sort_key[MAX_KEY_SIZE]; // standard C string '\0' terminated
238   char disp_term[MAX_KEY_SIZE];  // standard C utf-8 string
239 };
240
241
242
243 int icu_termmap_cmp(const void *vp1, const void *vp2)
244 {
245   struct icu_termmap *itmp1 = *(struct icu_termmap **) vp1;
246   struct icu_termmap *itmp2 = *(struct icu_termmap **) vp2;
247
248   int cmp = 0;
249     
250   cmp = strcmp((const char *)itmp1->sort_key, 
251                (const char *)itmp2->sort_key);
252   return cmp;
253 }
254
255
256 int icu_check_status(UErrorCode status)
257 {
258   if(!U_SUCCESS(status))
259     printf("ICU status: %d %s\n", status, u_errorName(status));
260   return status;
261 }
262
263
264
265 int icu_coll_sort(const char * locale, int src_list_len,
266                   const char ** src_list, const char ** chk_list)
267 {
268   UErrorCode status = U_ZERO_ERROR;
269   
270   struct icu_buf_utf8 * buf8 = icu_buf_utf8_create(0);
271   struct icu_buf_utf16 * buf16 = icu_buf_utf16_create(0);
272
273   int i;
274
275   struct icu_termmap * list[src_list_len];
276
277   UCollator *coll = ucol_open(locale, &status); 
278   icu_check_status(status);
279
280   if(!U_SUCCESS(status))
281     return 0;
282
283   // assigning display terms and sort keys using buf 8 and buf16
284   for( i = 0; i < src_list_len; i++) 
285     {
286
287       list[i] = (struct icu_termmap *) malloc(sizeof(struct icu_termmap));
288
289       // copy display term
290       strcpy(list[i]->disp_term, src_list[i]);    
291
292       // transforming to UTF16
293       icu_utf16_from_utf8_cstr(buf16, list[i]->disp_term, &status);
294       icu_check_status(status);
295
296       // computing sortkeys
297       icu_sortkey8_from_utf16(coll, buf8, buf16, &status);
298       icu_check_status(status);
299     
300       // assigning sortkeys
301       memcpy(list[i]->sort_key, buf8->utf8, buf8->utf8_len);    
302     } 
303
304   printf("\n"); 
305   printf("Input str: '%s' : ", locale); 
306   for (i = 0; i < src_list_len; i++) {
307     printf(" '%s'", list[i]->disp_term); 
308   }
309   printf("\n");
310
311   // do the sorting
312   qsort(list, src_list_len, 
313         sizeof(struct icu_termmap *), icu_termmap_cmp);
314   
315   
316   printf("ICU sort:  '%s' : ", locale); 
317   for (i = 0; i < src_list_len; i++) {
318     printf(" '%s'", list[i]->disp_term); 
319   }
320   printf("\n"); 
321   
322   ucol_close(coll);
323
324   icu_buf_utf8_destroy(buf8);
325   icu_buf_utf16_destroy(buf16);
326
327   return 1;
328 };
329
330
331 int main(int argc, char **argv)
332 {
333   
334   size_t en_1_len = 6;
335   const char * en_1_src[6] = {"z", "K", "a", "A", "Z", "k"};
336   const char * en_1_cck[6] = {"a", "A", "K", "k", "z", "Z"};
337   icu_coll_sort("en", en_1_len, en_1_src, en_1_cck);
338   icu_coll_sort("en_AU", en_1_len, en_1_src, en_1_cck);
339   icu_coll_sort("en_CA", en_1_len, en_1_src, en_1_cck);
340   icu_coll_sort("en_GB", en_1_len, en_1_src, en_1_cck);
341   icu_coll_sort("en_US", en_1_len, en_1_src, en_1_cck);
342     
343     
344   size_t da_1_len = 6;
345   const char * da_1_src[6] = {"z", "å", "o", "æ", "a", "ø"};
346   const char * da_1_cck[6] = {"a", "o", "z", "æ", "ø", "å"};
347   icu_coll_sort("da", da_1_len, da_1_src, da_1_cck);
348   icu_coll_sort("da_DK", da_1_len, da_1_src, da_1_cck);
349
350
351   size_t de_1_len = 9;
352   const char * de_1_src[9] = {"u", "ä", "o", "t", "s", "ß", "ü", "ö", "a"};
353   const char * de_1_cck[9] = {"ä", "a", "o", "ö", "s", "ß", "t", "u", "ü"};
354   icu_coll_sort("de", de_1_len, de_1_src, de_1_cck);
355   icu_coll_sort("de_AT", de_1_len, de_1_src, de_1_cck);
356   icu_coll_sort("de_DE", de_1_len, de_1_src, de_1_cck);
357
358   return 0;
359 };
360