added ICU experiment which sorts correctly given all locales tried.
[pazpar2-moved-to-github.git] / src / icu_experiment.c
1 // Make command on debian 64 bit testing dist  
2 /*
3 gcc -g -Wall `icu-config --cppflags`  `icu-config --ldflags` -o icu_experiment icu_experiment.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
32
33 struct icu_termmap
34 {
35   uint8_t sort_key[MAX_KEY_SIZE]; // standard C string '\0' terminated
36   UChar utf16_term[MAX_KEY_SIZE]; // ICU utf-16 string
37   int32_t utf16_len;               // ICU utf-16 string lenght
38   char disp_term[MAX_KEY_SIZE];  // standard C utf-8 string
39 };
40
41
42
43 int icu_termmap_cmp(const void *vp1, const void *vp2)
44 {
45     struct icu_termmap *itmp1 = *(struct icu_termmap **) vp1;
46     struct icu_termmap *itmp2 = *(struct icu_termmap **) vp2;
47
48     int cmp = 0;
49     
50     cmp = strcmp((const char *)itmp1->sort_key, 
51                   (const char *)itmp2->sort_key);
52     return cmp;
53 }
54
55
56 int icu_check_status(UErrorCode status)
57 {
58   if(!U_SUCCESS(status))
59     printf("ICU status: %d %s\n", status, u_errorName(status));
60   return status;
61 }
62
63
64
65 int icu_coll_sort(const char * locale, int src_list_len,
66                   const char ** src_list, const char ** chk_list)
67 {
68   
69   int i;
70   uint8_t *tmp = 0;
71   int32_t tmp_len = 0;
72   int32_t sort_key_len; 
73   
74   struct icu_termmap * list[src_list_len];
75   
76
77   UErrorCode status = U_ZERO_ERROR;
78   
79  
80   for( i = 0; i < src_list_len; i++) 
81     {
82       int text_len = strlen(src_list[i]);
83
84       list[i] = (struct icu_termmap *) malloc(sizeof(struct icu_termmap));
85
86       strcpy(list[i]->disp_term, src_list[i]);    
87
88       // transforming to UTF16
89       u_strFromUTF8(list[i]->utf16_term, MAX_KEY_SIZE, 
90                     &(list[i]->utf16_len), src_list[i], (int32_t) text_len,
91                     &status);
92       icu_check_status(status);
93
94       //u_uastrcpy(list[i]->utf16_term, src_list[i]);   
95    } 
96
97   printf("\n"); 
98   printf("Input str: '%s' : ", locale); 
99   for (i = 0; i < src_list_len; i++) {
100     printf(" '%s'", list[i]->disp_term); 
101   }
102   printf("\n");
103
104   UCollator *coll = ucol_open(locale, &status); 
105   icu_check_status(status);
106
107   if(!U_SUCCESS(status))
108     return 0;
109   
110
111
112   for(i=0; i < src_list_len; i++) {
113     sort_key_len 
114       = ucol_getSortKey(coll, list[i]->utf16_term, list[i]->utf16_len,
115                         tmp, tmp_len);
116     
117     // reallocating business ..
118     if (sort_key_len > tmp_len) {
119       printf("sort_key_len: %d tmp_len: %d, reallocating tmp buf\n", 
120              (int) sort_key_len, (int) tmp_len);
121       if (tmp == 0) { 
122         tmp = (uint8_t *) malloc(sort_key_len);
123       } else
124         tmp = (uint8_t *) realloc(tmp, sort_key_len);
125       tmp_len = sort_key_len;
126       
127       // one more round ..
128       sort_key_len 
129         = ucol_getSortKey(coll, list[i]->utf16_term, list[i]->utf16_len,
130                           tmp, tmp_len);
131     }
132     
133     // copy result out
134     memcpy(list[i]->sort_key, tmp, sort_key_len);    
135   }
136   icu_check_status(status);
137   
138   
139   //printf("Sortkeys assigned, now sorting\n");  
140   
141   // do the sorting
142   qsort(list, src_list_len, 
143         sizeof(struct icu_termmap *), icu_termmap_cmp);
144   
145   
146   printf("ICU sort:  '%s' : ", locale); 
147   for (i = 0; i < src_list_len; i++) {
148     printf(" '%s'", list[i]->disp_term); 
149   }
150   printf("\n"); 
151   
152 ucol_close(coll);
153
154  return 1;
155 };
156
157
158 int main(int argc, char **argv)
159 {
160   
161     size_t en_1_len = 6;
162     const char * en_1_src[6] = {"z", "K", "a", "A", "Z", "k"};
163     const char * en_1_cck[6] = {"a", "A", "K", "k", "z", "Z"};
164     icu_coll_sort("en", en_1_len, en_1_src, en_1_cck);
165     icu_coll_sort("en_AU", en_1_len, en_1_src, en_1_cck);
166     icu_coll_sort("en_CA", en_1_len, en_1_src, en_1_cck);
167     icu_coll_sort("en_GB", en_1_len, en_1_src, en_1_cck);
168     icu_coll_sort("en_US", en_1_len, en_1_src, en_1_cck);
169     
170     
171     size_t da_1_len = 6;
172     const char * da_1_src[6] = {"z", "å", "o", "æ", "a", "ø"};
173     const char * da_1_cck[6] = {"a", "o", "z", "æ", "ø", "å"};
174     icu_coll_sort("da", da_1_len, da_1_src, da_1_cck);
175     icu_coll_sort("da_DK", da_1_len, da_1_src, da_1_cck);
176
177
178     size_t de_1_len = 9;
179     const char * de_1_src[9] = {"u", "ä", "o", "t", "s", "ß", "ü", "ö", "a"};
180     const char * de_1_cck[9] = {"ä", "a", "o", "ö", "s", "ß", "t", "u", "ü"};
181     icu_coll_sort("de", de_1_len, de_1_src, de_1_cck);
182     icu_coll_sort("de_AT", de_1_len, de_1_src, de_1_cck);
183     icu_coll_sort("de_DE", de_1_len, de_1_src, de_1_cck);
184
185   return 0;
186 };
187