blob: 1be46073883f6cdd37d58cbd3102889cc8b5108e [file] [log] [blame]
/* Test collation function via transformation using real data.
Copyright (C) 1997-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Branched from glibc's localedata/xfrm-test.c. */
#include <ctype.h>
#include <error.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Keep in sync with string/strxfrm_l.c. */
#define SMALL_STR_SIZE 4095
#include "third_party/glibc_locales/glibc_locales.h"
struct lines {
char *xfrm;
char *line;
};
static int xstrcmp(const void *, const void *);
int main(int argc, char *argv[]) {
int result = 0;
bool nocache = false;
size_t nstrings, nstrings_max;
struct lines *strings;
char *line = NULL;
size_t len = 0;
size_t n;
if (argc < 3)
error(1, 0, "usage: %s <random seed> <locale> [-nocache]", argv[0]);
if (argc == 4) {
if (strcmp(argv[3], "-nocache") == 0)
nocache = true;
else {
printf("Unknown option %s!\n", argv[3]);
exit(1);
}
}
google_locale_t locale = google_newlocale(LC_ALL_MASK, argv[2], NULL, 0);
if (locale == NULL) {
error(1, 0, "failed to load locale '%s'", argv[2]);
exit(1);
}
nstrings_max = 100;
nstrings = 0;
strings = (struct lines *)malloc(nstrings_max * sizeof(struct lines));
if (strings == NULL) {
perror(argv[0]);
exit(1);
}
while (1) {
char saved, *word, *newp;
size_t l, line_len, needed;
if (getline(&line, &len, stdin) < 0) break;
if (nstrings == nstrings_max) {
strings = (struct lines *)realloc(strings,
(nstrings_max *= 2) * sizeof(*strings));
if (strings == NULL) {
perror(argv[0]);
exit(1);
}
}
strings[nstrings].line = strdup(line);
l = strcspn(line, ":(;");
while (l > 0 && isspace(line[l - 1])) --l;
saved = line[l];
line[l] = '\0';
if (nocache) {
line_len = strlen(line);
word = malloc(line_len + SMALL_STR_SIZE + 1);
if (word == NULL) {
printf("malloc failed: %m\n");
exit(1);
}
memset(word, ' ', SMALL_STR_SIZE);
memcpy(word + SMALL_STR_SIZE, line, line_len);
word[line_len + SMALL_STR_SIZE] = '\0';
} else
word = line;
needed = google_strxfrm_l(NULL, word, 0, locale);
newp = malloc(needed + 1);
if (newp == NULL) {
printf("malloc failed: %m\n");
exit(1);
}
google_strxfrm_l(newp, word, needed + 1, locale);
strings[nstrings].xfrm = newp;
if (nocache) free(word);
line[l] = saved;
++nstrings;
}
free(line);
/* First shuffle. */
srandom(atoi(argv[1]));
for (n = 0; n < 10 * nstrings; ++n) {
int r1, r2, r;
size_t idx1 = random() % nstrings;
size_t idx2 = random() % nstrings;
struct lines tmp = strings[idx1];
strings[idx1] = strings[idx2];
strings[idx2] = tmp;
/* While we are at it a first little test. */
r1 = strcmp(strings[idx1].xfrm, strings[idx2].xfrm);
r2 = strcmp(strings[idx2].xfrm, strings[idx1].xfrm);
r = -(r1 ^ r2);
if (r) r /= abs(r1 ^ r2);
if (r < 0 || (r == 0 && (r1 != 0 || r2 != 0)) || (r > 0 && (r1 ^ r2) >= 0))
printf("collate wrong: %d vs. %d\n", r1, r2);
}
/* Now sort. */
qsort(strings, nstrings, sizeof(struct lines), xstrcmp);
/* Print the result. */
for (n = 0; n < nstrings; ++n) {
fputs(strings[n].line, stdout);
free(strings[n].line);
free(strings[n].xfrm);
}
free(strings);
return result;
}
static int xstrcmp(ptr1, ptr2) const void *ptr1;
const void *ptr2;
{
const struct lines *l1 = (const struct lines *)ptr1;
const struct lines *l2 = (const struct lines *)ptr2;
return strcmp(l1->xfrm, l2->xfrm);
}