1 /* 2 * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <ctype.h> 7 #include <errno.h> 8 #include <langinfo.h> 9 #include <locale.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <time.h> 14 #include <wctype.h> 15 16 17 // #pragma mark - setlocale ---------------------------------------------------- 18 19 20 void 21 test_setlocale() 22 { 23 const char* locales[] = { 24 "POSIX", 25 "C", 26 "de_DE", 27 "en_US", 28 "en_US.US-ASCII", 29 "hr_HR.ISO-8859-2", 30 "nl_NL", 31 "nb_NO", 32 "fr_FR.UTF-8@collation=phonebook", 33 "de_DE.iso8859-1", 34 "De_dE.IsO8859-15", 35 "de_DE.utf8", 36 "de_DE.UTF-8", 37 "de_DE@euro", 38 "de_DE@EURO", 39 "de_DE.utf-8@Euro", 40 "POSIX", 41 "C", 42 NULL 43 }; 44 const char* expectedLocales[] = { 45 "POSIX", 46 "POSIX", 47 "de_DE", 48 "en_US", 49 "en_US.US-ASCII", 50 "hr_HR.ISO-8859-2", 51 "nl_NL", 52 "nb_NO", 53 "fr_FR.UTF-8@collation=phonebook", 54 "de_DE.iso8859-1", 55 "De_dE.IsO8859-15", 56 "de_DE.utf8", 57 "de_DE.UTF-8", 58 "de_DE@euro", 59 "de_DE@EURO", 60 "de_DE.utf-8@Euro", 61 "POSIX", 62 "POSIX" 63 }; 64 const char* categoryNames[] = { 65 "LC_ALL", 66 "LC_COLLATE", 67 "LC_CTYPE", 68 "LC_MONETARY", 69 "LC_NUMERIC", 70 "LC_TIME", 71 "LC_MESSAGES" 72 }; 73 printf("setlocale()\n"); 74 75 int problemCount = 0; 76 for (int i = 0; locales[i] != NULL; ++i) { 77 char* result = setlocale(LC_ALL, locales[i]); 78 if (!result || strcmp(result, expectedLocales[i]) != 0) { 79 printf("\tPROBLEM: setlocale(LC_ALL, \"%s\") = \"%s\" " 80 "(expected \"%s\")\n", 81 locales[i], result, expectedLocales[i]); 82 problemCount++; 83 } 84 } 85 86 for (int i = 1; i <= LC_LAST; ++i) 87 setlocale(i, locales[i + 1]); 88 char* result = setlocale(LC_ALL, NULL); 89 const char* expectedResult 90 = "LC_COLLATE=de_DE;LC_CTYPE=en_US;LC_MESSAGES=nb_NO;" 91 "LC_MONETARY=en_US.US-ASCII;LC_NUMERIC=hr_HR.ISO-8859-2;" 92 "LC_TIME=nl_NL"; 93 if (!result || strcmp(result, expectedResult) != 0) { 94 printf("\tPROBLEM: setlocale(LC_ALL, NULL) = \"%s\" " 95 "(expected \"%s\")\n", result, expectedResult); 96 problemCount++; 97 } 98 99 if (problemCount) 100 printf("\t%d problem(s) found!\n", problemCount); 101 else 102 printf("\tall fine\n"); 103 } 104 105 106 // #pragma mark - localeconv --------------------------------------------------- 107 108 109 void 110 dumpGrouping(const char* grouping, char* buf) 111 { 112 for (char* bufPtr = buf; *grouping; ++grouping) 113 bufPtr += sprintf(bufPtr, "\\x%02x", *grouping); 114 } 115 116 117 void 118 test_localeconv(const char* locale, const lconv* localeConv) 119 { 120 setlocale(LC_MONETARY, locale); 121 setlocale(LC_NUMERIC, locale); 122 printf("localeconv for '%s'\n", locale); 123 124 int problemCount = 0; 125 struct lconv* lc = localeconv(); 126 if (!lc) 127 printf("not ok - got no result from localeconv()\n"); 128 else { 129 if (strcmp(lc->decimal_point, localeConv->decimal_point) != 0) { 130 printf("\tPROBLEM: lc.decimal_point = \"%s\" (expected \"%s\")\n", 131 lc->decimal_point, localeConv->decimal_point); 132 problemCount++; 133 } 134 if (strcmp(lc->thousands_sep, localeConv->thousands_sep) != 0) { 135 printf("\tPROBLEM: lc.thousands_sep = \"%s\" (expected \"%s\")\n", 136 lc->thousands_sep, localeConv->thousands_sep); 137 problemCount++; 138 } 139 if (strcmp(lc->grouping, localeConv->grouping) != 0) { 140 char gotGrouping[20], expectedGrouping[20]; 141 dumpGrouping(lc->grouping, gotGrouping); 142 dumpGrouping(localeConv->grouping, expectedGrouping); 143 printf("\tPROBLEM: lc.grouping = \"%s\" (expected \"%s\")\n", 144 gotGrouping, expectedGrouping); 145 problemCount++; 146 } 147 if (strcmp(lc->int_curr_symbol, localeConv->int_curr_symbol) != 0) { 148 printf("\tPROBLEM: lc.int_curr_symbol = \"%s\" (expected \"%s\")\n", 149 lc->int_curr_symbol, localeConv->int_curr_symbol); 150 problemCount++; 151 } 152 if (strcmp(lc->currency_symbol, localeConv->currency_symbol) != 0) { 153 printf("\tPROBLEM: lc.currency_symbol = \"%s\" (expected \"%s\")\n", 154 lc->currency_symbol, localeConv->currency_symbol); 155 problemCount++; 156 } 157 if (strcmp(lc->mon_decimal_point, localeConv->mon_decimal_point) != 0) { 158 printf("\tPROBLEM: lc.mon_decimal_point = \"%s\" " 159 "(expected \"%s\")\n", 160 lc->mon_decimal_point, localeConv->mon_decimal_point); 161 problemCount++; 162 } 163 if (strcmp(lc->mon_thousands_sep, localeConv->mon_thousands_sep) != 0) { 164 printf("\tPROBLEM: lc.mon_thousands_sep = \"%s\" " 165 "(expected \"%s\")\n", 166 lc->mon_thousands_sep, localeConv->mon_thousands_sep); 167 problemCount++; 168 } 169 if (strcmp(lc->mon_grouping, localeConv->mon_grouping) != 0) { 170 char gotGrouping[20], expectedGrouping[20]; 171 dumpGrouping(lc->mon_grouping, gotGrouping); 172 dumpGrouping(localeConv->mon_grouping, expectedGrouping); 173 printf("\tPROBLEM: lc.mon_grouping: \"%s\" (expected \"%s\")\n", 174 gotGrouping, expectedGrouping); 175 problemCount++; 176 } 177 if (strcmp(lc->positive_sign, localeConv->positive_sign) != 0) { 178 printf("\tPROBLEM: lc.positive_sign = \"%s\" (expected \"%s\")\n", 179 lc->positive_sign, localeConv->positive_sign); 180 problemCount++; 181 } 182 if (strcmp(lc->negative_sign, localeConv->negative_sign) != 0) { 183 printf("\tPROBLEM: lc.negative_sign = \"%s\" (expected \"%s\")\n", 184 lc->negative_sign, localeConv->negative_sign); 185 problemCount++; 186 } 187 if (lc->frac_digits != localeConv->frac_digits) { 188 printf("\tPROBLEM: lc.frac_digits = %d (expected %d)\n", 189 lc->frac_digits, localeConv->frac_digits); 190 problemCount++; 191 } 192 if (lc->int_frac_digits != localeConv->int_frac_digits) { 193 printf("\tPROBLEM: lc.int_frac_digits = %d (expected %d)\n", 194 lc->int_frac_digits, localeConv->int_frac_digits); 195 problemCount++; 196 } 197 if (lc->p_cs_precedes != localeConv->p_cs_precedes) { 198 printf("\tPROBLEM: lc.p_cs_precedes = %d (expected %d)\n", 199 lc->p_cs_precedes, localeConv->p_cs_precedes); 200 problemCount++; 201 } 202 if (lc->p_sep_by_space != localeConv->p_sep_by_space) { 203 printf("\tPROBLEM: lc.p_sep_by_space = %d (expected %d)\n", 204 lc->p_sep_by_space, localeConv->p_sep_by_space); 205 problemCount++; 206 } 207 if (lc->p_sign_posn != localeConv->p_sign_posn) { 208 printf("\tPROBLEM: lc.p_sign_posn = %d (expected %d)\n", 209 lc->p_sign_posn, localeConv->p_sign_posn); 210 problemCount++; 211 } 212 if (lc->n_cs_precedes != localeConv->n_cs_precedes) { 213 printf("\tPROBLEM: lc.n_cs_precedes = %d (expected %d)\n", 214 lc->n_cs_precedes, localeConv->n_cs_precedes); 215 problemCount++; 216 } 217 if (lc->n_sep_by_space != localeConv->n_sep_by_space) { 218 printf("\tPROBLEM: lc.n_sep_by_space = %d (expected %d)\n", 219 lc->n_sep_by_space, localeConv->n_sep_by_space); 220 problemCount++; 221 } 222 if (lc->n_sign_posn != localeConv->n_sign_posn) { 223 printf("\tPROBLEM: lc.n_sign_posn = %d (expected %d)\n", 224 lc->n_sign_posn, localeConv->n_sign_posn); 225 problemCount++; 226 } 227 if (lc->int_p_cs_precedes != localeConv->int_p_cs_precedes) { 228 printf("\tPROBLEM: lc.int_p_cs_precedes = %d (expected %d)\n", 229 lc->int_p_cs_precedes, localeConv->int_p_cs_precedes); 230 problemCount++; 231 } 232 if (lc->int_p_sep_by_space != localeConv->int_p_sep_by_space) { 233 printf("\tPROBLEM: lc.int_p_sep_by_space = %d (expected %d)\n", 234 lc->int_p_sep_by_space, localeConv->int_p_sep_by_space); 235 problemCount++; 236 } 237 if (lc->int_p_sign_posn != localeConv->int_p_sign_posn) { 238 printf("\tPROBLEM: lc.int_p_sign_posn = %d (expected %d)\n", 239 lc->int_p_sign_posn, localeConv->int_p_sign_posn); 240 problemCount++; 241 } 242 if (lc->int_n_cs_precedes != localeConv->int_n_cs_precedes) { 243 printf("\tPROBLEM: lc.int_n_cs_precedes = %d (expected %d)\n", 244 lc->int_n_cs_precedes, localeConv->int_n_cs_precedes); 245 problemCount++; 246 } 247 if (lc->int_n_sep_by_space != localeConv->int_n_sep_by_space) { 248 printf("\tPROBLEM: lc.int_n_sep_by_space = %d (expected %d)\n", 249 lc->int_n_sep_by_space, localeConv->int_n_sep_by_space); 250 problemCount++; 251 } 252 if (lc->int_n_sign_posn != localeConv->int_n_sign_posn) { 253 printf("\tPROBLEM: lc.int_n_sign_posn = %d (expected %d)\n", 254 lc->int_n_sign_posn, localeConv->int_n_sign_posn); 255 problemCount++; 256 } 257 } 258 if (problemCount) 259 printf("\t%d problem(s) found!\n", problemCount); 260 else 261 printf("\tall fine\n"); 262 } 263 264 265 void 266 test_localeconv() 267 { 268 const lconv lconv_posix = { 269 (char*)".", 270 (char*)"", 271 (char*)"", 272 (char*)"", 273 (char*)"", 274 (char*)"", 275 (char*)"", 276 (char*)"", 277 (char*)"", 278 (char*)"", 279 CHAR_MAX, 280 CHAR_MAX, 281 CHAR_MAX, 282 CHAR_MAX, 283 CHAR_MAX, 284 CHAR_MAX, 285 CHAR_MAX, 286 CHAR_MAX, 287 CHAR_MAX, 288 CHAR_MAX, 289 CHAR_MAX, 290 CHAR_MAX, 291 CHAR_MAX, 292 CHAR_MAX 293 }; 294 test_localeconv("POSIX", &lconv_posix); 295 296 const lconv lconv_de = { 297 (char*)",", 298 (char*)".", 299 (char*)"\x03", 300 (char*)"EUR ", 301 (char*)"€", 302 (char*)",", 303 (char*)".", 304 (char*)"\x03", 305 (char*)"", 306 (char*)"-", 307 2, 308 2, 309 0, 310 1, 311 0, 312 1, 313 1, 314 1, 315 0, 316 1, 317 0, 318 1, 319 1, 320 1 321 }; 322 test_localeconv("de_DE", &lconv_de); 323 324 const lconv lconv_de_iso = { 325 (char*)",", 326 (char*)".", 327 (char*)"\x03", 328 (char*)"EUR ", 329 (char*)"EUR", 330 (char*)",", 331 (char*)".", 332 (char*)"\x03", 333 (char*)"", 334 (char*)"-", 335 2, 336 2, 337 0, 338 1, 339 0, 340 1, 341 1, 342 1, 343 0, 344 1, 345 0, 346 1, 347 1, 348 1 349 }; 350 test_localeconv("de_DE.ISO8859-1", &lconv_de_iso); 351 352 const lconv lconv_hr = { 353 (char*)",", 354 (char*)".", 355 (char*)"\x03", 356 (char*)"HRK ", 357 (char*)"kn", 358 (char*)",", 359 (char*)".", 360 (char*)"\x03", 361 (char*)"", 362 (char*)"-", 363 2, 364 2, 365 0, 366 1, 367 0, 368 1, 369 1, 370 1, 371 0, 372 1, 373 0, 374 1, 375 1, 376 1 377 }; 378 test_localeconv("hr_HR.ISO8859-2", &lconv_hr); 379 380 const lconv lconv_de_CH = { 381 (char*)".", 382 (char*)"'", 383 (char*)"\x03", 384 (char*)"CHF ", 385 (char*)"CHF", 386 (char*)".", 387 (char*)"'", 388 (char*)"\x03", 389 (char*)"", 390 (char*)"-", 391 2, 392 2, 393 1, 394 1, 395 1, 396 0, 397 4, 398 4, 399 1, 400 1, 401 1, 402 0, 403 4, 404 4 405 }; 406 test_localeconv("de_CH", &lconv_de_CH); 407 408 const lconv lconv_gu_IN = { 409 (char*)".", 410 (char*)",", 411 (char*)"\x03\x02", 412 (char*)"INR ", 413 (char*)"\xE2\x82\xB9", 414 (char*)".", 415 (char*)",", 416 (char*)"\x03\x02", 417 (char*)"", 418 (char*)"-", 419 2, 420 2, 421 1, 422 1, 423 1, 424 1, 425 1, 426 1, 427 1, 428 1, 429 1, 430 1, 431 1, 432 1 433 }; 434 test_localeconv("gu_IN", &lconv_gu_IN); 435 436 const lconv lconv_it = { 437 (char*)",", 438 (char*)".", 439 (char*)"\x03", 440 (char*)"EUR ", 441 (char*)"€", 442 (char*)",", 443 (char*)".", 444 (char*)"\x03", 445 (char*)"", 446 (char*)"-", 447 2, 448 2, 449 1, 450 1, 451 1, 452 1, 453 1, 454 1, 455 1, 456 1, 457 1, 458 1, 459 1, 460 1 461 }; 462 test_localeconv("it_IT", &lconv_it); 463 464 const lconv lconv_nl = { 465 (char*)",", 466 (char*)".", 467 (char*)"\x03", 468 (char*)"EUR ", 469 (char*)"€", 470 (char*)",", 471 (char*)".", 472 (char*)"\x03", 473 (char*)"", 474 (char*)"-", 475 2, 476 2, 477 1, 478 1, 479 1, 480 1, 481 2, 482 2, 483 1, 484 1, 485 1, 486 1, 487 2, 488 2 489 }; 490 test_localeconv("nl_NL", &lconv_nl); 491 492 const lconv lconv_nb = { 493 (char*)",", 494 (char*)" ", 495 (char*)"\x03", 496 (char*)"NOK ", 497 (char*)"kr", 498 (char*)",", 499 (char*)" ", 500 (char*)"\x03", 501 (char*)"", 502 (char*)"-", 503 2, 504 2, 505 1, 506 1, 507 1, 508 1, 509 1, 510 1, 511 1, 512 1, 513 1, 514 1, 515 1, 516 1 517 }; 518 test_localeconv("nb_NO", &lconv_nb); 519 } 520 521 522 // #pragma mark - strftime ----------------------------------------------------- 523 524 525 struct strftime_data { 526 const char* format; 527 const char* result; 528 }; 529 530 531 void 532 test_strftime(const char* locale, const strftime_data data[]) 533 { 534 setlocale(LC_TIME, locale); 535 printf("strftime for '%s'\n", locale); 536 537 time_t testTimeInSecs = 1279391169; // Sat Jul 17 18:26:09 2010 UTC 538 tm* testTime = localtime(&testTimeInSecs); 539 int problemCount = 0; 540 for(int i = 0; data[i].format != NULL; ++i) { 541 char buf[100]; 542 strftime(buf, 100, data[i].format, testTime); 543 if (strcmp(buf, data[i].result) != 0) { 544 printf("\tPROBLEM: strftime(\"%s\") = \"%s\" (expected \"%s\")\n", 545 data[i].format, buf, data[i].result); 546 problemCount++; 547 } 548 } 549 if (problemCount) 550 printf("\t%d problem(s) found!\n", problemCount); 551 else 552 printf("\tall fine\n"); 553 } 554 555 556 void 557 test_strftime() 558 { 559 setenv("TZ", "GMT", 1); 560 561 const strftime_data strftime_posix[] = { 562 { "%c", "Sat Jul 17 18:26:09 2010" }, 563 { "%x", "07/17/10" }, 564 { "%X", "18:26:09" }, 565 { "%a", "Sat" }, 566 { "%A", "Saturday" }, 567 { "%b", "Jul" }, 568 { "%B", "July" }, 569 { NULL, NULL } 570 }; 571 test_strftime("POSIX", strftime_posix); 572 573 const strftime_data strftime_de[] = { 574 { "%c", "Samstag, 17. Juli 2010 18:26:09 GMT" }, 575 { "%x", "17.07.2010" }, 576 { "%X", "18:26:09" }, 577 { "%a", "Sa." }, 578 { "%A", "Samstag" }, 579 { "%b", "Jul" }, 580 { "%B", "Juli" }, 581 { NULL, NULL } 582 }; 583 test_strftime("de_DE.UTF-8", strftime_de); 584 585 const strftime_data strftime_hr[] = { 586 { "%c", "subota, 17. srpnja 2010. 18:26:09 GMT" }, 587 { "%x", "17. 07. 2010." }, 588 { "%X", "18:26:09" }, 589 { "%a", "sub" }, 590 { "%A", "subota" }, 591 { "%b", "srp" }, 592 { "%B", "srpnja" }, 593 { NULL, NULL } 594 }; 595 test_strftime("hr_HR.ISO8859-2", strftime_hr); 596 597 const strftime_data strftime_gu[] = { 598 { "%c", "શનિવાર, 17 જુલાઈ, 2010 06:26:09 PM GMT" }, 599 { "%x", "17 જુલાઈ, 2010" }, 600 { "%X", "06:26:09 PM" }, 601 { "%a", "શનિ" }, 602 { "%A", "શનિવાર" }, 603 { "%b", "જુલાઈ" }, 604 { "%B", "જુલાઈ" }, 605 { NULL, NULL } 606 }; 607 test_strftime("gu_IN", strftime_gu); 608 609 const strftime_data strftime_it[] = { 610 { "%c", "sabato 17 luglio 2010 18:26:09 GMT" }, 611 { "%x", "17/lug/2010" }, 612 { "%X", "18:26:09" }, 613 { "%a", "sab" }, 614 { "%A", "sabato" }, 615 { "%b", "lug" }, 616 { "%B", "luglio" }, 617 { NULL, NULL } 618 }; 619 test_strftime("it_IT", strftime_it); 620 621 const strftime_data strftime_nl[] = { 622 { "%c", "zaterdag 17 juli 2010 18:26:09 GMT" }, 623 { "%x", "17 jul. 2010" }, 624 { "%X", "18:26:09" }, 625 { "%a", "za" }, 626 { "%A", "zaterdag" }, 627 { "%b", "jul." }, 628 { "%B", "juli" }, 629 { NULL, NULL } 630 }; 631 test_strftime("nl_NL", strftime_nl); 632 633 const strftime_data strftime_nb[] = { 634 { "%c", "kl. 18:26:09 GMT lørdag 17. juli 2010" }, 635 { "%x", "17. juli 2010" }, 636 { "%X", "18:26:09" }, 637 { "%a", "lør." }, 638 { "%A", "lørdag" }, 639 { "%b", "juli" }, 640 { "%B", "juli" }, 641 { NULL, NULL } 642 }; 643 test_strftime("nb_NO", strftime_nb); 644 } 645 646 647 // #pragma mark - strftime ----------------------------------------------------- 648 649 650 struct strptime_data { 651 const char* format; 652 const char* dateString; 653 }; 654 655 656 void 657 test_strptime(const char* locale, const strptime_data data[]) 658 { 659 setlocale(LC_TIME, locale); 660 printf("strptime for '%s'\n", locale); 661 662 time_t expectedTimeInSecs = 1279391169; // Sat Jul 17 18:26:09 2010 UTC 663 int problemCount = 0; 664 for(int i = 0; data[i].format != NULL; ++i) { 665 struct tm resultTime; 666 if (strptime(data[i].dateString, data[i].format, &resultTime) == NULL) { 667 printf("\tPROBLEM: strptime(\"%s\", \"%s\") failed\n", 668 data[i].dateString, data[i].format); 669 problemCount++; 670 } else { 671 time_t resultTimeInSecs = mktime(&resultTime); 672 if (resultTimeInSecs != expectedTimeInSecs) { 673 printf("\tPROBLEM: strptime(\"%s\", \"%s\") = \"%d\" (expected \"%d\")\n", 674 data[i].dateString, data[i].format, resultTimeInSecs, expectedTimeInSecs); 675 problemCount++; 676 } 677 } 678 } 679 if (problemCount) 680 printf("\t%d problem(s) found!\n", problemCount); 681 else 682 printf("\tall fine\n"); 683 } 684 685 686 void 687 test_strptime() 688 { 689 setenv("TZ", "GMT", 1); 690 691 const strptime_data strptime_posix[] = { 692 { "%c", "Sat Jul 17 18:26:09 2010" }, 693 { "%x", "07/17/10" }, 694 { "%X", "18:26:09" }, 695 { "%a", "Sat" }, 696 { "%A", "Saturday" }, 697 { "%b", "Jul" }, 698 { "%B", "July" }, 699 { NULL, NULL } 700 }; 701 test_strptime("POSIX", strptime_posix); 702 703 const strptime_data strptime_de[] = { 704 { "%c", "Samstag, 17. Juli 2010 18:26:09 GMT" }, 705 { "%x", "17.07.2010" }, 706 { "%X", "18:26:09" }, 707 { "%a", "Sa." }, 708 { "%A", "Samstag" }, 709 { "%b", "Jul" }, 710 { "%B", "Juli" }, 711 { NULL, NULL } 712 }; 713 test_strptime("de_DE.UTF-8", strptime_de); 714 715 const strptime_data strptime_hr[] = { 716 { "%c", "subota, 17. srpnja 2010. 18:26:09 GMT" }, 717 { "%x", "17. 07. 2010." }, 718 { "%X", "18:26:09" }, 719 { "%a", "sub" }, 720 { "%A", "subota" }, 721 { "%b", "srp" }, 722 { "%B", "srpnja" }, 723 { NULL, NULL } 724 }; 725 test_strptime("hr_HR.ISO8859-2", strptime_hr); 726 727 const strptime_data strptime_gu[] = { 728 { "%c", "શનિવાર, 17 જુલાઈ, 2010 06:26:09 PM GMT" }, 729 { "%x", "17 જુલાઈ, 2010" }, 730 { "%X", "06:26:09 PM" }, 731 { "%a", "શનિ" }, 732 { "%A", "શનિવાર" }, 733 { "%b", "જુલાઈ" }, 734 { "%B", "જુલાઈ" }, 735 { NULL, NULL } 736 }; 737 test_strptime("gu_IN", strptime_gu); 738 739 const strptime_data strptime_it[] = { 740 { "%c", "sabato 17 luglio 2010 18:26:09 GMT" }, 741 { "%x", "17/lug/2010" }, 742 { "%X", "18:26:09" }, 743 { "%a", "sab" }, 744 { "%A", "sabato" }, 745 { "%b", "lug" }, 746 { "%B", "luglio" }, 747 { NULL, NULL } 748 }; 749 test_strptime("it_IT", strptime_it); 750 751 const strptime_data strptime_nl[] = { 752 { "%c", "zaterdag 17 juli 2010 18:26:09 GMT" }, 753 { "%x", "17 jul. 2010" }, 754 { "%X", "18:26:09" }, 755 { "%a", "za" }, 756 { "%A", "zaterdag" }, 757 { "%b", "jul." }, 758 { "%B", "juli" }, 759 { NULL, NULL } 760 }; 761 test_strptime("nl_NL", strptime_nl); 762 763 const strptime_data strptime_nb[] = { 764 { "%c", "kl. 18:26:09 GMT lørdag 17. juli 2010" }, 765 { "%x", "17. juli 2010" }, 766 { "%X", "18:26:09" }, 767 { "%a", "lør." }, 768 { "%A", "lørdag" }, 769 { "%b", "juli" }, 770 { "%B", "juli" }, 771 { NULL, NULL } 772 }; 773 test_strptime("nb_NO", strptime_nb); 774 } 775 776 // #pragma mark - ctype -------------------------------------------------------- 777 778 779 unsigned short 780 determineFullClassInfo(int i) 781 { 782 unsigned short classInfo = 0; 783 784 if (isblank(i)) 785 classInfo |= _ISblank; 786 if (iscntrl(i)) 787 classInfo |= _IScntrl; 788 if (ispunct(i)) 789 classInfo |= _ISpunct; 790 if (isalnum(i)) 791 classInfo |= _ISalnum; 792 if (isupper(i)) 793 classInfo |= _ISupper; 794 if (islower(i)) 795 classInfo |= _ISlower; 796 if (isalpha(i)) 797 classInfo |= _ISalpha; 798 if (isdigit(i)) 799 classInfo |= _ISdigit; 800 if (isxdigit(i)) 801 classInfo |= _ISxdigit; 802 if (isspace(i)) 803 classInfo |= _ISspace; 804 if (isprint(i)) 805 classInfo |= _ISprint; 806 if (isgraph(i)) 807 classInfo |= _ISgraph; 808 809 return classInfo; 810 } 811 812 813 void 814 test_ctype(const char* locale, const unsigned short int classInfos[], 815 const int toLowerMap[], const int toUpperMap[]) 816 { 817 setlocale(LC_CTYPE, locale); 818 printf("ctype of %s locale\n", locale); 819 820 int problemCount = 0; 821 for (int i = -1; i < 256; ++i) { 822 unsigned short classInfo = determineFullClassInfo(i); 823 824 if (i < 255) { 825 char iAsChar = (char)i; 826 unsigned short classInfoFromChar = determineFullClassInfo(iAsChar); 827 828 if (classInfo != classInfoFromChar) { 829 printf("\tPROBLEM: ctype((int)%d)=%x, but ctype((char)%d)=%x\n", 830 i, classInfo, i, classInfoFromChar); 831 problemCount++; 832 } 833 } 834 if (classInfo != classInfos[i + 1]) { 835 printf("\tPROBLEM: ctype(%d) = %x (expected %x)\n", i, classInfo, 836 classInfos[i + 1]); 837 problemCount++; 838 } 839 int lower = tolower(i); 840 if (lower != toLowerMap[i + 1]) { 841 printf("\tPROBLEM: tolower(%d) = %x (expected %x)\n", i, lower, 842 toLowerMap[i + 1]); 843 problemCount++; 844 } 845 int upper = toupper(i); 846 if (upper != toUpperMap[i + 1]) { 847 printf("\tPROBLEM: toupper(%d) = %x (expected %x)\n", i, upper, 848 toUpperMap[i + 1]); 849 problemCount++; 850 } 851 } 852 if (problemCount) 853 printf("\t%d problem(s) found!\n", problemCount); 854 else 855 printf("\tall fine\n"); 856 } 857 858 859 void 860 test_ctype() 861 { 862 const unsigned short int classInfos_posix[257] = { 863 /* -1 */ 0, // neutral value 864 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 865 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 866 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 867 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 868 /* 32 */ _ISblank|_ISspace|_ISprint, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 869 /* 40 */ _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 870 /* 48 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, 871 /* 56 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 872 /* 64 */ _ISpunct|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 873 /* 72 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 874 /* 80 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 875 /* 88 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 876 /* 96 */ _ISpunct|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 877 /* 104 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 878 /* 112 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 879 /* 120 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _IScntrl, 880 /* 128 */ 0, 0, 0, 0, 0, 0, 0, 0, 881 /* 136 */ 0, 0, 0, 0, 0, 0, 0, 0, 882 /* 144 */ 0, 0, 0, 0, 0, 0, 0, 0, 883 /* 152 */ 0, 0, 0, 0, 0, 0, 0, 0, 884 /* 160 */ 0, 0, 0, 0, 0, 0, 0, 0, 885 /* 168 */ 0, 0, 0, 0, 0, 0, 0, 0, 886 /* 176 */ 0, 0, 0, 0, 0, 0, 0, 0, 887 /* 184 */ 0, 0, 0, 0, 0, 0, 0, 0, 888 /* 192 */ 0, 0, 0, 0, 0, 0, 0, 0, 889 /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0, 890 /* 208 */ 0, 0, 0, 0, 0, 0, 0, 0, 891 /* 216 */ 0, 0, 0, 0, 0, 0, 0, 0, 892 /* 224 */ 0, 0, 0, 0, 0, 0, 0, 0, 893 /* 232 */ 0, 0, 0, 0, 0, 0, 0, 0, 894 /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0, 895 /* 248 */ 0, 0, 0, 0, 0, 0, 0, 0, 896 }; 897 const int toLowerMap_posix[257] = { 898 /* -1 */ -1, // identity value 899 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 900 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 901 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 902 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 903 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 904 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 905 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 906 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 907 /* 64 */ 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 908 /* 72 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 909 /* 80 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 910 /* 88 */ 'x', 'y', 'z', 91, 92, 93, 94, 95, 911 /* 96 */ 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 912 /* 104 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 913 /* 112 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 914 /* 120 */ 'x', 'y', 'z', 123, 124, 125, 126, 127, 915 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 916 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 917 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 918 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 919 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 920 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 921 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 922 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 923 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 924 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 925 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 926 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 927 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 928 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 929 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 930 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 931 }; 932 const int toUpperMap_posix[257] = { 933 /* -1 */ -1, // identity value 934 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 935 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 936 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 937 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 938 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 939 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 940 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 941 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 942 /* 64 */ 64, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 943 /* 72 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 944 /* 80 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 945 /* 88 */ 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 946 /* 96 */ 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 947 /* 104 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 948 /* 112 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 949 /* 120 */ 'X', 'Y', 'Z', 123, 124, 125, 126, 127, 950 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 951 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 952 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 953 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 954 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 955 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 956 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 957 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 958 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 959 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 960 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 961 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 962 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 963 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 964 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 965 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 966 }; 967 test_ctype("POSIX", classInfos_posix, toLowerMap_posix, toUpperMap_posix); 968 969 const unsigned short int classInfos_de[257] = { 970 /* -1 */ 0, // neutral value 971 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 972 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 973 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 974 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 975 /* 32 */ _ISblank|_ISspace|_ISprint, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 976 /* 40 */ _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 977 /* 48 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, 978 /* 56 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 979 /* 64 */ _ISpunct|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 980 /* 72 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 981 /* 80 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 982 /* 88 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 983 /* 96 */ _ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 984 /* 104 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 985 /* 112 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 986 /* 120 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _IScntrl, 987 /* 128 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl|_ISspace, _IScntrl, _IScntrl, 988 /* 136 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 989 /* 144 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 990 /* 152 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 991 /* 160 */ _ISprint|_ISspace|_ISblank, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, 992 /* 168 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, 993 /* 176 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISpunct, 994 /* 184 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISpunct, 995 /* 192 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, 996 /* 200 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, 997 /* 208 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph, 998 /* 216 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, 999 /* 224 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, 1000 /* 232 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, 1001 /* 240 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph, 1002 /* 248 */ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, 1003 }; 1004 const int toLowerMap_de[257] = { 1005 /* -1 */ -1, // identity value 1006 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 1007 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 1008 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 1009 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 1010 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 1011 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 1012 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 1013 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 1014 /* 64 */ 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 1015 /* 72 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 1016 /* 80 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 1017 /* 88 */ 'x', 'y', 'z', 91, 92, 93, 94, 95, 1018 /* 96 */ 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 1019 /* 104 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 1020 /* 112 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 1021 /* 120 */ 'x', 'y', 'z', 123, 124, 125, 126, 127, 1022 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 1023 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 1024 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 1025 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 1026 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 1027 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 1028 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 1029 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 1030 /* 192 */ 224, 225, 226, 227, 228, 229, 230, 231, 1031 /* 200 */ 232, 233, 234, 235, 236, 237, 238, 239, 1032 /* 208 */ 240, 241, 242, 243, 244, 245, 246, 215, 1033 /* 216 */ 248, 249, 250, 251, 252, 253, 254, 223, 1034 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 1035 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 1036 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 1037 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 1038 }; 1039 const int toUpperMap_de[257] = { 1040 /* -1 */ -1, // identity value 1041 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 1042 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 1043 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 1044 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 1045 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 1046 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 1047 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 1048 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 1049 /* 64 */ 64, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 1050 /* 72 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 1051 /* 80 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 1052 /* 88 */ 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 1053 /* 96 */ 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 1054 /* 104 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 1055 /* 112 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 1056 /* 120 */ 'X', 'Y', 'Z', 123, 124, 125, 126, 127, 1057 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 1058 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 1059 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 1060 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 1061 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 1062 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 1063 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 1064 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 1065 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 1066 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 1067 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 1068 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 1069 /* 224 */ 192, 193, 194, 195, 196, 197, 198, 199, 1070 /* 232 */ 200, 201, 202, 203, 204, 205, 206, 207, 1071 /* 240 */ 208, 209, 210, 211, 212, 213, 214, 247, 1072 /* 248 */ 216, 217, 218, 219, 220, 221, 222, 255, 1073 }; 1074 test_ctype("de_DE.ISO8859-1", classInfos_de, toLowerMap_de, toUpperMap_de); 1075 1076 const unsigned short int classInfos_utf8[257] = { 1077 /* -1 */ 0, // neutral value 1078 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 1079 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 1080 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 1081 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 1082 /* 32 */ _ISblank|_ISspace|_ISprint, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 1083 /* 40 */ _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 1084 /* 48 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, 1085 /* 56 */ _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISdigit|_ISxdigit|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 1086 /* 64 */ _ISpunct|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 1087 /* 72 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 1088 /* 80 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, 1089 /* 88 */ _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISupper|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 1090 /* 96 */ _ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 1091 /* 104 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 1092 /* 112 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, 1093 /* 120 */ _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISalnum|_ISlower|_ISalpha|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _IScntrl, 1094 /* 128 */ 0, 0, 0, 0, 0, 0, 0, 0, 1095 /* 136 */ 0, 0, 0, 0, 0, 0, 0, 0, 1096 /* 144 */ 0, 0, 0, 0, 0, 0, 0, 0, 1097 /* 152 */ 0, 0, 0, 0, 0, 0, 0, 0, 1098 /* 160 */ 0, 0, 0, 0, 0, 0, 0, 0, 1099 /* 168 */ 0, 0, 0, 0, 0, 0, 0, 0, 1100 /* 176 */ 0, 0, 0, 0, 0, 0, 0, 0, 1101 /* 184 */ 0, 0, 0, 0, 0, 0, 0, 0, 1102 /* 192 */ 0, 0, 0, 0, 0, 0, 0, 0, 1103 /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0, 1104 /* 208 */ 0, 0, 0, 0, 0, 0, 0, 0, 1105 /* 216 */ 0, 0, 0, 0, 0, 0, 0, 0, 1106 /* 224 */ 0, 0, 0, 0, 0, 0, 0, 0, 1107 /* 232 */ 0, 0, 0, 0, 0, 0, 0, 0, 1108 /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0, 1109 /* 248 */ 0, 0, 0, 0, 0, 0, 0, 0, 1110 }; 1111 test_ctype("de_DE.UTF-8", classInfos_utf8, toLowerMap_posix, 1112 toUpperMap_posix); 1113 } 1114 1115 1116 // #pragma mark - wctype ------------------------------------------------------- 1117 1118 1119 unsigned short 1120 determineWideFullClassInfo(int i) 1121 { 1122 unsigned short classInfo = 0; 1123 1124 if (iswblank(i)) 1125 classInfo |= _ISblank; 1126 if (iswcntrl(i)) 1127 classInfo |= _IScntrl; 1128 if (iswpunct(i)) 1129 classInfo |= _ISpunct; 1130 if (iswalnum(i)) 1131 classInfo |= _ISalnum; 1132 if (iswupper(i)) 1133 classInfo |= _ISupper; 1134 if (iswlower(i)) 1135 classInfo |= _ISlower; 1136 if (iswalpha(i)) 1137 classInfo |= _ISalpha; 1138 if (iswdigit(i)) 1139 classInfo |= _ISdigit; 1140 if (iswxdigit(i)) 1141 classInfo |= _ISxdigit; 1142 if (iswspace(i)) 1143 classInfo |= _ISspace; 1144 if (iswprint(i)) 1145 classInfo |= _ISprint; 1146 if (iswgraph(i)) 1147 classInfo |= _ISgraph; 1148 1149 return classInfo; 1150 } 1151 1152 1153 void 1154 test_wctype(const char* locale, const wchar_t* text, 1155 const unsigned short int wcs[], const unsigned short int classInfos[]) 1156 { 1157 setlocale(LC_CTYPE, locale); 1158 printf("wctype of %s locale\n", locale); 1159 1160 int problemCount = 0; 1161 unsigned short classInfo = determineWideFullClassInfo(WEOF); 1162 if (classInfo != 0) { 1163 printf("\tPROBLEM: classinfo for WEOF = %x (expected 0)\n", classInfo); 1164 problemCount++; 1165 } 1166 wint_t wc = *text; 1167 for (int i = 0; i < 48; wc = *++text, ++i) { 1168 classInfo = determineWideFullClassInfo(wc); 1169 if (wc != wcs[i]) { 1170 printf("\tPROBLEM: wc for char #%d = %x (expected %x)\n", i, wc, 1171 wcs[i]); 1172 problemCount++; 1173 } 1174 1175 if (classInfo != classInfos[i]) { 1176 printf("\tPROBLEM: classinfo for #%d = %x (expected %x)\n", i, 1177 classInfo, classInfos[i]); 1178 problemCount++; 1179 } 1180 } 1181 if (problemCount) 1182 printf("\t%d problem(s) found!\n", problemCount); 1183 else 1184 printf("\tall fine\n"); 1185 } 1186 1187 1188 void 1189 test_wctype() 1190 { 1191 // haiku wide chars are always in UTF32, so nothing should change between 1192 // different locales 1193 1194 const wchar_t* text = L"Hi there, how do you do? (äÜößáéúíó€'¤¹²$%#@) 12"; 1195 1196 const unsigned short int wcs[48] = { 1197 0x48, 0x69, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 1198 0x2c, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x64, 0x6f, 1199 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x3f, 1200 0x20, 0x28, 0xe4, 0xdc, 0xf6, 0xdf, 0xe1, 0xe9, 1201 0xfa, 0xed, 0xf3, 0x20ac, 0x27, 0xa4, 0xb9, 0xb2, 1202 0x24, 0x25, 0x23, 0x40, 0x29, 0x20, 0x31, 0x32 1203 }; 1204 const unsigned short int classInfos[48] = { 1205 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISupper, 1206 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1207 _ISspace|_ISprint|_ISblank, 1208 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1209 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1210 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1211 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1212 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1213 _ISprint|_ISgraph|_ISpunct, 1214 _ISspace|_ISprint|_ISblank, 1215 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1216 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1217 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1218 _ISspace|_ISprint|_ISblank, 1219 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1220 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1221 _ISspace|_ISprint|_ISblank, 1222 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1223 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1224 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1225 _ISspace|_ISprint|_ISblank, 1226 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1227 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1228 _ISprint|_ISgraph|_ISpunct, 1229 _ISspace|_ISprint|_ISblank, 1230 _ISprint|_ISgraph|_ISpunct, 1231 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1232 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISupper, 1233 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1234 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1235 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1236 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1237 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1238 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1239 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1240 _ISprint|_ISgraph, 1241 _ISprint|_ISgraph|_ISpunct, 1242 _ISprint|_ISgraph, 1243 _ISprint|_ISgraph, 1244 _ISprint|_ISgraph, 1245 _ISprint|_ISgraph, 1246 _ISpunct|_ISprint|_ISgraph, 1247 _ISpunct|_ISprint|_ISgraph, 1248 _ISpunct|_ISprint|_ISgraph, 1249 _ISpunct|_ISprint|_ISgraph, 1250 _ISspace|_ISprint|_ISblank, 1251 _ISprint|_ISgraph|_ISalnum|_ISdigit|_ISxdigit, 1252 _ISprint|_ISgraph|_ISalnum|_ISdigit|_ISxdigit 1253 }; 1254 1255 test_wctype("POSIX", text, wcs, classInfos); 1256 test_wctype("de_DE.ISO8859-1", text, wcs, classInfos); 1257 test_wctype("de_DE.ISO8859-15", text, wcs, classInfos); 1258 test_wctype("de_DE.UTF-8", text, wcs, classInfos); 1259 } 1260 1261 1262 // #pragma mark - wctrans ------------------------------------------------------ 1263 1264 1265 void 1266 test_wctrans(const char* locale, const wchar_t* text, wctrans_t transition, 1267 const wchar_t* expectedResult) 1268 { 1269 setlocale(LC_CTYPE, locale); 1270 printf("towctrans(%s) of %s locale\n", 1271 transition == _ISlower ? "tolower" : "toupper", locale); 1272 1273 int problemCount = 0; 1274 wint_t wc = *text; 1275 for (int i = 0; wc != 0; wc = *++text, ++i) { 1276 errno = 0; 1277 wint_t result = towctrans(wc, transition); 1278 if (result != expectedResult[i] || errno != 0) { 1279 printf("\tPROBLEM: result for char #%d = %x (expected %x), " 1280 "errno = %x (expected %x)\n", 1281 i, result, expectedResult[i], errno, 0); 1282 problemCount++; 1283 } 1284 } 1285 if (problemCount) 1286 printf("\t%d problem(s) found!\n", problemCount); 1287 else 1288 printf("\tall fine\n"); 1289 } 1290 1291 1292 void 1293 test_wctrans() 1294 { 1295 // haiku wide chars are always in UTF32, so nothing should change between 1296 // different locales 1297 1298 setlocale(LC_CTYPE, "POSIX"); 1299 printf("wctrans setup\n"); 1300 1301 int problemCount = 0; 1302 errno = 0; 1303 wctrans_t toU = wctrans("toupper"); 1304 if (errno != 0 || toU != _ISupper) { 1305 printf("\tPROBLEM: wctrans(\"upper\") = %x (expected %x), " 1306 "errno=%x (expected %x)\n", 1307 toU, _ISupper, errno, 0); 1308 problemCount++; 1309 } 1310 errno = 0; 1311 wctrans_t toL = wctrans("tolower"); 1312 if (errno != 0 || toL != _ISlower) { 1313 printf("\tPROBLEM: wctrans(\"lower\") = %x (expected %x), " 1314 "errno=%x (expected %x)\n", 1315 toL, _ISlower, errno, 0); 1316 problemCount++; 1317 } 1318 errno = 0; 1319 wctrans_t invalid1 = wctrans(NULL); 1320 if (errno != EINVAL || invalid1 != 0) { 1321 printf("\tPROBLEM: wctrans(NULL) = %x (expected %x), " 1322 "errno=%x (expected %x)\n", 1323 invalid1, 0, errno, EINVAL); 1324 problemCount++; 1325 } 1326 errno = 0; 1327 wctrans_t invalid2 = wctrans("invalid"); 1328 if (errno != EINVAL || invalid2 != 0) { 1329 printf("\tPROBLEM: wctrans(\"invalid\") = %x (expected %x), " 1330 "errno=%x (expected %x)\n", 1331 invalid2, 0, errno, EINVAL); 1332 problemCount++; 1333 } 1334 if (problemCount) 1335 printf("\t%d problem(s) found!\n", problemCount); 1336 else 1337 printf("\tall fine\n"); 1338 1339 const wchar_t* text = L"Hi there, how do you do? (äÜößáéúíó€'¤¹²$%#@) 12"; 1340 const wchar_t* textU = L"HI THERE, HOW DO YOU DO? (ÄÜÖßÁÉÚÍÓ€'¤¹²$%#@) 12"; 1341 const wchar_t* textL = L"hi there, how do you do? (äüößáéúíó€'¤¹²$%#@) 12"; 1342 1343 test_wctrans("POSIX", text, toU, textU); 1344 test_wctrans("de_DE.ISO8859-1", text, toU, textU); 1345 test_wctrans("de_DE.ISO8859-15", text, toU, textU); 1346 test_wctrans("de_DE.UTF-8", text, toU, textU); 1347 test_wctrans("fr_Fr", text, toU, textU); 1348 1349 test_wctrans("POSIX", text, toL, textL); 1350 test_wctrans("de_DE.ISO8859-1", text, toL, textL); 1351 test_wctrans("de_DE.ISO8859-15", text, toL, textL); 1352 test_wctrans("de_DE.UTF-8", text, toL, textL); 1353 test_wctrans("fr_Fr", text, toL, textL); 1354 } 1355 1356 1357 // #pragma mark - wcwidth ------------------------------------------------------ 1358 1359 1360 void 1361 test_wcwidth() 1362 { 1363 setlocale(LC_ALL, "fr_FR.UTF-8"); 1364 printf("wcwidth()\n"); 1365 1366 /* many of the following tests have been copied from gnulib */ 1367 1368 int problemCount = 0; 1369 int result = 0; 1370 1371 /* Test width of ASCII characters. */ 1372 for (wchar_t wc = 0x20; wc < 0x7F; wc++) { 1373 result = wcwidth(wc); 1374 if (result != 1) { 1375 printf("\tPROBLEM: wcwidth(%x)=%x (expected %x)\n", wc, result, 1); 1376 problemCount++; 1377 } 1378 } 1379 1380 struct { 1381 wchar_t wc; 1382 int result; 1383 } data[] = { 1384 { 0x0, 0 }, 1385 { 0x1, -1 }, 1386 { 0x1F, -1 }, 1387 { 0x80, -1 }, 1388 { 0x9F, -1 }, 1389 { 0xA0, 1 }, 1390 { 0x0301, 0 }, 1391 { 0x05B0, 0 }, 1392 { 0x200E, 0 }, 1393 { 0x2060, 0 }, 1394 { 0xE0001, 0 }, 1395 { 0xE0044, 0 }, 1396 { 0x200B, 0 }, 1397 { 0xFEFF, 0 }, 1398 { 0x3000, 2 }, 1399 { 0xB250, 2 }, 1400 { 0xFF1A, 2 }, 1401 { 0x20369, 2 }, 1402 { 0x2F876, 2 }, 1403 { 0x0, 0 }, 1404 }; 1405 for (int i = 0; data[i].wc != 0 || i == 0; i++) { 1406 result = wcwidth(data[i].wc); 1407 if (result != data[i].result) { 1408 printf("\tPROBLEM: wcwidth(%x)=%x (expected %x)\n", data[i].wc, 1409 result, data[i].result); 1410 problemCount++; 1411 } 1412 } 1413 1414 if (problemCount) 1415 printf("\t%d problem(s) found!\n", problemCount); 1416 else 1417 printf("\tall fine\n"); 1418 } 1419 1420 1421 // #pragma mark - nl_langinfo -------------------------------------------------- 1422 1423 1424 void 1425 test_langinfo(const char* locale, const char* langinfos[]) 1426 { 1427 setlocale(LC_ALL, locale); 1428 printf("langinfo of %s locale\n", locale); 1429 1430 int problemCount = 0; 1431 for (int i = -1; langinfos[i + 1] != NULL; ++i) { 1432 const char* langinfo = nl_langinfo(i); 1433 if (strcmp(langinfo, langinfos[i + 1]) != 0) { 1434 printf("\tPROBLEM: langinfo for #%d = '%s' (expected '%s')\n", i, 1435 langinfo, langinfos[i + 1]); 1436 problemCount++; 1437 } 1438 } 1439 if (problemCount) 1440 printf("\t%d problem(s) found!\n", problemCount); 1441 else 1442 printf("\tall fine\n"); 1443 } 1444 1445 1446 void 1447 test_langinfo() 1448 { 1449 const char* li_posix[] = { 1450 "", // out of bounds 1451 "US-ASCII", 1452 "%a %b %e %H:%M:%S %Y", 1453 "%m/%d/%y", 1454 "%H:%M:%S", 1455 "%I:%M:%S %p", 1456 "AM", 1457 "PM", 1458 1459 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 1460 "Saturday", 1461 1462 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 1463 1464 "January", "February", "March", "April", "May", "June", 1465 "July", "August", "September", "October", "November", "December", 1466 1467 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1468 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 1469 1470 "%EC, %Ey, %EY", 1471 "%Ex", 1472 "%Ec", 1473 "%EX", 1474 "%O", 1475 1476 ".", 1477 "", 1478 1479 "^[yY]", 1480 "^[nN]", 1481 1482 "", 1483 1484 "", // out of bounds 1485 NULL 1486 }; 1487 test_langinfo("POSIX", li_posix); 1488 1489 const char* li_de[] = { 1490 "", // out of bounds 1491 "UTF-8", 1492 "%A, %e. %B %Y %H:%M:%S %Z", 1493 "%d.%m.%Y", 1494 "%H:%M:%S", 1495 "%I:%M:%S %p", 1496 "vorm.", 1497 "nachm.", 1498 1499 "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", 1500 "Samstag", 1501 1502 "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", 1503 1504 "Januar", "Februar", "März", "April", "Mai", "Juni", 1505 "Juli", "August", "September", "Oktober", "November", "Dezember", 1506 1507 "Jan", "Feb", "Mär", "Apr", "Mai", "Jun", 1508 "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 1509 1510 "%EC, %Ey, %EY", 1511 "%Ex", 1512 "%Ec", 1513 "%EX", 1514 "%O", 1515 1516 ",", 1517 ".", 1518 1519 "^[yY]", 1520 "^[nN]", 1521 1522 "€", 1523 1524 "", // out of bounds 1525 NULL, 1526 }; 1527 test_langinfo("de_DE.UTF-8", li_de); 1528 1529 const char* li_de_iso[] = { 1530 "", // out of bounds 1531 "ISO8859-15", 1532 "%A, %e. %B %Y %H:%M:%S %Z", 1533 "%d.%m.%Y", 1534 "%H:%M:%S", 1535 "%I:%M:%S %p", 1536 "vorm.", 1537 "nachm.", 1538 1539 "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", 1540 "Samstag", 1541 1542 "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", 1543 1544 "Januar", "Februar", "M\xE4rz", "April", "Mai", "Juni", 1545 "Juli", "August", "September", "Oktober", "November", "Dezember", 1546 1547 "Jan", "Feb", "M\xE4r", "Apr", "Mai", "Jun", 1548 "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 1549 1550 "%EC, %Ey, %EY", 1551 "%Ex", 1552 "%Ec", 1553 "%EX", 1554 "%O", 1555 1556 ",", 1557 ".", 1558 1559 "^[yY]", 1560 "^[nN]", 1561 1562 "\xA4", 1563 1564 "", // out of bounds 1565 NULL 1566 }; 1567 test_langinfo("de_DE.ISO8859-15", li_de_iso); 1568 } 1569 1570 1571 // #pragma mark - collation ---------------------------------------------------- 1572 1573 1574 struct coll_data { 1575 const char* a; 1576 const char* b; 1577 int result; 1578 int err; 1579 }; 1580 1581 1582 static int sign (int a) 1583 { 1584 if (a < 0) 1585 return -1; 1586 if (a > 0) 1587 return 1; 1588 return 0; 1589 } 1590 1591 1592 void 1593 test_coll(bool useStrxfrm, const char* locale, const coll_data* coll) 1594 { 1595 setlocale(LC_COLLATE, locale); 1596 printf("%s in %s locale\n", useStrxfrm ? "strxfrm" : "strcoll", locale); 1597 1598 int problemCount = 0; 1599 for (unsigned int i = 0; coll[i].a != NULL; ++i) { 1600 errno = 0; 1601 int result; 1602 char funcCall[100]; 1603 if (useStrxfrm) { 1604 char sortKeyA[100], sortKeyB[100]; 1605 strxfrm(sortKeyA, coll[i].a, 100); 1606 strxfrm(sortKeyB, coll[i].b, 100); 1607 result = sign(strcmp(sortKeyA, sortKeyB)); 1608 sprintf(funcCall, "strcmp(strxfrm(\"%s\"), strxfrm(\"%s\"))", 1609 coll[i].a, coll[i].b); 1610 } else { 1611 result = sign(strcoll(coll[i].a, coll[i].b)); 1612 sprintf(funcCall, "strcoll(\"%s\", \"%s\")", coll[i].a, coll[i].b); 1613 } 1614 1615 if (result != coll[i].result || errno != coll[i].err) { 1616 printf( 1617 "\tPROBLEM: %s = %d (expected %d), errno = %x (expected %x)\n", 1618 funcCall, result, coll[i].result, errno, coll[i].err); 1619 problemCount++; 1620 } 1621 } 1622 if (problemCount) 1623 printf("\t%d problem(s) found!\n", problemCount); 1624 else 1625 printf("\tall fine\n"); 1626 } 1627 1628 1629 void 1630 test_collation() 1631 { 1632 const coll_data coll_posix[] = { 1633 { "", "", 0, 0 }, 1634 { "test", "test", 0, 0 }, 1635 { "tester", "test", 1, 0 }, 1636 { "tEst", "teSt", -1, 0 }, 1637 { "test", "tester", -1, 0 }, 1638 { "tast", "täst", -1, EINVAL }, 1639 { "tæst", "test", 1, EINVAL }, 1640 { NULL, NULL, 0, 0 }, 1641 }; 1642 test_coll(0, "POSIX", coll_posix); 1643 test_coll(1, "POSIX", coll_posix); 1644 1645 const coll_data coll_en[] = { 1646 { "", "", 0, 0 }, 1647 { "test", "test", 0, 0 }, 1648 { "tester", "test", 1, 0 }, 1649 { "tEst", "test", 1, 0 }, 1650 { "test", "tester", -1, 0 }, 1651 { "täst", "täst", 0, 0 }, 1652 { "tast", "täst", -1, 0 }, 1653 { "tbst", "täst", 1, 0 }, 1654 { "tbst", "tæst", 1, 0 }, 1655 { "täst", "tÄst", -1, 0 }, 1656 { "tBst", "tÄst", 1, 0 }, 1657 { "tBst", "täst", 1, 0 }, 1658 { "taest", "tæst", -1, 0 }, 1659 { "tafst", "tæst", 1, 0 }, 1660 { "taa", "täa", -1, 0 }, 1661 { "tab", "täb", -1, 0 }, 1662 { "tad", "täd", -1, 0 }, 1663 { "tae", "täe", -1, 0 }, 1664 { "taf", "täf", -1, 0 }, 1665 { "cote", "coté", -1, 0 }, 1666 { "coté", "côte", -1, 0 }, 1667 { "côte", "côté", -1, 0 }, 1668 { NULL, NULL, 0, 0 }, 1669 }; 1670 test_coll(0, "en_US.UTF-8", coll_en); 1671 test_coll(1, "en_US.UTF-8", coll_en); 1672 1673 const coll_data coll_de[] = { 1674 { "", "", 0, 0 }, 1675 { "test", "test", 0, 0 }, 1676 { "tester", "test", 1, 0 }, 1677 { "tEst", "test", 1, 0 }, 1678 { "test", "tester", -1, 0 }, 1679 { "täst", "täst", 0, 0 }, 1680 { "tast", "täst", -1, 0 }, 1681 { "tbst", "täst", 1, 0 }, 1682 { "tbst", "tæst", 1, 0 }, 1683 { "täst", "tÄst", -1, 0 }, 1684 { "tBst", "tÄst", 1, 0 }, 1685 { "tBst", "täst", 1, 0 }, 1686 { "taest", "tæst", -1, 0 }, 1687 { "tafst", "tæst", 1, 0 }, 1688 { "taa", "tä", 1, 0 }, 1689 { "tab", "tä", 1, 0 }, 1690 { "tad", "tä", 1, 0 }, 1691 { "tae", "tä", 1, 0 }, 1692 { "taf", "tä", 1, 0 }, 1693 { "cote", "coté", -1, 0 }, 1694 { "coté", "côte", -1, 0 }, 1695 { "côte", "côté", -1, 0 }, 1696 { NULL, NULL, 0, 0 }, 1697 }; 1698 test_coll(0, "de_DE.UTF-8", coll_de); 1699 test_coll(1, "de_DE.UTF-8", coll_de); 1700 1701 const coll_data coll_de_phonebook[] = { 1702 { "", "", 0, 0 }, 1703 { "test", "test", 0, 0 }, 1704 { "tester", "test", 1, 0 }, 1705 { "tEst", "test", 1, 0 }, 1706 { "test", "tester", -1, 0 }, 1707 { "täst", "täst", 0, 0 }, 1708 { "tast", "täst", 1, 0 }, 1709 { "tbst", "täst", 1, 0 }, 1710 { "tbst", "tæst", 1, 0 }, 1711 { "täst", "tÄst", -1, 0 }, 1712 { "tBst", "tÄst", 1, 0 }, 1713 { "tBst", "täst", 1, 0 }, 1714 { "taest", "tæst", -1, 0 }, 1715 { "tafst", "tæst", 1, 0 }, 1716 { "taa", "tä", -1, 0 }, 1717 { "tab", "tä", -1, 0 }, 1718 { "tad", "tä", -1, 0 }, 1719 { "tae", "tä", -1, 0 }, 1720 { "taf", "tä", 1, 0 }, 1721 { "cote", "coté", -1, 0 }, 1722 { "coté", "côte", -1, 0 }, 1723 { "côte", "côté", -1, 0 }, 1724 { NULL, NULL, 0, 0 }, 1725 }; 1726 test_coll(0, "de_DE.UTF-8@collation=phonebook", coll_de_phonebook); 1727 test_coll(1, "de_DE.UTF-8@collation=phonebook", coll_de_phonebook); 1728 1729 const coll_data coll_fr[] = { 1730 { "", "", 0, 0 }, 1731 { "test", "test", 0, 0 }, 1732 { "tester", "test", 1, 0 }, 1733 { "tEst", "test", 1, 0 }, 1734 { "test", "tester", -1, 0 }, 1735 { "täst", "täst", 0, 0 }, 1736 { "tast", "täst", -1, 0 }, 1737 { "tbst", "täst", 1, 0 }, 1738 { "tbst", "tæst", 1, 0 }, 1739 { "täst", "tÄst", -1, 0 }, 1740 { "tBst", "tÄst", 1, 0 }, 1741 { "tBst", "täst", 1, 0 }, 1742 { "taest", "tæst", -1, 0 }, 1743 { "tafst", "tæst", 1, 0 }, 1744 { "taa", "tä", 1, 0 }, 1745 { "tab", "tä", 1, 0 }, 1746 { "tad", "tä", 1, 0 }, 1747 { "tae", "tä", 1, 0 }, 1748 { "taf", "tä", 1, 0 }, 1749 { "cote", "coté", -1, 0 }, 1750 { "coté", "côte", 1, 0 }, 1751 { "côte", "côté", -1, 0 }, 1752 { NULL, NULL, 0, 0 }, 1753 }; 1754 // CLDR-1.9 has adjusted the defaults of fr_FR to no longer do reverse 1755 // ordering of secondary differences (accents), but fr_CA still does that 1756 // by default 1757 test_coll(0, "fr_CA.UTF-8", coll_fr); 1758 test_coll(1, "fr_CA.UTF-8", coll_fr); 1759 } 1760 1761 1762 // #pragma mark - time conversion ---------------------------------------------- 1763 1764 1765 void 1766 test_localtime(const char* tz, time_t nowSecs, const tm& expected) 1767 { 1768 setenv("TZ", tz, 1); 1769 printf("localtime for '%s'\n", tz); 1770 1771 tm now; 1772 tm* result = localtime_r(&nowSecs, &now); 1773 int problemCount = 0; 1774 if (result == NULL) { 1775 printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs); 1776 problemCount++; 1777 } 1778 if (now.tm_year != expected.tm_year) { 1779 printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n", 1780 now.tm_year, expected.tm_year); 1781 problemCount++; 1782 } 1783 if (now.tm_mon != expected.tm_mon) { 1784 printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n", 1785 now.tm_mon, expected.tm_mon); 1786 problemCount++; 1787 } 1788 if (now.tm_mday != expected.tm_mday) { 1789 printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n", 1790 now.tm_mday, expected.tm_mday); 1791 problemCount++; 1792 } 1793 if (now.tm_hour != expected.tm_hour) { 1794 printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n", 1795 now.tm_hour, expected.tm_hour); 1796 problemCount++; 1797 } 1798 if (now.tm_min != expected.tm_min) { 1799 printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n", 1800 now.tm_min, expected.tm_min); 1801 problemCount++; 1802 } 1803 if (now.tm_sec != expected.tm_sec) { 1804 printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n", 1805 now.tm_sec, expected.tm_sec); 1806 problemCount++; 1807 } 1808 if (now.tm_wday != expected.tm_wday) { 1809 printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n", 1810 now.tm_wday, expected.tm_wday); 1811 problemCount++; 1812 } 1813 if (now.tm_yday != expected.tm_yday) { 1814 printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n", 1815 now.tm_yday, expected.tm_yday); 1816 problemCount++; 1817 } 1818 if (now.tm_isdst != expected.tm_isdst) { 1819 printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n", 1820 now.tm_isdst, expected.tm_isdst); 1821 problemCount++; 1822 } 1823 if (now.tm_gmtoff != expected.tm_gmtoff) { 1824 printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n", 1825 now.tm_gmtoff, expected.tm_gmtoff); 1826 problemCount++; 1827 } 1828 if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) { 1829 printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n", 1830 now.tm_zone, expected.tm_zone); 1831 problemCount++; 1832 } 1833 if (problemCount) 1834 printf("\t%d problem(s) found!\n", problemCount); 1835 else 1836 printf("\tall fine\n"); 1837 } 1838 1839 1840 void 1841 test_gmtime(const char* tz, time_t nowSecs, const tm& expected) 1842 { 1843 setenv("TZ", tz, 1); 1844 printf("gmtime for '%s'\n", tz); 1845 1846 tm now; 1847 tm* result = gmtime_r(&nowSecs, &now); 1848 int problemCount = 0; 1849 if (result == NULL) { 1850 printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs); 1851 problemCount++; 1852 } 1853 if (now.tm_year != expected.tm_year) { 1854 printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n", 1855 now.tm_year, expected.tm_year); 1856 problemCount++; 1857 } 1858 if (now.tm_mon != expected.tm_mon) { 1859 printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n", 1860 now.tm_mon, expected.tm_mon); 1861 problemCount++; 1862 } 1863 if (now.tm_mday != expected.tm_mday) { 1864 printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n", 1865 now.tm_mday, expected.tm_mday); 1866 problemCount++; 1867 } 1868 if (now.tm_hour != expected.tm_hour) { 1869 printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n", 1870 now.tm_hour, expected.tm_hour); 1871 problemCount++; 1872 } 1873 if (now.tm_min != expected.tm_min) { 1874 printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n", 1875 now.tm_min, expected.tm_min); 1876 problemCount++; 1877 } 1878 if (now.tm_sec != expected.tm_sec) { 1879 printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n", 1880 now.tm_sec, expected.tm_sec); 1881 problemCount++; 1882 } 1883 if (now.tm_wday != expected.tm_wday) { 1884 printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n", 1885 now.tm_wday, expected.tm_wday); 1886 problemCount++; 1887 } 1888 if (now.tm_yday != expected.tm_yday) { 1889 printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n", 1890 now.tm_yday, expected.tm_yday); 1891 problemCount++; 1892 } 1893 if (now.tm_isdst != expected.tm_isdst) { 1894 printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n", 1895 now.tm_isdst, expected.tm_isdst); 1896 problemCount++; 1897 } 1898 if (now.tm_gmtoff != expected.tm_gmtoff) { 1899 printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n", 1900 now.tm_gmtoff, expected.tm_gmtoff); 1901 problemCount++; 1902 } 1903 if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) { 1904 printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n", 1905 now.tm_zone, expected.tm_zone); 1906 problemCount++; 1907 } 1908 if (problemCount) 1909 printf("\t%d problem(s) found!\n", problemCount); 1910 else 1911 printf("\tall fine\n"); 1912 } 1913 1914 1915 void 1916 test_mktime(const char* tz, tm& tm, time_t expected, int expectedWeekDay, 1917 int expectedYearDay) 1918 { 1919 setenv("TZ", tz, 1); 1920 printf("mktime for '%s'\n", tz); 1921 1922 time_t result = mktime(&tm); 1923 int problemCount = 0; 1924 if (result != expected) { 1925 printf("\tPROBLEM: mktime() = %ld (expected %ld)\n", result, expected); 1926 problemCount++; 1927 } 1928 if (tm.tm_wday != expectedWeekDay) { 1929 printf("\tPROBLEM: mktime().tm_wday = %d (expected %d)\n", 1930 tm.tm_wday, expectedWeekDay); 1931 problemCount++; 1932 } 1933 if (tm.tm_yday != expectedYearDay) { 1934 printf("\tPROBLEM: mktime().tm_yday = %d (expected %d)\n", 1935 tm.tm_yday, expectedYearDay); 1936 problemCount++; 1937 } 1938 if (problemCount) 1939 printf("\t%d problem(s) found!\n", problemCount); 1940 else 1941 printf("\tall fine\n"); 1942 } 1943 1944 1945 void 1946 test_timeconversions() 1947 { 1948 setlocale(LC_ALL, "en_US"); 1949 { 1950 time_t testTime = 1279391169; // Sat Jul 17 18:26:09 GMT 2010 1951 tm gtm = { 1952 9, 26, 18, 17, 6, 110, 6, 197, 0, 0, (char*)"GMT" 1953 }; 1954 test_localtime("GMT", testTime, gtm); 1955 test_gmtime("GMT", testTime, gtm); 1956 gtm.tm_wday = -1; 1957 gtm.tm_yday = -1; 1958 test_mktime("GMT", gtm, testTime, 6, 197); 1959 1960 tm gtmplus2 = { 1961 9, 26, 16, 17, 6, 110, 6, 197, 0, -2 * 3600, (char*)"GMT+2" 1962 }; 1963 test_localtime("GMT+2", testTime, gtmplus2); 1964 test_gmtime("GMT+2", testTime, gtm); 1965 gtmplus2.tm_wday = -1; 1966 gtmplus2.tm_yday = -1; 1967 test_mktime("GMT+2", gtmplus2, testTime, 6, 197); 1968 1969 tm gtmminus2 = { 1970 9, 26, 20, 17, 6, 110, 6, 197, 0, 2 * 3600, (char*)"GMT-2" 1971 }; 1972 test_localtime("GMT-2", testTime, gtmminus2); 1973 test_gmtime("GMT-2", testTime, gtm); 1974 gtmminus2.tm_wday = -1; 1975 gtmminus2.tm_yday = -1; 1976 test_mktime("GMT-2", gtmminus2, testTime, 6, 197); 1977 1978 tm btm = { 1979 9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST" 1980 }; 1981 test_localtime(":Europe/Berlin", testTime, btm); 1982 test_gmtime(":Europe/Berlin", testTime, gtm); 1983 btm.tm_wday = -1; 1984 btm.tm_yday = -1; 1985 test_mktime(":Europe/Berlin", btm, testTime, 6, 197); 1986 1987 tm ctm = { 1988 9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST" 1989 }; 1990 test_localtime("CET", testTime, ctm); 1991 test_gmtime("CET", testTime, gtm); 1992 ctm.tm_wday = -1; 1993 ctm.tm_yday = -1; 1994 test_mktime("CET", ctm, testTime, 6, 197); 1995 1996 tm latm = { 1997 9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT" 1998 }; 1999 test_localtime(":America/Los_Angeles", testTime, latm); 2000 test_gmtime(":America/Los_Angeles", testTime, gtm); 2001 latm.tm_wday = -1; 2002 latm.tm_yday = -1; 2003 test_mktime(":America/Los_Angeles", latm, testTime, 6, 197); 2004 2005 tm ttm = { 2006 9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"GMT+09:00" 2007 }; 2008 test_localtime(":Asia/Tokyo", testTime, ttm); 2009 test_gmtime(":Asia/Tokyo", testTime, gtm); 2010 ttm.tm_wday = -1; 2011 ttm.tm_yday = -1; 2012 test_mktime(":Asia/Tokyo", ttm, testTime, 0, 198); 2013 } 2014 2015 { 2016 time_t testTime = 1268159169; // Tue Mar 9 18:26:09 GMT 2010 2017 tm gtm = { 2018 9, 26, 18, 9, 2, 110, 2, 67, 0, 0, (char*)"GMT" 2019 }; 2020 test_localtime("GMT", testTime, gtm); 2021 test_gmtime("GMT", testTime, gtm); 2022 gtm.tm_wday = -1; 2023 gtm.tm_yday = -1; 2024 test_mktime("GMT", gtm, testTime, 2, 67); 2025 2026 tm btm = { 2027 9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET" 2028 }; 2029 test_localtime(":Europe/Berlin", testTime, btm); 2030 test_gmtime(":Europe/Berlin", testTime, gtm); 2031 btm.tm_wday = -1; 2032 btm.tm_yday = -1; 2033 test_mktime(":Europe/Berlin", btm, testTime, 2, 67); 2034 2035 tm ctm = { 2036 9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET" 2037 }; 2038 test_localtime("CET", testTime, ctm); 2039 test_gmtime("CET", testTime, gtm); 2040 ctm.tm_wday = -1; 2041 ctm.tm_yday = -1; 2042 test_mktime("CET", ctm, testTime, 2, 67); 2043 2044 tm latm = { 2045 9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST" 2046 }; 2047 test_localtime(":America/Los_Angeles", testTime, latm); 2048 test_gmtime(":America/Los_Angeles", testTime, gtm); 2049 latm.tm_wday = -1; 2050 latm.tm_yday = -1; 2051 test_mktime(":America/Los_Angeles", latm, testTime, 2, 67); 2052 2053 tm ttm = { 2054 9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"GMT+09:00" 2055 }; 2056 test_localtime(":Asia/Tokyo", testTime, ttm); 2057 test_gmtime(":Asia/Tokyo", testTime, gtm); 2058 ttm.tm_wday = -1; 2059 ttm.tm_yday = -1; 2060 test_mktime(":Asia/Tokyo", ttm, testTime, 3, 68); 2061 } 2062 2063 { 2064 time_t testTime = 0; // Thu Jan 1 00:00:00 GMT 1970 2065 tm gtm = { 2066 0, 0, 0, 1, 0, 70, 4, 0, 0, 0, (char*)"GMT" 2067 }; 2068 test_localtime("GMT", testTime, gtm); 2069 test_gmtime("GMT", testTime, gtm); 2070 gtm.tm_wday = -1; 2071 gtm.tm_yday = -1; 2072 test_mktime("GMT", gtm, testTime, 4, 0); 2073 2074 tm btm = { 2075 0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET" 2076 }; 2077 test_localtime(":Europe/Berlin", testTime, btm); 2078 test_gmtime(":Europe/Berlin", testTime, gtm); 2079 btm.tm_wday = -1; 2080 btm.tm_yday = -1; 2081 test_mktime(":Europe/Berlin", btm, testTime, 4, 0); 2082 2083 tm ctm = { 2084 0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET" 2085 }; 2086 test_localtime("CET", testTime, ctm); 2087 test_gmtime("CET", testTime, gtm); 2088 ctm.tm_wday = -1; 2089 ctm.tm_yday = -1; 2090 test_mktime("CET", ctm, testTime, 4, 0); 2091 2092 tm latm = { 2093 0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST" 2094 }; 2095 test_localtime(":America/Los_Angeles", testTime, latm); 2096 test_gmtime(":America/Los_Angeles", testTime, gtm); 2097 latm.tm_wday = -1; 2098 latm.tm_yday = -1; 2099 test_mktime(":America/Los_Angeles", latm, testTime, 3, 364); 2100 2101 tm ttm = { 2102 0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"GMT+09:00" 2103 }; 2104 test_localtime(":Asia/Tokyo", testTime, ttm); 2105 test_gmtime(":Asia/Tokyo", testTime, gtm); 2106 ttm.tm_wday = -1; 2107 ttm.tm_yday = -1; 2108 test_mktime(":Asia/Tokyo", ttm, testTime, 4, 0); 2109 } 2110 } 2111 2112 2113 // #pragma mark - printf ------------------------------------------------------- 2114 2115 2116 struct sprintf_data { 2117 const char* format; 2118 double value; 2119 const char* result; 2120 }; 2121 2122 2123 void 2124 test_sprintf(const char* locale, const sprintf_data data[]) 2125 { 2126 setlocale(LC_ALL, locale); 2127 printf("sprintf for '%s'\n", locale); 2128 2129 int problemCount = 0; 2130 for(int i = 0; data[i].format != NULL; ++i) { 2131 char buf[100]; 2132 if (strchr(data[i].format, 'd') != NULL) 2133 sprintf(buf, data[i].format, (int)data[i].value); 2134 else if (strchr(data[i].format, 'f') != NULL) 2135 sprintf(buf, data[i].format, data[i].value); 2136 if (strcmp(buf, data[i].result) != 0) { 2137 printf("\tPROBLEM: sprintf(\"%s\") = \"%s\" (expected \"%s\")\n", 2138 data[i].format, buf, data[i].result); 2139 problemCount++; 2140 } 2141 } 2142 if (problemCount) 2143 printf("\t%d problem(s) found!\n", problemCount); 2144 else 2145 printf("\tall fine\n"); 2146 } 2147 2148 2149 void 2150 test_sprintf() 2151 { 2152 const sprintf_data sprintf_posix[] = { 2153 { "%d", 123, "123" }, 2154 { "%d", -123, "-123" }, 2155 { "%d", 123456, "123456" }, 2156 { "%'d", 123456, "123456" }, 2157 { "%f", 123, "123.000000" }, 2158 { "%f", -123, "-123.000000" }, 2159 { "%.2f", 123456.789, "123456.79" }, 2160 { "%'.2f", 123456.789, "123456.79" }, 2161 { NULL, 0.0, NULL } 2162 }; 2163 test_sprintf("POSIX", sprintf_posix); 2164 2165 const sprintf_data sprintf_de[] = { 2166 { "%d", 123, "123" }, 2167 { "%d", -123, "-123" }, 2168 { "%d", 123456, "123456" }, 2169 { "%'d", 123456, "123.456" }, 2170 { "%f", 123, "123,000000" }, 2171 { "%f", -123, "-123,000000" }, 2172 { "%.2f", 123456.789, "123456,79" }, 2173 { "%'.2f", 123456.789, "123.456,79" }, 2174 { NULL, 0.0, NULL } 2175 }; 2176 test_sprintf("de_DE.UTF-8", sprintf_de); 2177 2178 const sprintf_data sprintf_gu[] = { 2179 { "%d", 123, "123" }, 2180 { "%d", -123, "-123" }, 2181 { "%d", 123456, "123456" }, 2182 { "%'d", 123456, "123,456" }, 2183 { "%f", 123, "123.000000" }, 2184 { "%f", -123, "-123.000000" }, 2185 { "%.2f", 123456.789, "123456.79" }, 2186 { "%'.2f", 123456.789, "1,23,456.79" }, 2187 { NULL, 0.0, NULL } 2188 }; 2189 test_sprintf("gu_IN", sprintf_gu); 2190 2191 const sprintf_data sprintf_nb[] = { 2192 { "%d", 123, "123" }, 2193 { "%d", -123, "-123" }, 2194 { "%d", 123456, "123456" }, 2195 { "%'d", 123456, "123 456" }, 2196 { "%f", 123, "123,000000" }, 2197 { "%f", -123, "-123,000000" }, 2198 { "%.2f", 123456.789, "123456,79" }, 2199 { "%'.2f", 123456.789, "123 456,79" }, 2200 { NULL, 0.0, NULL } 2201 }; 2202 test_sprintf("nb_NO", sprintf_nb); 2203 } 2204 2205 2206 // #pragma mark - main --------------------------------------------------------- 2207 2208 2209 /* 2210 * Test several different aspects of the POSIX locale and the functions 2211 * influenced by it. 2212 */ 2213 int 2214 main(void) 2215 { 2216 test_setlocale(); 2217 test_localeconv(); 2218 test_strftime(); 2219 test_strptime(); 2220 test_ctype(); 2221 test_wctype(); 2222 test_wctrans(); 2223 test_wcwidth(); 2224 test_langinfo(); 2225 test_collation(); 2226 test_timeconversions(); 2227 test_sprintf(); 2228 2229 return 0; 2230 } 2231