// (c) Peter Kankowski, 2008. http://smallcode.weblogs.us kankowski@narod.ru
#include "plurals.h"
#include <stdio.h>
#include <assert.h>
#define NUM_OF(A) (sizeof(A)/sizeof((A)[0]))
// Code for comparison from http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
unsigned Japanese(unsigned n) { n=n; return 0; }
unsigned English(unsigned n) { return n != 1; }
unsigned French(unsigned n) { return n > 1; }
unsigned Latvian(unsigned n) { return n%10==1 && n%100!=11 ? 0 : n == 0 ? 1 : 2; }
unsigned Irish(unsigned n) { return n==1 ? 0 : n==2 ? 1 : 2; }
unsigned Romanian(unsigned n) { return n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2; }
unsigned Lithuanian(unsigned n) { return n%10==1 && n%100!=11 ? 0 :
n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2; }
unsigned Russian(unsigned n) { return n%10==1 && n%100!=11 ? 0 : \
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; }
unsigned Czech(unsigned n) { return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; }
unsigned Polish(unsigned n) { return n==1 ? 0 :
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; }
unsigned Slovenian(unsigned n) { return n%100==1 ? 0 : n%100==2 ? 1 :
n%100==3 || n%100==4 ? 2 : 3; }
unsigned nplurals[] = {1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4};
const char* strings[] = {
"", // jp
"1", // en
"0 1", // fr
"1 1 10 t; 0 0", // lv
"1; 2", // gd
"z=1; 1; 1 19 100", // ro
"1 1 10 t; 2 9 10 t", // lt
"1 1 10 t; 2 4 10 t", // ru
"1; 2 4", // cs
"1; 2 4 10 t", // pl
"1 1 100; 2 2 100; 3 4 100", // sl
};
unsigned (*const funcs[])(unsigned) = {
Japanese, English, French, Latvian, Irish, Romanian,
Lithuanian, Russian, Czech, Polish, Slovenian,
};
void TestCompareWithGetText(void) {
assert( NUM_OF(funcs) == NUM_OF(strings) );
assert( NUM_OF(nplurals) == NUM_OF(funcs) );
for(int i = 0; i < NUM_OF(funcs); i++) {
PLURAL_INFO plurals;
unsigned count = PluralsReadCfg(&plurals, strings[i]);
if(count != nplurals[i])
printf("Wrong count for %s: expected %d, got %d\n",
strings[i], nplurals[i], count);
for(int n = 0; n < 1000; n++)
if(funcs[i](n) != PluralsGetForm(&plurals, n))
printf("Error: %d for %s: expected %d, got %d\n",
n, strings[i], funcs[i](n), PluralsGetForm(&plurals, n));
}
}
void TestReadCfg(void) {
PLURAL_INFO plurals;
assert( PluralsReadCfg(&plurals, "xyz") == 1);
assert( PluralsReadCfg(&plurals, ";") == 1);
assert( PluralsReadCfg(&plurals, "1 2;") == 2);
assert(plurals.form[0].start == 1);
assert(plurals.form[0].finish == 2);
assert(plurals.form[0].modulo == 0);
assert(plurals.form[0].skip_teens == 0);
assert( PluralsReadCfg(&plurals, "1 2 0;3 4 0 sdf") == 3);
assert(plurals.form[0].start == 1);
assert(plurals.form[0].finish == 2);
assert(plurals.form[0].modulo == 0);
assert(!plurals.form[0].skip_teens);
assert(plurals.form[1].start == 3);
assert(plurals.form[1].finish == 4);
assert(plurals.form[1].modulo == 0);
assert(plurals.form[1].skip_teens);
assert( PluralsReadCfg(&plurals, ";xyz") == 1);
assert( PluralsReadCfg(&plurals, "!1 a;xyz") == 1);
assert( PluralsReadCfg(&plurals, " z = 1 23 sdf ; 1 2 10 ; ^% 12 ad ; 10 20 0 2") == 3);
assert(plurals.form[0].start == 1);
assert(plurals.form[0].finish == 2);
assert(plurals.form[0].modulo == 10);
assert(plurals.form[0].skip_teens == 0);
assert(plurals.form[1].start == 10);
assert(plurals.form[1].finish == 20);
assert(plurals.form[1].modulo == 0);
assert(plurals.form[1].skip_teens);
assert( PluralsReadCfg(&plurals, " z = 1 23 sdf") == 1);
}
void Demo(void) {
static const char* file_plurals[] = {"plik", "pliki", "plik\'ow"};
PLURAL_INFO plurals;
PluralsReadCfg(&plurals, "1; 2 4 10 t");
for(int i = 0; i < 32; i++)
printf("%2d %s\n", i, file_plurals[ PluralsGetForm(&plurals, i) ]);
}
int main(void) {
TestCompareWithGetText();
TestReadCfg();
Demo();
return 0;
}