xref: /haiku/src/tests/kits/locale/collatorTest.cpp (revision b6f76ebe7153b94820cf35f8db4facc158841abb)
1 /*
2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the MIT License.
4 */
5 
6 
7 #include <Collator.h>
8 #include <Locale.h>
9 #include <LocaleRoster.h>
10 #include <Message.h>
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 
17 
18 const char *kStrings[] = {
19 	"a-b-c",
20 	"a b c",
21 	"A.b.c",
22 	"ä,b,c",
23 	"abc",
24 	"gehen",
25 	"géhen",
26 	"aus",
27 	"äUß",
28 	"auss",
29 	"WO",
30 	"wÖ",
31 	"SO",
32 	"so",
33 	"açñ",
34 	"acn",
35 	"pêche",
36 	"pêché",
37 	"peché",
38 	"peche",
39 	"PECHE",
40 	"PÊCHE",
41 	"pecher",
42 	"eñe",
43 	"ene",
44 	"nz",
45 	"ña",
46 	"llamar",
47 	"luz",
48 };
49 const uint32 kNumStrings = sizeof(kStrings) / sizeof(kStrings[0]);
50 
51 BCollator *gCollator;
52 
53 bool gTestKeyGeneration = true;
54 bool gShowKeys = false;
55 
56 
57 int
compareStrings(const void * _a,const void * _b)58 compareStrings(const void *_a, const void *_b)
59 {
60 	const char *a = *(const char **)_a;
61 	const char *b = *(const char **)_b;
62 
63 	return gCollator->Compare(a, b);
64 }
65 
66 
67 void
printArray(const char * label,const char ** strings,size_t size)68 printArray(const char *label, const char **strings, size_t size)
69 {
70 	puts(label);
71 
72 	uint32 bucket = 1;
73 	for (uint32 i = 0; i < size; i++) {
74 		if (i > 0) {
75 			int compare = gCollator->Compare(strings[i], strings[i - 1]);
76 			if (compare > 0)
77 				printf("\n%2lu)", bucket++);
78 			else if (compare < 0) {
79 				printf("\t*** broken sort order, next is NOT %s\n", strings[i]);
80 				exit(-1);
81 			}
82 
83 			// Test sort key generation
84 
85 			if (gTestKeyGeneration) {
86 				BString a, b;
87 				gCollator->GetSortKey(strings[i - 1], &a);
88 				gCollator->GetSortKey(strings[i], &b);
89 
90 				int keyCompare = strcmp(a.String(), b.String());
91 				if (keyCompare > 0 || (keyCompare == 0 && compare != 0))
92 					printf(" (*** \"%s\" wrong keys \"%s\" ***) ", a.String(), b.String());
93 			}
94 		} else
95 			printf("%2lu)", bucket++);
96 
97 		printf("\t%s", strings[i]);
98 
99 		if (gShowKeys) {
100 			BString key;
101 			gCollator->GetSortKey(strings[i], &key);
102 			printf(" (%s)", key.String());
103 		}
104 	}
105 	putchar('\n');
106 }
107 
108 
109 void
usage()110 usage()
111 {
112 	fprintf(stderr,
113 		"usage: collatorTest [-ick] [<add-on path>]\n"
114 		"  -i\tignore punctuation (defaults to: punctuation matters)\n"
115 		"  -c\tcomparison only, no sort key test\n"
116 		"  -k\tshows the sort keys along the strings (sort keys doesn't have to be visually correct)\n");
117 	exit(-1);
118 }
119 
120 
121 int
main(int argc,char ** argv)122 main(int argc, char **argv)
123 {
124 	// Parse command line arguments
125 
126 	int strength = B_COLLATE_SECONDARY;
127 	bool ignorePunctuation = false;
128 	char *addon = NULL;
129 
130 	BCollator defaultCollator;
131 	BLocaleRoster::Default()->GetDefaultLocale()->GetCollator(&defaultCollator);
132 
133 	while ((++argv)[0]) {
134 		if (argv[0][0] == '-' && argv[0][1] != '-') {
135 			char *arg = argv[0] + 1;
136 			char c;
137 			while ((c = *arg++)) {
138 				if (c == 'i')
139 					ignorePunctuation = true;
140 				else if (c == 'c')
141 					gTestKeyGeneration = false;
142 				else if (c == 'k')
143 					gShowKeys = true;
144 				else if (isdigit(c)) {
145 					int strength = c - '0';
146 					if (strength < B_COLLATE_PRIMARY)
147 						strength = B_COLLATE_PRIMARY;
148 					else if (strength > B_COLLATE_IDENTICAL)
149 						strength = B_COLLATE_IDENTICAL;
150 				}
151 			}
152 		} else if (!strcmp(argv[0], "--help")) {
153 			usage();
154 		} else {
155 			// this will be the add-on to be loaded
156 			addon = argv[0];
157 		}
158 	}
159 
160 	// load the collator add-on if necessary
161 
162 	if (addon != NULL)
163 		gCollator = new BCollator(addon, strength, true);
164 
165 	if (gCollator == NULL) {
166 		printf("--------- Use standard collator! -----------\n");
167 		gCollator = &defaultCollator;
168 	}
169 
170 	printf("test archiving/unarchiving collator\n");
171 
172 	BMessage archive;
173 	if (gCollator->Archive(&archive, true) != B_OK)
174 		fprintf(stderr, "Archiving failed!\n");
175 	else {
176 		BArchivable *unarchived = instantiate_object(&archive);
177 		gCollator = dynamic_cast<BCollator *>(unarchived);
178 		if (gCollator == NULL) {
179 			fprintf(stderr, "Unarchiving failed!\n");
180 
181 			delete unarchived;
182 			gCollator = &defaultCollator;
183 		}
184 	}
185 
186 	printf(" Archived content :");
187 	archive.PrintToStream();
188 
189 	printf("test the BCollator::Compare() and GetSortKey() methods\n");
190 
191 	const char *strengthLabels[] = {"primary:  ", "secondary:", "tertiary: "};
192 	uint32 strengths[] = {B_COLLATE_PRIMARY, B_COLLATE_SECONDARY, B_COLLATE_TERTIARY};
193 
194 	gCollator->SetIgnorePunctuation(ignorePunctuation);
195 
196 	for (uint32 i = 0; i < sizeof(strengths) / sizeof(strengths[0]); i++) {
197 		gCollator->SetDefaultStrength(strengths[i]);
198 		qsort(kStrings, kNumStrings, sizeof(char *), compareStrings);
199 
200 		printArray(strengthLabels[i], kStrings, kNumStrings);
201 	}
202 }
203 
204