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