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 nowSecs = 1279391169; // pure magic 538 tm* now = localtime(&nowSecs); 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, now); 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 - ctype -------------------------------------------------------- 648 649 650 unsigned short 651 determineFullClassInfo(int i) 652 { 653 unsigned short classInfo = 0; 654 655 if (isblank(i)) 656 classInfo |= _ISblank; 657 if (iscntrl(i)) 658 classInfo |= _IScntrl; 659 if (ispunct(i)) 660 classInfo |= _ISpunct; 661 if (isalnum(i)) 662 classInfo |= _ISalnum; 663 if (isupper(i)) 664 classInfo |= _ISupper; 665 if (islower(i)) 666 classInfo |= _ISlower; 667 if (isalpha(i)) 668 classInfo |= _ISalpha; 669 if (isdigit(i)) 670 classInfo |= _ISdigit; 671 if (isxdigit(i)) 672 classInfo |= _ISxdigit; 673 if (isspace(i)) 674 classInfo |= _ISspace; 675 if (isprint(i)) 676 classInfo |= _ISprint; 677 if (isgraph(i)) 678 classInfo |= _ISgraph; 679 680 return classInfo; 681 } 682 683 684 void 685 test_ctype(const char* locale, const unsigned short int classInfos[], 686 const int toLowerMap[], const int toUpperMap[]) 687 { 688 setlocale(LC_CTYPE, locale); 689 printf("ctype of %s locale\n", locale); 690 691 int problemCount = 0; 692 for (int i = -1; i < 256; ++i) { 693 unsigned short classInfo = determineFullClassInfo(i); 694 695 if (i < 255) { 696 char iAsChar = (char)i; 697 unsigned short classInfoFromChar = determineFullClassInfo(iAsChar); 698 699 if (classInfo != classInfoFromChar) { 700 printf("\tPROBLEM: ctype((int)%d)=%x, but ctype((char)%d)=%x\n", 701 i, classInfo, i, classInfoFromChar); 702 problemCount++; 703 } 704 } 705 if (classInfo != classInfos[i + 1]) { 706 printf("\tPROBLEM: ctype(%d) = %x (expected %x)\n", i, classInfo, 707 classInfos[i + 1]); 708 problemCount++; 709 } 710 int lower = tolower(i); 711 if (lower != toLowerMap[i + 1]) { 712 printf("\tPROBLEM: tolower(%d) = %x (expected %x)\n", i, lower, 713 toLowerMap[i + 1]); 714 problemCount++; 715 } 716 int upper = toupper(i); 717 if (upper != toUpperMap[i + 1]) { 718 printf("\tPROBLEM: toupper(%d) = %x (expected %x)\n", i, upper, 719 toUpperMap[i + 1]); 720 problemCount++; 721 } 722 } 723 if (problemCount) 724 printf("\t%d problem(s) found!\n", problemCount); 725 else 726 printf("\tall fine\n"); 727 } 728 729 730 void 731 test_ctype() 732 { 733 const unsigned short int classInfos_posix[257] = { 734 /* -1 */ 0, // neutral value 735 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 736 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 737 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 738 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 739 /* 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, 740 /* 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, 741 /* 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, 742 /* 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, 743 /* 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, 744 /* 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, 745 /* 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, 746 /* 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, 747 /* 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, 748 /* 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, 749 /* 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, 750 /* 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, 751 /* 128 */ 0, 0, 0, 0, 0, 0, 0, 0, 752 /* 136 */ 0, 0, 0, 0, 0, 0, 0, 0, 753 /* 144 */ 0, 0, 0, 0, 0, 0, 0, 0, 754 /* 152 */ 0, 0, 0, 0, 0, 0, 0, 0, 755 /* 160 */ 0, 0, 0, 0, 0, 0, 0, 0, 756 /* 168 */ 0, 0, 0, 0, 0, 0, 0, 0, 757 /* 176 */ 0, 0, 0, 0, 0, 0, 0, 0, 758 /* 184 */ 0, 0, 0, 0, 0, 0, 0, 0, 759 /* 192 */ 0, 0, 0, 0, 0, 0, 0, 0, 760 /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0, 761 /* 208 */ 0, 0, 0, 0, 0, 0, 0, 0, 762 /* 216 */ 0, 0, 0, 0, 0, 0, 0, 0, 763 /* 224 */ 0, 0, 0, 0, 0, 0, 0, 0, 764 /* 232 */ 0, 0, 0, 0, 0, 0, 0, 0, 765 /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0, 766 /* 248 */ 0, 0, 0, 0, 0, 0, 0, 0, 767 }; 768 const int toLowerMap_posix[257] = { 769 /* -1 */ -1, // identity value 770 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 771 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 772 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 773 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 774 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 775 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 776 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 777 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 778 /* 64 */ 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 779 /* 72 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 780 /* 80 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 781 /* 88 */ 'x', 'y', 'z', 91, 92, 93, 94, 95, 782 /* 96 */ 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 783 /* 104 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 784 /* 112 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 785 /* 120 */ 'x', 'y', 'z', 123, 124, 125, 126, 127, 786 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 787 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 788 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 789 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 790 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 791 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 792 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 793 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 794 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 795 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 796 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 797 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 798 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 799 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 800 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 801 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 802 }; 803 const int toUpperMap_posix[257] = { 804 /* -1 */ -1, // identity value 805 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 806 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 807 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 808 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 809 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 810 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 811 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 812 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 813 /* 64 */ 64, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 814 /* 72 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 815 /* 80 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 816 /* 88 */ 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 817 /* 96 */ 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 818 /* 104 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 819 /* 112 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 820 /* 120 */ 'X', 'Y', 'Z', 123, 124, 125, 126, 127, 821 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 822 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 823 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 824 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 825 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 826 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 827 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 828 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 829 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 830 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 831 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 832 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 833 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 834 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 835 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 836 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 837 }; 838 test_ctype("POSIX", classInfos_posix, toLowerMap_posix, toUpperMap_posix); 839 840 const unsigned short int classInfos_de[257] = { 841 /* -1 */ 0, // neutral value 842 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 843 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 844 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 845 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 846 /* 32 */ _ISblank|_ISspace|_ISprint, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 847 /* 40 */ _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 848 /* 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, 849 /* 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, 850 /* 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, 851 /* 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, 852 /* 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, 853 /* 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, 854 /* 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, 855 /* 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, 856 /* 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, 857 /* 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, 858 /* 128 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl|_ISspace, _IScntrl, _IScntrl, 859 /* 136 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 860 /* 144 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 861 /* 152 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 862 /* 160 */ _ISprint|_ISspace|_ISblank, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, 863 /* 168 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, 864 /* 176 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISpunct, 865 /* 184 */ _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, _ISprint|_ISgraph|_ISpunct, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph, _ISprint|_ISgraph|_ISpunct, 866 /* 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, 867 /* 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, 868 /* 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, 869 /* 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, 870 /* 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, 871 /* 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, 872 /* 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, 873 /* 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, 874 }; 875 const int toLowerMap_de[257] = { 876 /* -1 */ -1, // identity value 877 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 878 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 879 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 880 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 881 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 882 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 883 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 884 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 885 /* 64 */ 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 886 /* 72 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 887 /* 80 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 888 /* 88 */ 'x', 'y', 'z', 91, 92, 93, 94, 95, 889 /* 96 */ 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 890 /* 104 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 891 /* 112 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 892 /* 120 */ 'x', 'y', 'z', 123, 124, 125, 126, 127, 893 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 894 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 895 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 896 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 897 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 898 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 899 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 900 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 901 /* 192 */ 224, 225, 226, 227, 228, 229, 230, 231, 902 /* 200 */ 232, 233, 234, 235, 236, 237, 238, 239, 903 /* 208 */ 240, 241, 242, 243, 244, 245, 246, 215, 904 /* 216 */ 248, 249, 250, 251, 252, 253, 254, 223, 905 /* 224 */ 224, 225, 226, 227, 228, 229, 230, 231, 906 /* 232 */ 232, 233, 234, 235, 236, 237, 238, 239, 907 /* 240 */ 240, 241, 242, 243, 244, 245, 246, 247, 908 /* 248 */ 248, 249, 250, 251, 252, 253, 254, 255, 909 }; 910 const int toUpperMap_de[257] = { 911 /* -1 */ -1, // identity value 912 /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 913 /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, 914 /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, 915 /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31, 916 /* 32 */ 32, 33, 34, 35, 36, 37, 38, 39, 917 /* 40 */ 40, 41, 42, 43, 44, 45, 46, 47, 918 /* 48 */ '0', '1', '2', '3', '4', '5', '6', '7', 919 /* 56 */ '8', '9', 58, 59, 60, 61, 62, 63, 920 /* 64 */ 64, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 921 /* 72 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 922 /* 80 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 923 /* 88 */ 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 924 /* 96 */ 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 925 /* 104 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 926 /* 112 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 927 /* 120 */ 'X', 'Y', 'Z', 123, 124, 125, 126, 127, 928 /* 128 */ 128, 129, 130, 131, 132, 133, 134, 135, 929 /* 136 */ 136, 137, 138, 139, 140, 141, 142, 143, 930 /* 144 */ 144, 145, 146, 147, 148, 149, 150, 151, 931 /* 152 */ 152, 153, 154, 155, 156, 157, 158, 159, 932 /* 160 */ 160, 161, 162, 163, 164, 165, 166, 167, 933 /* 168 */ 168, 169, 170, 171, 172, 173, 174, 175, 934 /* 176 */ 176, 177, 178, 179, 180, 181, 182, 183, 935 /* 184 */ 184, 185, 186, 187, 188, 189, 190, 191, 936 /* 192 */ 192, 193, 194, 195, 196, 197, 198, 199, 937 /* 200 */ 200, 201, 202, 203, 204, 205, 206, 207, 938 /* 208 */ 208, 209, 210, 211, 212, 213, 214, 215, 939 /* 216 */ 216, 217, 218, 219, 220, 221, 222, 223, 940 /* 224 */ 192, 193, 194, 195, 196, 197, 198, 199, 941 /* 232 */ 200, 201, 202, 203, 204, 205, 206, 207, 942 /* 240 */ 208, 209, 210, 211, 212, 213, 214, 247, 943 /* 248 */ 216, 217, 218, 219, 220, 221, 222, 255, 944 }; 945 test_ctype("de_DE.ISO8859-1", classInfos_de, toLowerMap_de, toUpperMap_de); 946 947 const unsigned short int classInfos_utf8[257] = { 948 /* -1 */ 0, // neutral value 949 /* 0 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 950 /* 8 */ _IScntrl, _ISblank|_IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl|_ISspace, _IScntrl, _IScntrl, 951 /* 16 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 952 /* 24 */ _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, _IScntrl, 953 /* 32 */ _ISblank|_ISspace|_ISprint, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 954 /* 40 */ _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, _ISpunct|_ISprint|_ISgraph, 955 /* 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, 956 /* 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, 957 /* 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, 958 /* 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, 959 /* 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, 960 /* 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, 961 /* 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, 962 /* 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, 963 /* 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, 964 /* 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, 965 /* 128 */ 0, 0, 0, 0, 0, 0, 0, 0, 966 /* 136 */ 0, 0, 0, 0, 0, 0, 0, 0, 967 /* 144 */ 0, 0, 0, 0, 0, 0, 0, 0, 968 /* 152 */ 0, 0, 0, 0, 0, 0, 0, 0, 969 /* 160 */ 0, 0, 0, 0, 0, 0, 0, 0, 970 /* 168 */ 0, 0, 0, 0, 0, 0, 0, 0, 971 /* 176 */ 0, 0, 0, 0, 0, 0, 0, 0, 972 /* 184 */ 0, 0, 0, 0, 0, 0, 0, 0, 973 /* 192 */ 0, 0, 0, 0, 0, 0, 0, 0, 974 /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0, 975 /* 208 */ 0, 0, 0, 0, 0, 0, 0, 0, 976 /* 216 */ 0, 0, 0, 0, 0, 0, 0, 0, 977 /* 224 */ 0, 0, 0, 0, 0, 0, 0, 0, 978 /* 232 */ 0, 0, 0, 0, 0, 0, 0, 0, 979 /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0, 980 /* 248 */ 0, 0, 0, 0, 0, 0, 0, 0, 981 }; 982 test_ctype("de_DE.UTF-8", classInfos_utf8, toLowerMap_posix, 983 toUpperMap_posix); 984 } 985 986 987 // #pragma mark - wctype ------------------------------------------------------- 988 989 990 unsigned short 991 determineWideFullClassInfo(int i) 992 { 993 unsigned short classInfo = 0; 994 995 if (iswblank(i)) 996 classInfo |= _ISblank; 997 if (iswcntrl(i)) 998 classInfo |= _IScntrl; 999 if (iswpunct(i)) 1000 classInfo |= _ISpunct; 1001 if (iswalnum(i)) 1002 classInfo |= _ISalnum; 1003 if (iswupper(i)) 1004 classInfo |= _ISupper; 1005 if (iswlower(i)) 1006 classInfo |= _ISlower; 1007 if (iswalpha(i)) 1008 classInfo |= _ISalpha; 1009 if (iswdigit(i)) 1010 classInfo |= _ISdigit; 1011 if (iswxdigit(i)) 1012 classInfo |= _ISxdigit; 1013 if (iswspace(i)) 1014 classInfo |= _ISspace; 1015 if (iswprint(i)) 1016 classInfo |= _ISprint; 1017 if (iswgraph(i)) 1018 classInfo |= _ISgraph; 1019 1020 return classInfo; 1021 } 1022 1023 1024 void 1025 test_wctype(const char* locale, const wchar_t* text, 1026 const unsigned short int wcs[], const unsigned short int classInfos[]) 1027 { 1028 setlocale(LC_CTYPE, locale); 1029 printf("wctype of %s locale\n", locale); 1030 1031 int problemCount = 0; 1032 unsigned short classInfo = determineWideFullClassInfo(WEOF); 1033 if (classInfo != 0) { 1034 printf("\tPROBLEM: classinfo for WEOF = %x (expected 0)\n", classInfo); 1035 problemCount++; 1036 } 1037 wint_t wc = *text; 1038 for (int i = 0; i < 48; wc = *++text, ++i) { 1039 classInfo = determineWideFullClassInfo(wc); 1040 if (wc != wcs[i]) { 1041 printf("\tPROBLEM: wc for char #%d = %x (expected %x)\n", i, wc, 1042 wcs[i]); 1043 problemCount++; 1044 } 1045 1046 if (classInfo != classInfos[i]) { 1047 printf("\tPROBLEM: classinfo for #%d = %x (expected %x)\n", i, 1048 classInfo, classInfos[i]); 1049 problemCount++; 1050 } 1051 } 1052 if (problemCount) 1053 printf("\t%d problem(s) found!\n", problemCount); 1054 else 1055 printf("\tall fine\n"); 1056 } 1057 1058 1059 void 1060 test_wctype() 1061 { 1062 // haiku wide chars are always in UTF32, so nothing should change between 1063 // different locales 1064 1065 const wchar_t* text = L"Hi there, how do you do? (äÜößáéúíó€'¤¹²$%#@) 12"; 1066 1067 const unsigned short int wcs[48] = { 1068 0x48, 0x69, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 1069 0x2c, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x64, 0x6f, 1070 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x3f, 1071 0x20, 0x28, 0xe4, 0xdc, 0xf6, 0xdf, 0xe1, 0xe9, 1072 0xfa, 0xed, 0xf3, 0x20ac, 0x27, 0xa4, 0xb9, 0xb2, 1073 0x24, 0x25, 0x23, 0x40, 0x29, 0x20, 0x31, 0x32 1074 }; 1075 const unsigned short int classInfos[48] = { 1076 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISupper, 1077 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1078 _ISspace|_ISprint|_ISblank, 1079 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1080 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1081 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1082 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1083 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1084 _ISprint|_ISgraph|_ISpunct, 1085 _ISspace|_ISprint|_ISblank, 1086 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1087 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1088 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1089 _ISspace|_ISprint|_ISblank, 1090 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1091 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1092 _ISspace|_ISprint|_ISblank, 1093 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1094 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1095 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1096 _ISspace|_ISprint|_ISblank, 1097 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower|_ISxdigit, 1098 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1099 _ISprint|_ISgraph|_ISpunct, 1100 _ISspace|_ISprint|_ISblank, 1101 _ISprint|_ISgraph|_ISpunct, 1102 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1103 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISupper, 1104 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1105 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1106 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1107 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1108 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1109 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1110 _ISprint|_ISgraph|_ISalpha|_ISalnum|_ISlower, 1111 _ISprint|_ISgraph, 1112 _ISprint|_ISgraph|_ISpunct, 1113 _ISprint|_ISgraph, 1114 _ISprint|_ISgraph, 1115 _ISprint|_ISgraph, 1116 _ISprint|_ISgraph, 1117 _ISpunct|_ISprint|_ISgraph, 1118 _ISpunct|_ISprint|_ISgraph, 1119 _ISpunct|_ISprint|_ISgraph, 1120 _ISpunct|_ISprint|_ISgraph, 1121 _ISspace|_ISprint|_ISblank, 1122 _ISprint|_ISgraph|_ISalnum|_ISdigit|_ISxdigit, 1123 _ISprint|_ISgraph|_ISalnum|_ISdigit|_ISxdigit 1124 }; 1125 1126 test_wctype("POSIX", text, wcs, classInfos); 1127 test_wctype("de_DE.ISO8859-1", text, wcs, classInfos); 1128 test_wctype("de_DE.ISO8859-15", text, wcs, classInfos); 1129 test_wctype("de_DE.UTF-8", text, wcs, classInfos); 1130 } 1131 1132 1133 // #pragma mark - wctrans ------------------------------------------------------ 1134 1135 1136 void 1137 test_wctrans(const char* locale, const wchar_t* text, wctrans_t transition, 1138 const wchar_t* expectedResult) 1139 { 1140 setlocale(LC_CTYPE, locale); 1141 printf("towctrans(%s) of %s locale\n", 1142 transition == _ISlower ? "tolower" : "toupper", locale); 1143 1144 int problemCount = 0; 1145 wint_t wc = *text; 1146 for (int i = 0; wc != 0; wc = *++text, ++i) { 1147 errno = 0; 1148 wint_t result = towctrans(wc, transition); 1149 if (result != expectedResult[i] || errno != 0) { 1150 printf("\tPROBLEM: result for char #%d = %x (expected %x), " 1151 "errno = %x (expected %x)\n", 1152 i, result, expectedResult[i], errno, 0); 1153 problemCount++; 1154 } 1155 } 1156 if (problemCount) 1157 printf("\t%d problem(s) found!\n", problemCount); 1158 else 1159 printf("\tall fine\n"); 1160 } 1161 1162 1163 void 1164 test_wctrans() 1165 { 1166 // haiku wide chars are always in UTF32, so nothing should change between 1167 // different locales 1168 1169 setlocale(LC_CTYPE, "POSIX"); 1170 printf("wctrans setup\n"); 1171 1172 int problemCount = 0; 1173 errno = 0; 1174 wctrans_t toU = wctrans("toupper"); 1175 if (errno != 0 || toU != _ISupper) { 1176 printf("\tPROBLEM: wctrans(\"upper\") = %x (expected %x), " 1177 "errno=%x (expected %x)\n", 1178 toU, _ISupper, errno, 0); 1179 problemCount++; 1180 } 1181 errno = 0; 1182 wctrans_t toL = wctrans("tolower"); 1183 if (errno != 0 || toL != _ISlower) { 1184 printf("\tPROBLEM: wctrans(\"lower\") = %x (expected %x), " 1185 "errno=%x (expected %x)\n", 1186 toL, _ISlower, errno, 0); 1187 problemCount++; 1188 } 1189 errno = 0; 1190 wctrans_t invalid1 = wctrans(NULL); 1191 if (errno != EINVAL || invalid1 != 0) { 1192 printf("\tPROBLEM: wctrans(NULL) = %x (expected %x), " 1193 "errno=%x (expected %x)\n", 1194 invalid1, 0, errno, EINVAL); 1195 problemCount++; 1196 } 1197 errno = 0; 1198 wctrans_t invalid2 = wctrans("invalid"); 1199 if (errno != EINVAL || invalid2 != 0) { 1200 printf("\tPROBLEM: wctrans(\"invalid\") = %x (expected %x), " 1201 "errno=%x (expected %x)\n", 1202 invalid2, 0, errno, EINVAL); 1203 problemCount++; 1204 } 1205 if (problemCount) 1206 printf("\t%d problem(s) found!\n", problemCount); 1207 else 1208 printf("\tall fine\n"); 1209 1210 const wchar_t* text = L"Hi there, how do you do? (äÜößáéúíó€'¤¹²$%#@) 12"; 1211 const wchar_t* textU = L"HI THERE, HOW DO YOU DO? (ÄÜÖßÁÉÚÍÓ€'¤¹²$%#@) 12"; 1212 const wchar_t* textL = L"hi there, how do you do? (äüößáéúíó€'¤¹²$%#@) 12"; 1213 1214 test_wctrans("POSIX", text, toU, textU); 1215 test_wctrans("de_DE.ISO8859-1", text, toU, textU); 1216 test_wctrans("de_DE.ISO8859-15", text, toU, textU); 1217 test_wctrans("de_DE.UTF-8", text, toU, textU); 1218 test_wctrans("fr_Fr", text, toU, textU); 1219 1220 test_wctrans("POSIX", text, toL, textL); 1221 test_wctrans("de_DE.ISO8859-1", text, toL, textL); 1222 test_wctrans("de_DE.ISO8859-15", text, toL, textL); 1223 test_wctrans("de_DE.UTF-8", text, toL, textL); 1224 test_wctrans("fr_Fr", text, toL, textL); 1225 } 1226 1227 1228 // #pragma mark - wcwidth ------------------------------------------------------ 1229 1230 1231 void 1232 test_wcwidth() 1233 { 1234 setlocale(LC_ALL, "fr_FR.UTF-8"); 1235 printf("wcwidth()\n"); 1236 1237 /* many of the following tests have been copied from gnulib */ 1238 1239 int problemCount = 0; 1240 int result = 0; 1241 1242 /* Test width of ASCII characters. */ 1243 for (wchar_t wc = 0x20; wc < 0x7F; wc++) { 1244 result = wcwidth(wc); 1245 if (result != 1) { 1246 printf("\tPROBLEM: wcwidth(%x)=%x (expected %x)\n", wc, result, 1); 1247 problemCount++; 1248 } 1249 } 1250 1251 struct { 1252 wchar_t wc; 1253 int result; 1254 } data[] = { 1255 { 0x0, 0 }, 1256 { 0x1, -1 }, 1257 { 0x1F, -1 }, 1258 { 0x80, -1 }, 1259 { 0x9F, -1 }, 1260 { 0xA0, 1 }, 1261 { 0x0301, 0 }, 1262 { 0x05B0, 0 }, 1263 { 0x200E, 0 }, 1264 { 0x2060, 0 }, 1265 { 0xE0001, 0 }, 1266 { 0xE0044, 0 }, 1267 { 0x200B, 0 }, 1268 { 0xFEFF, 0 }, 1269 { 0x3000, 2 }, 1270 { 0xB250, 2 }, 1271 { 0xFF1A, 2 }, 1272 { 0x20369, 2 }, 1273 { 0x2F876, 2 }, 1274 { 0x0, 0 }, 1275 }; 1276 for (int i = 0; data[i].wc != 0 || i == 0; i++) { 1277 result = wcwidth(data[i].wc); 1278 if (result != data[i].result) { 1279 printf("\tPROBLEM: wcwidth(%x)=%x (expected %x)\n", data[i].wc, 1280 result, data[i].result); 1281 problemCount++; 1282 } 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 // #pragma mark - nl_langinfo -------------------------------------------------- 1293 1294 1295 void 1296 test_langinfo(const char* locale, const char* langinfos[]) 1297 { 1298 setlocale(LC_ALL, locale); 1299 printf("langinfo of %s locale\n", locale); 1300 1301 int problemCount = 0; 1302 for (int i = -1; langinfos[i + 1] != NULL; ++i) { 1303 const char* langinfo = nl_langinfo(i); 1304 if (strcmp(langinfo, langinfos[i + 1]) != 0) { 1305 printf("\tPROBLEM: langinfo for #%d = '%s' (expected '%s')\n", i, 1306 langinfo, langinfos[i + 1]); 1307 problemCount++; 1308 } 1309 } 1310 if (problemCount) 1311 printf("\t%d problem(s) found!\n", problemCount); 1312 else 1313 printf("\tall fine\n"); 1314 } 1315 1316 1317 void 1318 test_langinfo() 1319 { 1320 const char* li_posix[] = { 1321 "", // out of bounds 1322 "US-ASCII", 1323 "%a %b %e %H:%M:%S %Y", 1324 "%m/%d/%y", 1325 "%H:%M:%S", 1326 "%I:%M:%S %p", 1327 "AM", 1328 "PM", 1329 1330 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 1331 "Saturday", 1332 1333 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 1334 1335 "January", "February", "March", "April", "May", "June", 1336 "July", "August", "September", "October", "November", "December", 1337 1338 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1339 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 1340 1341 "%EC, %Ey, %EY", 1342 "%Ex", 1343 "%Ec", 1344 "%EX", 1345 "%O", 1346 1347 ".", 1348 "", 1349 1350 "^[yY]", 1351 "^[nN]", 1352 1353 "", 1354 1355 "", // out of bounds 1356 NULL 1357 }; 1358 test_langinfo("POSIX", li_posix); 1359 1360 const char* li_de[] = { 1361 "", // out of bounds 1362 "UTF-8", 1363 "%A, %e. %B %Y %H:%M:%S %Z", 1364 "%d.%m.%Y", 1365 "%H:%M:%S", 1366 "%I:%M:%S %p", 1367 "vorm.", 1368 "nachm.", 1369 1370 "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", 1371 "Samstag", 1372 1373 "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", 1374 1375 "Januar", "Februar", "März", "April", "Mai", "Juni", 1376 "Juli", "August", "September", "Oktober", "November", "Dezember", 1377 1378 "Jan", "Feb", "Mär", "Apr", "Mai", "Jun", 1379 "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 1380 1381 "%EC, %Ey, %EY", 1382 "%Ex", 1383 "%Ec", 1384 "%EX", 1385 "%O", 1386 1387 ",", 1388 ".", 1389 1390 "^[yY]", 1391 "^[nN]", 1392 1393 "€", 1394 1395 "", // out of bounds 1396 NULL, 1397 }; 1398 test_langinfo("de_DE.UTF-8", li_de); 1399 1400 const char* li_de_iso[] = { 1401 "", // out of bounds 1402 "ISO8859-15", 1403 "%A, %e. %B %Y %H:%M:%S %Z", 1404 "%d.%m.%Y", 1405 "%H:%M:%S", 1406 "%I:%M:%S %p", 1407 "vorm.", 1408 "nachm.", 1409 1410 "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", 1411 "Samstag", 1412 1413 "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", 1414 1415 "Januar", "Februar", "M\xE4rz", "April", "Mai", "Juni", 1416 "Juli", "August", "September", "Oktober", "November", "Dezember", 1417 1418 "Jan", "Feb", "M\xE4r", "Apr", "Mai", "Jun", 1419 "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 1420 1421 "%EC, %Ey, %EY", 1422 "%Ex", 1423 "%Ec", 1424 "%EX", 1425 "%O", 1426 1427 ",", 1428 ".", 1429 1430 "^[yY]", 1431 "^[nN]", 1432 1433 "\xA4", 1434 1435 "", // out of bounds 1436 NULL 1437 }; 1438 test_langinfo("de_DE.ISO8859-15", li_de_iso); 1439 } 1440 1441 1442 // #pragma mark - collation ---------------------------------------------------- 1443 1444 1445 struct coll_data { 1446 const char* a; 1447 const char* b; 1448 int result; 1449 int err; 1450 }; 1451 1452 1453 static int sign (int a) 1454 { 1455 if (a < 0) 1456 return -1; 1457 if (a > 0) 1458 return 1; 1459 return 0; 1460 } 1461 1462 1463 void 1464 test_coll(bool useStrxfrm, const char* locale, const coll_data* coll) 1465 { 1466 setlocale(LC_COLLATE, locale); 1467 printf("%s in %s locale\n", useStrxfrm ? "strxfrm" : "strcoll", locale); 1468 1469 int problemCount = 0; 1470 for (unsigned int i = 0; coll[i].a != NULL; ++i) { 1471 errno = 0; 1472 int result; 1473 char funcCall[100]; 1474 if (useStrxfrm) { 1475 char sortKeyA[100], sortKeyB[100]; 1476 strxfrm(sortKeyA, coll[i].a, 100); 1477 strxfrm(sortKeyB, coll[i].b, 100); 1478 result = sign(strcmp(sortKeyA, sortKeyB)); 1479 sprintf(funcCall, "strcmp(strxfrm(\"%s\"), strxfrm(\"%s\"))", 1480 coll[i].a, coll[i].b); 1481 } else { 1482 result = sign(strcoll(coll[i].a, coll[i].b)); 1483 sprintf(funcCall, "strcoll(\"%s\", \"%s\")", coll[i].a, coll[i].b); 1484 } 1485 1486 if (result != coll[i].result || errno != coll[i].err) { 1487 printf( 1488 "\tPROBLEM: %s = %d (expected %d), errno = %x (expected %x)\n", 1489 funcCall, result, coll[i].result, errno, coll[i].err); 1490 problemCount++; 1491 } 1492 } 1493 if (problemCount) 1494 printf("\t%d problem(s) found!\n", problemCount); 1495 else 1496 printf("\tall fine\n"); 1497 } 1498 1499 1500 void 1501 test_collation() 1502 { 1503 const coll_data coll_posix[] = { 1504 { "", "", 0, 0 }, 1505 { "test", "test", 0, 0 }, 1506 { "tester", "test", 1, 0 }, 1507 { "tEst", "teSt", -1, 0 }, 1508 { "test", "tester", -1, 0 }, 1509 { "tast", "täst", -1, EINVAL }, 1510 { "tæst", "test", 1, EINVAL }, 1511 { NULL, NULL, 0, 0 }, 1512 }; 1513 test_coll(0, "POSIX", coll_posix); 1514 test_coll(1, "POSIX", coll_posix); 1515 1516 const coll_data coll_en[] = { 1517 { "", "", 0, 0 }, 1518 { "test", "test", 0, 0 }, 1519 { "tester", "test", 1, 0 }, 1520 { "tEst", "test", 1, 0 }, 1521 { "test", "tester", -1, 0 }, 1522 { "täst", "täst", 0, 0 }, 1523 { "tast", "täst", -1, 0 }, 1524 { "tbst", "täst", 1, 0 }, 1525 { "tbst", "tæst", 1, 0 }, 1526 { "täst", "tÄst", -1, 0 }, 1527 { "tBst", "tÄst", 1, 0 }, 1528 { "tBst", "täst", 1, 0 }, 1529 { "taest", "tæst", -1, 0 }, 1530 { "tafst", "tæst", 1, 0 }, 1531 { "taa", "täa", -1, 0 }, 1532 { "tab", "täb", -1, 0 }, 1533 { "tad", "täd", -1, 0 }, 1534 { "tae", "täe", -1, 0 }, 1535 { "taf", "täf", -1, 0 }, 1536 { "cote", "coté", -1, 0 }, 1537 { "coté", "côte", -1, 0 }, 1538 { "côte", "côté", -1, 0 }, 1539 { NULL, NULL, 0, 0 }, 1540 }; 1541 test_coll(0, "en_US.UTF-8", coll_en); 1542 test_coll(1, "en_US.UTF-8", coll_en); 1543 1544 const coll_data coll_de[] = { 1545 { "", "", 0, 0 }, 1546 { "test", "test", 0, 0 }, 1547 { "tester", "test", 1, 0 }, 1548 { "tEst", "test", 1, 0 }, 1549 { "test", "tester", -1, 0 }, 1550 { "täst", "täst", 0, 0 }, 1551 { "tast", "täst", -1, 0 }, 1552 { "tbst", "täst", 1, 0 }, 1553 { "tbst", "tæst", 1, 0 }, 1554 { "täst", "tÄst", -1, 0 }, 1555 { "tBst", "tÄst", 1, 0 }, 1556 { "tBst", "täst", 1, 0 }, 1557 { "taest", "tæst", -1, 0 }, 1558 { "tafst", "tæst", 1, 0 }, 1559 { "taa", "tä", 1, 0 }, 1560 { "tab", "tä", 1, 0 }, 1561 { "tad", "tä", 1, 0 }, 1562 { "tae", "tä", 1, 0 }, 1563 { "taf", "tä", 1, 0 }, 1564 { "cote", "coté", -1, 0 }, 1565 { "coté", "côte", -1, 0 }, 1566 { "côte", "côté", -1, 0 }, 1567 { NULL, NULL, 0, 0 }, 1568 }; 1569 test_coll(0, "de_DE.UTF-8", coll_de); 1570 test_coll(1, "de_DE.UTF-8", coll_de); 1571 1572 const coll_data coll_de_phonebook[] = { 1573 { "", "", 0, 0 }, 1574 { "test", "test", 0, 0 }, 1575 { "tester", "test", 1, 0 }, 1576 { "tEst", "test", 1, 0 }, 1577 { "test", "tester", -1, 0 }, 1578 { "täst", "täst", 0, 0 }, 1579 { "tast", "täst", 1, 0 }, 1580 { "tbst", "täst", 1, 0 }, 1581 { "tbst", "tæst", 1, 0 }, 1582 { "täst", "tÄst", -1, 0 }, 1583 { "tBst", "tÄst", 1, 0 }, 1584 { "tBst", "täst", 1, 0 }, 1585 { "taest", "tæst", -1, 0 }, 1586 { "tafst", "tæst", 1, 0 }, 1587 { "taa", "tä", -1, 0 }, 1588 { "tab", "tä", -1, 0 }, 1589 { "tad", "tä", -1, 0 }, 1590 { "tae", "tä", -1, 0 }, 1591 { "taf", "tä", 1, 0 }, 1592 { "cote", "coté", -1, 0 }, 1593 { "coté", "côte", -1, 0 }, 1594 { "côte", "côté", -1, 0 }, 1595 { NULL, NULL, 0, 0 }, 1596 }; 1597 test_coll(0, "de_DE.UTF-8@collation=phonebook", coll_de_phonebook); 1598 test_coll(1, "de_DE.UTF-8@collation=phonebook", coll_de_phonebook); 1599 1600 const coll_data coll_fr[] = { 1601 { "", "", 0, 0 }, 1602 { "test", "test", 0, 0 }, 1603 { "tester", "test", 1, 0 }, 1604 { "tEst", "test", 1, 0 }, 1605 { "test", "tester", -1, 0 }, 1606 { "täst", "täst", 0, 0 }, 1607 { "tast", "täst", -1, 0 }, 1608 { "tbst", "täst", 1, 0 }, 1609 { "tbst", "tæst", 1, 0 }, 1610 { "täst", "tÄst", -1, 0 }, 1611 { "tBst", "tÄst", 1, 0 }, 1612 { "tBst", "täst", 1, 0 }, 1613 { "taest", "tæst", -1, 0 }, 1614 { "tafst", "tæst", 1, 0 }, 1615 { "taa", "tä", 1, 0 }, 1616 { "tab", "tä", 1, 0 }, 1617 { "tad", "tä", 1, 0 }, 1618 { "tae", "tä", 1, 0 }, 1619 { "taf", "tä", 1, 0 }, 1620 { "cote", "coté", -1, 0 }, 1621 { "coté", "côte", 1, 0 }, 1622 { "côte", "côté", -1, 0 }, 1623 { NULL, NULL, 0, 0 }, 1624 }; 1625 // CLDR-1.9 has adjusted the defaults of fr_FR to no longer do reverse 1626 // ordering of secondary differences (accents), but fr_CA still does that 1627 // by default 1628 test_coll(0, "fr_CA.UTF-8", coll_fr); 1629 test_coll(1, "fr_CA.UTF-8", coll_fr); 1630 } 1631 1632 1633 // #pragma mark - time conversion ---------------------------------------------- 1634 1635 1636 void 1637 test_localtime(const char* tz, time_t nowSecs, const tm& expected) 1638 { 1639 setenv("TZ", tz, 1); 1640 printf("localtime for '%s'\n", tz); 1641 1642 tm now; 1643 tm* result = localtime_r(&nowSecs, &now); 1644 int problemCount = 0; 1645 if (result == NULL) { 1646 printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs); 1647 problemCount++; 1648 } 1649 if (now.tm_year != expected.tm_year) { 1650 printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n", 1651 now.tm_year, expected.tm_year); 1652 problemCount++; 1653 } 1654 if (now.tm_mon != expected.tm_mon) { 1655 printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n", 1656 now.tm_mon, expected.tm_mon); 1657 problemCount++; 1658 } 1659 if (now.tm_mday != expected.tm_mday) { 1660 printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n", 1661 now.tm_mday, expected.tm_mday); 1662 problemCount++; 1663 } 1664 if (now.tm_hour != expected.tm_hour) { 1665 printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n", 1666 now.tm_hour, expected.tm_hour); 1667 problemCount++; 1668 } 1669 if (now.tm_min != expected.tm_min) { 1670 printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n", 1671 now.tm_min, expected.tm_min); 1672 problemCount++; 1673 } 1674 if (now.tm_sec != expected.tm_sec) { 1675 printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n", 1676 now.tm_sec, expected.tm_sec); 1677 problemCount++; 1678 } 1679 if (now.tm_wday != expected.tm_wday) { 1680 printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n", 1681 now.tm_wday, expected.tm_wday); 1682 problemCount++; 1683 } 1684 if (now.tm_yday != expected.tm_yday) { 1685 printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n", 1686 now.tm_yday, expected.tm_yday); 1687 problemCount++; 1688 } 1689 if (now.tm_isdst != expected.tm_isdst) { 1690 printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n", 1691 now.tm_isdst, expected.tm_isdst); 1692 problemCount++; 1693 } 1694 if (now.tm_gmtoff != expected.tm_gmtoff) { 1695 printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n", 1696 now.tm_gmtoff, expected.tm_gmtoff); 1697 problemCount++; 1698 } 1699 if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) { 1700 printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n", 1701 now.tm_zone, expected.tm_zone); 1702 problemCount++; 1703 } 1704 if (problemCount) 1705 printf("\t%d problem(s) found!\n", problemCount); 1706 else 1707 printf("\tall fine\n"); 1708 } 1709 1710 1711 void 1712 test_gmtime(const char* tz, time_t nowSecs, const tm& expected) 1713 { 1714 setenv("TZ", tz, 1); 1715 printf("gmtime for '%s'\n", tz); 1716 1717 tm now; 1718 tm* result = gmtime_r(&nowSecs, &now); 1719 int problemCount = 0; 1720 if (result == NULL) { 1721 printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs); 1722 problemCount++; 1723 } 1724 if (now.tm_year != expected.tm_year) { 1725 printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n", 1726 now.tm_year, expected.tm_year); 1727 problemCount++; 1728 } 1729 if (now.tm_mon != expected.tm_mon) { 1730 printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n", 1731 now.tm_mon, expected.tm_mon); 1732 problemCount++; 1733 } 1734 if (now.tm_mday != expected.tm_mday) { 1735 printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n", 1736 now.tm_mday, expected.tm_mday); 1737 problemCount++; 1738 } 1739 if (now.tm_hour != expected.tm_hour) { 1740 printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n", 1741 now.tm_hour, expected.tm_hour); 1742 problemCount++; 1743 } 1744 if (now.tm_min != expected.tm_min) { 1745 printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n", 1746 now.tm_min, expected.tm_min); 1747 problemCount++; 1748 } 1749 if (now.tm_sec != expected.tm_sec) { 1750 printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n", 1751 now.tm_sec, expected.tm_sec); 1752 problemCount++; 1753 } 1754 if (now.tm_wday != expected.tm_wday) { 1755 printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n", 1756 now.tm_wday, expected.tm_wday); 1757 problemCount++; 1758 } 1759 if (now.tm_yday != expected.tm_yday) { 1760 printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n", 1761 now.tm_yday, expected.tm_yday); 1762 problemCount++; 1763 } 1764 if (now.tm_isdst != expected.tm_isdst) { 1765 printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n", 1766 now.tm_isdst, expected.tm_isdst); 1767 problemCount++; 1768 } 1769 if (now.tm_gmtoff != expected.tm_gmtoff) { 1770 printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n", 1771 now.tm_gmtoff, expected.tm_gmtoff); 1772 problemCount++; 1773 } 1774 if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) { 1775 printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n", 1776 now.tm_zone, expected.tm_zone); 1777 problemCount++; 1778 } 1779 if (problemCount) 1780 printf("\t%d problem(s) found!\n", problemCount); 1781 else 1782 printf("\tall fine\n"); 1783 } 1784 1785 1786 void 1787 test_mktime(const char* tz, tm& tm, time_t expected, int expectedWeekDay, 1788 int expectedYearDay) 1789 { 1790 setenv("TZ", tz, 1); 1791 printf("mktime for '%s'\n", tz); 1792 1793 time_t result = mktime(&tm); 1794 int problemCount = 0; 1795 if (result != expected) { 1796 printf("\tPROBLEM: mktime() = %ld (expected %ld)\n", result, expected); 1797 problemCount++; 1798 } 1799 if (tm.tm_wday != expectedWeekDay) { 1800 printf("\tPROBLEM: mktime().tm_wday = %d (expected %d)\n", 1801 tm.tm_wday, expectedWeekDay); 1802 problemCount++; 1803 } 1804 if (tm.tm_yday != expectedYearDay) { 1805 printf("\tPROBLEM: mktime().tm_yday = %d (expected %d)\n", 1806 tm.tm_yday, expectedYearDay); 1807 problemCount++; 1808 } 1809 if (problemCount) 1810 printf("\t%d problem(s) found!\n", problemCount); 1811 else 1812 printf("\tall fine\n"); 1813 } 1814 1815 1816 void 1817 test_timeconversions() 1818 { 1819 setlocale(LC_ALL, "en_US"); 1820 { 1821 time_t testTime = 1279391169; // Sat Jul 17 18:26:09 GMT 2010 1822 tm gtm = { 1823 9, 26, 18, 17, 6, 110, 6, 197, 0, 0, (char*)"GMT" 1824 }; 1825 test_localtime("GMT", testTime, gtm); 1826 test_gmtime("GMT", testTime, gtm); 1827 gtm.tm_wday = -1; 1828 gtm.tm_yday = -1; 1829 test_mktime("GMT", gtm, testTime, 6, 197); 1830 1831 tm gtmplus2 = { 1832 9, 26, 16, 17, 6, 110, 6, 197, 0, -2 * 3600, (char*)"GMT+2" 1833 }; 1834 test_localtime("GMT+2", testTime, gtmplus2); 1835 test_gmtime("GMT+2", testTime, gtm); 1836 gtmplus2.tm_wday = -1; 1837 gtmplus2.tm_yday = -1; 1838 test_mktime("GMT+2", gtmplus2, testTime, 6, 197); 1839 1840 tm gtmminus2 = { 1841 9, 26, 20, 17, 6, 110, 6, 197, 0, 2 * 3600, (char*)"GMT-2" 1842 }; 1843 test_localtime("GMT-2", testTime, gtmminus2); 1844 test_gmtime("GMT-2", testTime, gtm); 1845 gtmminus2.tm_wday = -1; 1846 gtmminus2.tm_yday = -1; 1847 test_mktime("GMT-2", gtmminus2, testTime, 6, 197); 1848 1849 tm btm = { 1850 9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST" 1851 }; 1852 test_localtime(":Europe/Berlin", testTime, btm); 1853 test_gmtime(":Europe/Berlin", testTime, gtm); 1854 btm.tm_wday = -1; 1855 btm.tm_yday = -1; 1856 test_mktime(":Europe/Berlin", btm, testTime, 6, 197); 1857 1858 tm ctm = { 1859 9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST" 1860 }; 1861 test_localtime("CET", testTime, ctm); 1862 test_gmtime("CET", testTime, gtm); 1863 ctm.tm_wday = -1; 1864 ctm.tm_yday = -1; 1865 test_mktime("CET", ctm, testTime, 6, 197); 1866 1867 tm latm = { 1868 9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT" 1869 }; 1870 test_localtime(":America/Los_Angeles", testTime, latm); 1871 test_gmtime(":America/Los_Angeles", testTime, gtm); 1872 latm.tm_wday = -1; 1873 latm.tm_yday = -1; 1874 test_mktime(":America/Los_Angeles", latm, testTime, 6, 197); 1875 1876 tm ttm = { 1877 9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"GMT+09:00" 1878 }; 1879 test_localtime(":Asia/Tokyo", testTime, ttm); 1880 test_gmtime(":Asia/Tokyo", testTime, gtm); 1881 ttm.tm_wday = -1; 1882 ttm.tm_yday = -1; 1883 test_mktime(":Asia/Tokyo", ttm, testTime, 0, 198); 1884 } 1885 1886 { 1887 time_t testTime = 1268159169; // Tue Mar 9 18:26:09 GMT 2010 1888 tm gtm = { 1889 9, 26, 18, 9, 2, 110, 2, 67, 0, 0, (char*)"GMT" 1890 }; 1891 test_localtime("GMT", testTime, gtm); 1892 test_gmtime("GMT", testTime, gtm); 1893 gtm.tm_wday = -1; 1894 gtm.tm_yday = -1; 1895 test_mktime("GMT", gtm, testTime, 2, 67); 1896 1897 tm btm = { 1898 9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET" 1899 }; 1900 test_localtime(":Europe/Berlin", testTime, btm); 1901 test_gmtime(":Europe/Berlin", testTime, gtm); 1902 btm.tm_wday = -1; 1903 btm.tm_yday = -1; 1904 test_mktime(":Europe/Berlin", btm, testTime, 2, 67); 1905 1906 tm ctm = { 1907 9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET" 1908 }; 1909 test_localtime("CET", testTime, ctm); 1910 test_gmtime("CET", testTime, gtm); 1911 ctm.tm_wday = -1; 1912 ctm.tm_yday = -1; 1913 test_mktime("CET", ctm, testTime, 2, 67); 1914 1915 tm latm = { 1916 9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST" 1917 }; 1918 test_localtime(":America/Los_Angeles", testTime, latm); 1919 test_gmtime(":America/Los_Angeles", testTime, gtm); 1920 latm.tm_wday = -1; 1921 latm.tm_yday = -1; 1922 test_mktime(":America/Los_Angeles", latm, testTime, 2, 67); 1923 1924 tm ttm = { 1925 9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"GMT+09:00" 1926 }; 1927 test_localtime(":Asia/Tokyo", testTime, ttm); 1928 test_gmtime(":Asia/Tokyo", testTime, gtm); 1929 ttm.tm_wday = -1; 1930 ttm.tm_yday = -1; 1931 test_mktime(":Asia/Tokyo", ttm, testTime, 3, 68); 1932 } 1933 1934 { 1935 time_t testTime = 0; // Thu Jan 1 00:00:00 GMT 1970 1936 tm gtm = { 1937 0, 0, 0, 1, 0, 70, 4, 0, 0, 0, (char*)"GMT" 1938 }; 1939 test_localtime("GMT", testTime, gtm); 1940 test_gmtime("GMT", testTime, gtm); 1941 gtm.tm_wday = -1; 1942 gtm.tm_yday = -1; 1943 test_mktime("GMT", gtm, testTime, 4, 0); 1944 1945 tm btm = { 1946 0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET" 1947 }; 1948 test_localtime(":Europe/Berlin", testTime, btm); 1949 test_gmtime(":Europe/Berlin", testTime, gtm); 1950 btm.tm_wday = -1; 1951 btm.tm_yday = -1; 1952 test_mktime(":Europe/Berlin", btm, testTime, 4, 0); 1953 1954 tm ctm = { 1955 0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET" 1956 }; 1957 test_localtime("CET", testTime, ctm); 1958 test_gmtime("CET", testTime, gtm); 1959 ctm.tm_wday = -1; 1960 ctm.tm_yday = -1; 1961 test_mktime("CET", ctm, testTime, 4, 0); 1962 1963 tm latm = { 1964 0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST" 1965 }; 1966 test_localtime(":America/Los_Angeles", testTime, latm); 1967 test_gmtime(":America/Los_Angeles", testTime, gtm); 1968 latm.tm_wday = -1; 1969 latm.tm_yday = -1; 1970 test_mktime(":America/Los_Angeles", latm, testTime, 3, 364); 1971 1972 tm ttm = { 1973 0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"GMT+09:00" 1974 }; 1975 test_localtime(":Asia/Tokyo", testTime, ttm); 1976 test_gmtime(":Asia/Tokyo", testTime, gtm); 1977 ttm.tm_wday = -1; 1978 ttm.tm_yday = -1; 1979 test_mktime(":Asia/Tokyo", ttm, testTime, 4, 0); 1980 } 1981 } 1982 1983 1984 // #pragma mark - printf ------------------------------------------------------- 1985 1986 1987 struct sprintf_data { 1988 const char* format; 1989 double value; 1990 const char* result; 1991 }; 1992 1993 1994 void 1995 test_sprintf(const char* locale, const sprintf_data data[]) 1996 { 1997 setlocale(LC_ALL, locale); 1998 printf("sprintf for '%s'\n", locale); 1999 2000 int problemCount = 0; 2001 for(int i = 0; data[i].format != NULL; ++i) { 2002 char buf[100]; 2003 if (strchr(data[i].format, 'd') != NULL) 2004 sprintf(buf, data[i].format, (int)data[i].value); 2005 else if (strchr(data[i].format, 'f') != NULL) 2006 sprintf(buf, data[i].format, data[i].value); 2007 if (strcmp(buf, data[i].result) != 0) { 2008 printf("\tPROBLEM: sprintf(\"%s\") = \"%s\" (expected \"%s\")\n", 2009 data[i].format, buf, data[i].result); 2010 problemCount++; 2011 } 2012 } 2013 if (problemCount) 2014 printf("\t%d problem(s) found!\n", problemCount); 2015 else 2016 printf("\tall fine\n"); 2017 } 2018 2019 2020 void 2021 test_sprintf() 2022 { 2023 const sprintf_data sprintf_posix[] = { 2024 { "%d", 123, "123" }, 2025 { "%d", -123, "-123" }, 2026 { "%d", 123456, "123456" }, 2027 { "%'d", 123456, "123456" }, 2028 { "%f", 123, "123.000000" }, 2029 { "%f", -123, "-123.000000" }, 2030 { "%.2f", 123456.789, "123456.79" }, 2031 { "%'.2f", 123456.789, "123456.79" }, 2032 { NULL, 0.0, NULL } 2033 }; 2034 test_sprintf("POSIX", sprintf_posix); 2035 2036 const sprintf_data sprintf_de[] = { 2037 { "%d", 123, "123" }, 2038 { "%d", -123, "-123" }, 2039 { "%d", 123456, "123456" }, 2040 { "%'d", 123456, "123.456" }, 2041 { "%f", 123, "123,000000" }, 2042 { "%f", -123, "-123,000000" }, 2043 { "%.2f", 123456.789, "123456,79" }, 2044 { "%'.2f", 123456.789, "123.456,79" }, 2045 { NULL, 0.0, NULL } 2046 }; 2047 test_sprintf("de_DE.UTF-8", sprintf_de); 2048 2049 const sprintf_data sprintf_gu[] = { 2050 { "%d", 123, "123" }, 2051 { "%d", -123, "-123" }, 2052 { "%d", 123456, "123456" }, 2053 { "%'d", 123456, "123,456" }, 2054 { "%f", 123, "123.000000" }, 2055 { "%f", -123, "-123.000000" }, 2056 { "%.2f", 123456.789, "123456.79" }, 2057 { "%'.2f", 123456.789, "1,23,456.79" }, 2058 { NULL, 0.0, NULL } 2059 }; 2060 test_sprintf("gu_IN", sprintf_gu); 2061 2062 const sprintf_data sprintf_nb[] = { 2063 { "%d", 123, "123" }, 2064 { "%d", -123, "-123" }, 2065 { "%d", 123456, "123456" }, 2066 { "%'d", 123456, "123 456" }, 2067 { "%f", 123, "123,000000" }, 2068 { "%f", -123, "-123,000000" }, 2069 { "%.2f", 123456.789, "123456,79" }, 2070 { "%'.2f", 123456.789, "123 456,79" }, 2071 { NULL, 0.0, NULL } 2072 }; 2073 test_sprintf("nb_NO", sprintf_nb); 2074 } 2075 2076 2077 // #pragma mark - main --------------------------------------------------------- 2078 2079 2080 /* 2081 * Test several different aspects of the POSIX locale and the functions 2082 * influenced by it. 2083 */ 2084 int 2085 main(void) 2086 { 2087 test_setlocale(); 2088 test_localeconv(); 2089 test_strftime(); 2090 test_ctype(); 2091 test_wctype(); 2092 test_wctrans(); 2093 test_wcwidth(); 2094 test_langinfo(); 2095 test_collation(); 2096 test_timeconversions(); 2097 test_sprintf(); 2098 2099 return 0; 2100 } 2101