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 */ 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 */ 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 */ 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 */ 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