1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (C) 2002-2006 IBM, Inc.   All Rights Reserved.
4  *
5  ********************************************************************/
6 
7 /**
8  * This program demos string collation
9  */
10 
11 const char gHelpString[] =
12     "usage: coll [options*] -source source_string -target target_string\n"
13     "-help            Display this message.\n"
14     "-locale name     ICU locale to use.  Default is en_US\n"
15     "-rules rule      Collation rules file (overrides locale)\n"
16     "-french          French accent ordering\n"
17     "-norm            Normalizing mode on\n"
18     "-shifted         Shifted mode\n"
19     "-lower           Lower case first\n"
20     "-upper           Upper case first\n"
21     "-case            Enable separate case level\n"
22     "-level n         Sort level, 1 to 5, for Primary, Secndary, Tertiary, Quaternary, Identical\n"
23 	"-source string   Source string for comparison\n"
24 	"-target string   Target string for comparison\n"
25     "Example coll -rules \\u0026b\\u003ca -source a -target b\n"
26 	"The format \\uXXXX is supported for the rules and comparison strings\n"
27 	;
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include <unicode/utypes.h>
34 #include <unicode/ucol.h>
35 #include <unicode/ustring.h>
36 
37 /**
38  * Command line option variables
39  *    These global variables are set according to the options specified
40  *    on the command line by the user.
41  */
42 char * opt_locale     = "en_US";
43 char * opt_rules      = 0;
44 UBool  opt_help       = FALSE;
45 UBool  opt_norm       = FALSE;
46 UBool  opt_french     = FALSE;
47 UBool  opt_shifted    = FALSE;
48 UBool  opt_lower      = FALSE;
49 UBool  opt_upper      = FALSE;
50 UBool  opt_case       = FALSE;
51 int    opt_level      = 0;
52 char * opt_source     = "abc";
53 char * opt_target     = "abd";
54 UCollator * collator  = 0;
55 
56 /**
57  * Definitions for the command line options
58  */
59 struct OptSpec {
60     const char *name;
61     enum {FLAG, NUM, STRING} type;
62     void *pVar;
63 };
64 
65 OptSpec opts[] = {
66     {"-locale",      OptSpec::STRING, &opt_locale},
67     {"-rules",       OptSpec::STRING, &opt_rules},
68 	{"-source",      OptSpec::STRING, &opt_source},
69     {"-target",      OptSpec::STRING, &opt_target},
70     {"-norm",        OptSpec::FLAG,   &opt_norm},
71     {"-french",      OptSpec::FLAG,   &opt_french},
72     {"-shifted",     OptSpec::FLAG,   &opt_shifted},
73     {"-lower",       OptSpec::FLAG,   &opt_lower},
74     {"-upper",       OptSpec::FLAG,   &opt_upper},
75     {"-case",        OptSpec::FLAG,   &opt_case},
76     {"-level",       OptSpec::NUM,    &opt_level},
77     {"-help",        OptSpec::FLAG,   &opt_help},
78     {"-?",           OptSpec::FLAG,   &opt_help},
79     {0, OptSpec::FLAG, 0}
80 };
81 
82 /**
83  * processOptions()  Function to read the command line options.
84  */
processOptions(int argc,const char ** argv,OptSpec opts[])85 UBool processOptions(int argc, const char **argv, OptSpec opts[])
86 {
87     for (int argNum = 1; argNum < argc; argNum ++) {
88         const char *pArgName = argv[argNum];
89         OptSpec *pOpt;
90         for (pOpt = opts;  pOpt->name != 0; pOpt ++) {
91             if (strcmp(pOpt->name, pArgName) == 0) {
92                 switch (pOpt->type) {
93                 case OptSpec::FLAG:
94                     *(UBool *)(pOpt->pVar) = TRUE;
95                     break;
96                 case OptSpec::STRING:
97                     argNum ++;
98                     if (argNum >= argc) {
99                         fprintf(stderr, "value expected for \"%s\" option.\n",
100 							    pOpt->name);
101                         return FALSE;
102                     }
103                     *(const char **)(pOpt->pVar) = argv[argNum];
104                     break;
105                 case OptSpec::NUM:
106                     argNum ++;
107                     if (argNum >= argc) {
108                         fprintf(stderr, "value expected for \"%s\" option.\n",
109 							    pOpt->name);
110                         return FALSE;
111                     }
112                     char *endp;
113                     int i = strtol(argv[argNum], &endp, 0);
114                     if (endp == argv[argNum]) {
115                         fprintf(stderr,
116 							    "integer value expected for \"%s\" option.\n",
117 								pOpt->name);
118                         return FALSE;
119                     }
120                     *(int *)(pOpt->pVar) = i;
121                 }
122                 break;
123             }
124         }
125         if (pOpt->name == 0)
126         {
127             fprintf(stderr, "Unrecognized option \"%s\"\n", pArgName);
128             return FALSE;
129         }
130     }
131 	return TRUE;
132 }
133 
134 /**
135  * ICU string comparison
136  */
strcmp()137 int strcmp()
138 {
139 	UChar source[100];
140 	UChar target[100];
141 	u_unescape(opt_source, source, 100);
142 	u_unescape(opt_target, target, 100);
143     UCollationResult result = ucol_strcoll(collator, source, -1, target, -1);
144     if (result == UCOL_LESS) {
145 		return -1;
146 	}
147     else if (result == UCOL_GREATER) {
148 		return 1;
149 	}
150 	return 0;
151 }
152 
153 /**
154  * Creates a collator
155  */
processCollator()156 UBool processCollator()
157 {
158 	// Set up an ICU collator
159     UErrorCode status = U_ZERO_ERROR;
160 	UChar rules[100];
161 
162     if (opt_rules != 0) {
163 		u_unescape(opt_rules, rules, 100);
164         collator = ucol_openRules(rules, -1, UCOL_OFF, UCOL_TERTIARY,
165 			                  NULL, &status);
166     }
167     else {
168         collator = ucol_open(opt_locale, &status);
169     }
170 	if (U_FAILURE(status)) {
171         fprintf(stderr, "Collator creation failed.: %d\n", status);
172         return FALSE;
173     }
174     if (status == U_USING_DEFAULT_WARNING) {
175         fprintf(stderr, "Warning, U_USING_DEFAULT_WARNING for %s\n",
176 			    opt_locale);
177     }
178     if (status == U_USING_FALLBACK_WARNING) {
179         fprintf(stderr, "Warning, U_USING_FALLBACK_ERROR for %s\n",
180 			    opt_locale);
181     }
182     if (opt_norm) {
183         ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
184     }
185     if (opt_french) {
186         ucol_setAttribute(collator, UCOL_FRENCH_COLLATION, UCOL_ON, &status);
187     }
188     if (opt_lower) {
189         ucol_setAttribute(collator, UCOL_CASE_FIRST, UCOL_LOWER_FIRST,
190 			              &status);
191     }
192     if (opt_upper) {
193         ucol_setAttribute(collator, UCOL_CASE_FIRST, UCOL_UPPER_FIRST,
194 			              &status);
195     }
196     if (opt_case) {
197         ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_ON, &status);
198     }
199     if (opt_shifted) {
200         ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
201 			              &status);
202     }
203     if (opt_level != 0) {
204         switch (opt_level) {
205         case 1:
206             ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
207             break;
208         case 2:
209             ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_SECONDARY,
210 				              &status);
211             break;
212         case 3:
213             ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_TERTIARY, &status);
214             break;
215         case 4:
216             ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_QUATERNARY,
217 				              &status);
218             break;
219         case 5:
220             ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_IDENTICAL,
221 				              &status);
222             break;
223         default:
224             fprintf(stderr, "-level param must be between 1 and 5\n");
225             return FALSE;
226         }
227     }
228     if (U_FAILURE(status)) {
229         fprintf(stderr, "Collator attribute setting failed.: %d\n", status);
230         return FALSE;
231     }
232 	return TRUE;
233 }
234 
235 /**
236  * Main   --  process command line, read in and pre-process the test file,
237  *            call other functions to do the actual tests.
238  */
main(int argc,const char ** argv)239 int main(int argc, const char** argv)
240 {
241     if (processOptions(argc, argv, opts) != TRUE || opt_help) {
242         printf(gHelpString);
243         return -1;
244     }
245 
246     if (processCollator() != TRUE) {
247 		fprintf(stderr, "Error creating collator for comparison\n");
248 		return -1;
249 	}
250 
251 	fprintf(stdout, "Comparing source=%s and target=%s\n", opt_source,
252 			opt_target);
253 	int result = strcmp();
254 	if (result == 0) {
255 		fprintf(stdout, "source is equals to target\n");
256 	}
257 	else if (result < 0) {
258 		fprintf(stdout, "source is less than target\n");
259 	}
260 	else {
261 		fprintf(stdout, "source is greater than target\n");
262 	}
263 
264 	ucol_close(collator);
265 	return 0;
266 }
267