finished test ICU stand-allone program for benchmarking of ICU tokenization and norma...
[pazpar2-moved-to-github.git] / src / icu_chain_test.c
1 /**
2  gcc -I/usr/include/libxml2 -lxml2 -o icu-xml-convert icu-xml-convert.c
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 //#include <yaz/xmalloc.h>
13 #include <yaz/options.h>
14
15 #include <unicode/ucnv.h>
16 #include <unicode/ustring.h>
17
18 #include "icu_I18N.h"
19
20 /* commando line and config parameters */
21 static struct config_t { 
22     char conffile[1024];
23     char print[1024];
24     int xmloutput;
25     struct icu_chain * chain;
26     FILE * infile;
27     FILE * outfile;
28 } config;
29
30
31   
32 void print_option_error(const struct config_t *p_config)
33 {  
34   fprintf(stderr, "Calling error, valid options are :\n");
35   fprintf(stderr, "icu_chain_test\n"
36           "   [-c (path/to/config/file.xml)]\n"
37           "   [-p (a|c|l|t)] print ICU info \n"
38           "   [-x] XML output\n"
39           "\n"
40           "Examples:\n"
41           "cat hugetextfile.txt | ./icu_chain_test -c config.xml \n"
42           "./icu_chain_test -p c\n"
43           "./icu_chain_test -p l -x\n"
44           "./icu_chain_test -p t -x\n"
45           );
46   exit(1);
47 }
48
49 void read_params(int argc, char **argv, struct config_t *p_config){    
50   char *arg;
51   int ret;
52   
53   /* set default parameters */
54   p_config->conffile[0] = 0;
55   p_config->print[0] = 0;
56   p_config->xmloutput = 0;
57   p_config->chain = 0;
58   p_config->infile = stdin;
59   p_config->outfile = stdout;
60
61   /* set up command line parameters */
62   
63   while ((ret = options("c:p:x", argv, argc, &arg)) != -2)
64     {
65       switch (ret)
66         {
67         case 'c':
68           strcpy(p_config->conffile, arg);
69           break;
70         case 'p':
71           strcpy(p_config->print, arg);
72           break;
73         case 'x':
74             p_config->xmloutput = 1;
75           break;
76         default:
77           print_option_error(p_config);
78         }
79     }
80     
81     //p_config->infile = fopen("/etc/passwd", "r");
82     
83
84
85   if ((!strlen(p_config->conffile)
86       && !strlen(p_config->print))
87       || !config.infile
88       || !config.outfile)
89
90     print_option_error(p_config);
91 };
92
93
94 /*     UConverter *conv; */
95 /*     conv = ucnv_open("utf-8", &status); */
96 /*     assert(U_SUCCESS(status)); */
97
98 /*     *ustr16_len  */
99 /*       = ucnv_toUChars(conv, ustr16, 1024,  */
100 /*                       (const char *) *xstr8, strlen((const char *) *xstr8), */
101 /*                       &status); */
102   
103
104
105 /*      ucnv_fromUChars(conv, */
106 /*                      (char *) *xstr8, strlen((const char *) *xstr8), */
107 /*                      ustr16, *ustr16_len, */
108 /*                      &status); */
109 /*      ucnv_close(conv); */
110
111
112 static void print_icu_converters(const struct config_t *p_config)
113 {
114     int32_t count;
115     int32_t i;
116
117     count = ucnv_countAvailable();
118     if (p_config->xmloutput)
119         fprintf(config.outfile, "<converters count=\"%d\" default=\"%s\">\n",
120                count, ucnv_getDefaultName());
121     else {    
122         fprintf(config.outfile, "Available ICU converters: %d\n", count);
123         fprintf(config.outfile, "Default ICU Converter is: '%s'\n", ucnv_getDefaultName());
124     }
125     
126     for(i=0;i<count;i++){
127         if (p_config->xmloutput)
128             fprintf(config.outfile, "<converter id=\"%s\"/>\n", ucnv_getAvailableName(i));
129         else     
130             fprintf(config.outfile, "%s ", ucnv_getAvailableName(i));
131     }
132     
133     if (p_config->xmloutput)
134         fprintf(config.outfile, "</converters>\n");
135     else
136         fprintf(config.outfile, "\n");
137 }
138
139 static void print_icu_transliterators(const struct config_t *p_config)
140 {
141   int32_t count;
142   int32_t i;
143
144   count = utrans_countAvailableIDs();
145
146   int32_t buf_cap = 128;
147   char buf[buf_cap];
148
149   if (p_config->xmloutput)
150     fprintf(config.outfile, "<transliterators count=\"%d\">\n",  count);
151    else 
152     fprintf(config.outfile, "Available ICU transliterators: %d\n", count);
153
154   for(i=0;i<count;i++)
155     {
156       utrans_getAvailableID(i, buf, buf_cap);
157        if (p_config->xmloutput)
158          fprintf(config.outfile, "<transliterator id=\"%s\"/>\n", buf);
159        else
160          fprintf(config.outfile, " %s", buf);
161     }
162
163   if (p_config->xmloutput){
164     fprintf(config.outfile, "</transliterators>\n");
165   }
166   else
167     {
168       fprintf(config.outfile, "\n\nUnicode Set Patterns:\n"
169              "   Pattern         Description\n"
170              "   Ranges          [a-z]  The lower case letters a through z\n"
171              "   Named Chars     [abc123] The six characters a,b,c,1,2 and 3\n"
172              "   String          [abc{def}] chars a, b and c, and string 'def'\n"
173              "   Categories      [\\p{Letter}] Perl General Category 'Letter'.\n"
174              "   Categories      [:Letter:] Posix General Category 'Letter'.\n"
175              "\n"
176              "   Combination     Example\n"
177              "   Union           [[:Greek:] [:letter:]]\n"
178              "   Intersection    [[:Greek:] & [:letter:]]\n"
179              "   Set Complement  [[:Greek:] - [:letter:]]\n"
180              "   Complement      [^[:Greek:] [:letter:]]\n"
181              "\n"
182              "see: http://icu.sourceforge.net/userguide/unicodeSet.html\n"
183              "\n"
184              "Examples:\n"
185              "   [:Punctuation:] Any-Remove\n"
186              "   [:Cased-Letter:] Any-Upper\n"
187              "   [:Control:] Any-Remove\n"
188              "   [:Decimal_Number:] Any-Remove\n"
189              "   [:Final_Punctuation:] Any-Remove\n"
190              "   [:Georgian:] Any-Upper\n"
191              "   [:Katakana:] Any-Remove\n"
192              "   [:Arabic:] Any-Remove\n"
193              "   [:Punctuation:] Remove\n"
194              "   [[:Punctuation:]-[.,]] Remove\n"
195              "   [:Line_Separator:] Any-Remove\n"
196              "   [:Math_Symbol:] Any-Remove\n"
197              "   Lower; [:^Letter:] Remove (word tokenization)\n"
198              "   [:^Number:] Remove (numeric tokenization)\n"
199              "   [:^Katagana:] Remove (remove everything except Katagana)\n"
200              "   Lower;[[:WhiteSpace:][:Punctuation:]] Remove (word tokenization)\n"
201              "   NFD; [:Nonspacing Mark:] Remove; NFC   (removes accents from characters)\n"
202              "   [A-Za-z]; Lower(); Latin-Katakana; Katakana-Hiragana (transforms latin and katagana to hiragana)\n"
203              "   [[:separator:][:start punctuation:][:initial punctuation:]] Remove \n"
204              "\n"
205              "see http://icu.sourceforge.net/userguide/Transform.html\n"
206              "    http://www.unicode.org/Public/UNIDATA/UCD.html\n"
207              "    http://icu.sourceforge.net/userguide/Transform.html\n"
208              "    http://icu.sourceforge.net/userguide/TransformRule.html\n"
209              );
210
211
212   fprintf(config.outfile, "\n\n");
213   
214     }
215 }
216
217 static void print_icu_xml_locales(const struct config_t *p_config)
218 {
219   int32_t count;
220   int32_t i;
221   UErrorCode status = U_ZERO_ERROR;
222
223   UChar keyword[64];
224   int32_t keyword_len = 0;
225   char keyword_str[128];
226   int32_t keyword_str_len = 0;
227
228   UChar language[64];
229   int32_t language_len = 0;
230   char lang_str[128];
231   int32_t lang_str_len = 0;
232
233   UChar script[64];
234   int32_t script_len = 0;
235   char script_str[128];
236   int32_t script_str_len = 0;
237
238   UChar location[64];
239   int32_t location_len = 0;
240   char location_str[128];
241   int32_t location_str_len = 0;
242
243   UChar variant[64];
244   int32_t variant_len = 0;
245   char variant_str[128];
246   int32_t variant_str_len = 0;
247
248   UChar name[64];
249   int32_t name_len = 0;
250   char name_str[128];
251   int32_t name_str_len = 0;
252
253   UChar localname[64];
254   int32_t localname_len = 0;
255   char localname_str[128];
256   int32_t localname_str_len = 0;
257
258   count = uloc_countAvailable() ;
259
260   if (p_config->xmloutput){
261     
262       fprintf(config.outfile, "<locales count=\"%d\" default=\"%s\" collations=\"%d\">\n", 
263              count, uloc_getDefault(), ucol_countAvailable());
264   }
265   
266   for(i=0;i<count;i++) 
267   {
268
269     keyword_len 
270       = uloc_getDisplayKeyword(uloc_getAvailable(i), "en", 
271                                 keyword, 64, 
272                                 &status);
273
274     u_strToUTF8(keyword_str, 128, &keyword_str_len,
275                 keyword, keyword_len,
276                 &status);
277     
278     
279     language_len 
280       = uloc_getDisplayLanguage(uloc_getAvailable(i), "en", 
281                                 language, 64, 
282                                 &status);
283
284     u_strToUTF8(lang_str, 128, &lang_str_len,
285                 language, language_len,
286                 &status);
287
288
289     script_len 
290       = uloc_getDisplayScript(uloc_getAvailable(i), "en", 
291                                 script, 64, 
292                                 &status);
293
294     u_strToUTF8(script_str, 128, &script_str_len,
295                 script, script_len,
296                 &status);
297
298     location_len 
299       = uloc_getDisplayCountry(uloc_getAvailable(i), "en", 
300                                 location, 64, 
301                                 &status);
302
303     u_strToUTF8(location_str, 128, &location_str_len,
304                 location, location_len,
305                 &status);
306
307     variant_len 
308       = uloc_getDisplayVariant(uloc_getAvailable(i), "en", 
309                                 variant, 64, 
310                                 &status);
311
312     u_strToUTF8(variant_str, 128, &variant_str_len,
313                 variant, variant_len,
314                 &status);
315
316     name_len 
317       = uloc_getDisplayName(uloc_getAvailable(i), "en", 
318                                 name, 64, 
319                                 &status);
320
321     u_strToUTF8(name_str, 128, &name_str_len,
322                 name, name_len,
323                 &status);
324
325     localname_len 
326       = uloc_getDisplayName(uloc_getAvailable(i), uloc_getAvailable(i), 
327                                 localname, 64, 
328                                 &status);
329
330     u_strToUTF8(localname_str, 128, &localname_str_len,
331                 localname, localname_len,
332                 &status);
333
334
335     if (p_config->xmloutput){
336       fprintf(config.outfile, "<locale id=\"%s\"", uloc_getAvailable(i)); 
337       /* fprintf(config.outfile, " locale=\"%s\"", uloc_getAvailable(i)); */
338       /* if (strlen(keyword_str)) */
339       /*   fprintf(config.outfile, " keyword=\"%s\"", keyword_str); */
340       /* if (ucol_getAvailable(i)) */
341       /*   fprintf(config.outfile, " collation=\"1\""); */
342       if (strlen(lang_str))
343         fprintf(config.outfile, " language=\"%s\"", lang_str);
344       if (strlen(script_str))
345         fprintf(config.outfile, " script=\"%s\"", script_str);
346       if (strlen(location_str))
347         fprintf(config.outfile, " location=\"%s\"", location_str);
348       if (strlen(variant_str))
349         fprintf(config.outfile, " variant=\"%s\"", variant_str);
350       if (strlen(name_str))
351         fprintf(config.outfile, " name=\"%s\"", name_str);
352       if (strlen(localname_str))
353         fprintf(config.outfile, " localname=\"%s\"", localname_str);
354       fprintf(config.outfile, ">");
355       if (strlen(localname_str))
356         fprintf(config.outfile, "%s", localname_str);
357       fprintf(config.outfile, "</locale>\n"); 
358     }
359     else if (1 == p_config->xmloutput){
360       fprintf(config.outfile, "%s", uloc_getAvailable(i)); 
361       fprintf(config.outfile, " | ");
362       if (strlen(name_str))
363         fprintf(config.outfile, "%s", name_str);
364       fprintf(config.outfile, " | ");
365       if (strlen(localname_str))
366         fprintf(config.outfile, "%s", localname_str);
367       fprintf(config.outfile, "\n");
368     }
369     else
370       fprintf(config.outfile, "%s ", uloc_getAvailable(i));
371   }
372   if (p_config->xmloutput)
373     fprintf(config.outfile, "</locales>\n");
374   else
375     fprintf(config.outfile, "\n");
376
377   if(U_FAILURE(status)) {
378     fprintf(stderr, "ICU Error: %d %s\n", status, u_errorName(status));
379     exit(status);
380   }
381 }
382
383
384 static void print_info(const struct config_t *p_config)
385 {
386   if (p_config->xmloutput)
387     fprintf(config.outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
388            "<icu>\n");
389
390     if ('c' == config.print[0])
391         print_icu_converters(&config);
392     else if ('l' == config.print[0])
393         print_icu_xml_locales(&config);
394     else if ('t' == config.print[0])
395         print_icu_transliterators(&config);
396     else {
397         print_icu_converters(&config);
398         print_icu_xml_locales(&config);
399         print_icu_transliterators(&config);
400     }
401
402     if (p_config->xmloutput)
403         fprintf(config.outfile, "</icu>\n");
404
405   exit(0);
406 };
407
408
409
410 static void process_text_file(const struct config_t *p_config)
411 {
412     char * line = 0;
413     size_t line_cap = 0;
414     ssize_t line_len;
415  
416     xmlDoc *doc = xmlParseFile(config.conffile);  
417     xmlNode *xml_node = xmlDocGetRootElement(doc);
418
419     long unsigned int token_count = 0;    
420     long unsigned int line_count = 0;    
421     
422     UErrorCode status = U_ZERO_ERROR;
423     int success = 0;
424     
425     
426     config.chain = icu_chain_xml_config(xml_node, &status);
427
428     if (config.chain && U_SUCCESS(status))
429         success = 1;
430
431     if (p_config->xmloutput)
432         fprintf(config.outfile,
433                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
434                 "<icu>\n"
435                 "<tokens>\n");
436     
437     // read input lines for processing
438     while ((line_len = getline(&line, &line_cap, config.infile)) != -1) {
439         success = icu_chain_assign_cstr(config.chain, line, &status);
440         line_count++;
441
442         while (success && icu_chain_next_token(config.chain, &status)){
443             if (U_FAILURE(status))
444                 success = 0;
445             else {
446                 token_count++;
447                 if (p_config->xmloutput)                    
448                     fprintf(config.outfile, 
449                             "<token id=\%lu\" line=\"%lu\""
450                             " norm=\"%s\" display=\"%s\"/>\n",
451                             token_count,
452                             line_count,
453                             icu_chain_get_norm(config.chain),
454                             icu_chain_get_display(config.chain));
455                 else
456                     fprintf(config.outfile, "%lu %lu '%s' '%s'\n",
457                             token_count,
458                             line_count,
459                             icu_chain_get_norm(config.chain),
460                             icu_chain_get_display(config.chain));
461             }
462         }
463         
464     }
465
466    if (p_config->xmloutput)
467         fprintf(config.outfile, 
468                 "</tokens>\n"
469                 "</icu>\n");
470
471     icu_chain_destroy(config.chain);
472     xmlFreeDoc(doc);
473     if (line)
474         free(line);
475 };
476
477
478 int main(int argc, char **argv) 
479 {
480
481     read_params(argc, argv, &config);
482
483     if (config.conffile && strlen(config.conffile))
484         process_text_file(&config);
485      
486     if (config.print && strlen(config.print))
487         print_info(&config);
488     
489     
490     return(0);
491 };
492
493
494 /*
495  * Local variables:
496  * c-basic-offset: 4
497  * indent-tabs-mode: nil
498  * End:
499  * vim: shiftwidth=4 tabstop=8 expandtab
500  */
501