1 /************************************************************************* 2 * 3 * $Id$ 4 * 5 * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 12 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 13 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 14 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 15 * 16 ************************************************************************/ 17 18 /************************************************************************* 19 * Include files 20 */ 21 22 #include <assert.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <ctype.h> 26 #include <math.h> 27 #include "triodef.h" 28 #include "triostr.h" 29 30 /************************************************************************* 31 * Definitions 32 */ 33 34 #if !defined(TRIO_STRING_PUBLIC) 35 # define TRIO_STRING_PUBLIC TRIO_PUBLIC 36 #endif 37 #if !defined(TRIO_STRING_PRIVATE) 38 # define TRIO_STRING_PRIVATE TRIO_PRIVATE 39 #endif 40 41 #if !defined(NULL) 42 # define NULL 0 43 #endif 44 #if !defined(NIL) 45 # define NIL ((char)0) 46 #endif 47 #if !defined(FALSE) 48 # define FALSE (1 == 0) 49 # define TRUE (! FALSE) 50 #endif 51 #if !defined(BOOLEAN_T) 52 # define BOOLEAN_T int 53 #endif 54 55 #ifdef __VMS 56 # define USE_STRTOD 57 #elif defined(TRIO_COMPILER_SUPPORTS_C99) 58 # define USE_STRTOD 59 # define USE_STRTOF 60 #elif defined(TRIO_COMPILER_MSVC) 61 # define USE_STRTOD 62 #endif 63 64 #if defined(TRIO_PLATFORM_UNIX) 65 # define USE_STRCASECMP 66 # define USE_STRNCASECMP 67 # if defined(TRIO_PLATFORM_SUNOS) 68 # define USE_SYS_ERRLIST 69 # else 70 # define USE_STRERROR 71 # endif 72 # if defined(TRIO_PLATFORM_QNX) 73 # define strcasecmp(x,y) stricmp(x,y) 74 # define strncasecmp(x,y,n) strnicmp(x,y,n) 75 # endif 76 #elif defined(TRIO_PLATFORM_WIN32) 77 # define USE_STRCASECMP 78 # if defined(_WIN32_WCE) 79 # define strcasecmp(x,y) _stricmp(x,y) 80 # else 81 # define strcasecmp(x,y) strcmpi(x,y) 82 # endif 83 #elif defined(TRIO_PLATFORM_OS400) 84 # define USE_STRCASECMP 85 # define USE_STRNCASECMP 86 # include <strings.h> 87 #endif 88 89 #if !(defined(TRIO_PLATFORM_SUNOS)) 90 # define USE_TOLOWER 91 # define USE_TOUPPER 92 #endif 93 94 /************************************************************************* 95 * Structures 96 */ 97 98 struct _trio_string_t 99 { 100 char *content; 101 size_t length; 102 size_t allocated; 103 }; 104 105 /************************************************************************* 106 * Constants 107 */ 108 109 #if !defined(TRIO_MINIMAL) 110 static TRIO_CONST char rcsid[] = "@(#)$Id$"; 111 #endif 112 113 /************************************************************************* 114 * Static String Functions 115 */ 116 117 #if defined(TRIO_DOCUMENTATION) 118 # include "doc/doc_static.h" 119 #endif 120 /** @addtogroup StaticStrings 121 @{ 122 */ 123 124 /** 125 Create new string. 126 127 @param size Size of new string. 128 @return Pointer to string, or NULL if allocation failed. 129 */ 130 TRIO_STRING_PUBLIC char * 131 trio_create 132 TRIO_ARGS1((size), 133 size_t size) 134 { 135 return (char *)TRIO_MALLOC(size); 136 } 137 138 139 /** 140 Destroy string. 141 142 @param string String to be freed. 143 */ 144 TRIO_STRING_PUBLIC void 145 trio_destroy 146 TRIO_ARGS1((string), 147 char *string) 148 { 149 if (string) 150 { 151 TRIO_FREE(string); 152 } 153 } 154 155 156 /** 157 Count the number of characters in a string. 158 159 @param string String to measure. 160 @return Number of characters in @string. 161 */ 162 TRIO_STRING_PUBLIC size_t 163 trio_length 164 TRIO_ARGS1((string), 165 TRIO_CONST char *string) 166 { 167 return strlen(string); 168 } 169 170 171 #if !defined(TRIO_MINIMAL) 172 /** 173 Append @p source at the end of @p target. 174 175 @param target Target string. 176 @param source Source string. 177 @return Boolean value indicating success or failure. 178 179 @pre @p target must point to a memory chunk with sufficient room to 180 contain the @p target string and @p source string. 181 @pre No boundary checking is performed, so insufficient memory will 182 result in a buffer overrun. 183 @post @p target will be zero terminated. 184 */ 185 TRIO_STRING_PUBLIC int 186 trio_append 187 TRIO_ARGS2((target, source), 188 char *target, 189 TRIO_CONST char *source) 190 { 191 assert(target); 192 assert(source); 193 194 return (strcat(target, source) != NULL); 195 } 196 #endif /* !defined(TRIO_MINIMAL) */ 197 198 #if !defined(TRIO_MINIMAL) 199 /** 200 Append at most @p max characters from @p source to @p target. 201 202 @param target Target string. 203 @param max Maximum number of characters to append. 204 @param source Source string. 205 @return Boolean value indicating success or failure. 206 207 @pre @p target must point to a memory chuck with sufficient room to 208 contain the @p target string and the @p source string (at most @p max 209 characters). 210 @pre No boundary checking is performed, so insufficient memory will 211 result in a buffer overrun. 212 @post @p target will be zero terminated. 213 */ 214 TRIO_STRING_PUBLIC int 215 trio_append_max 216 TRIO_ARGS3((target, max, source), 217 char *target, 218 size_t max, 219 TRIO_CONST char *source) 220 { 221 size_t length; 222 223 assert(target); 224 assert(source); 225 226 length = trio_length(target); 227 228 if (max > length) 229 { 230 strncat(target, source, max - length - 1); 231 } 232 return TRUE; 233 } 234 #endif /* !defined(TRIO_MINIMAL) */ 235 236 237 #if !defined(TRIO_MINIMAL) 238 /** 239 Determine if a string contains a substring. 240 241 @param string String to be searched. 242 @param substring String to be found. 243 @return Boolean value indicating success or failure. 244 */ 245 TRIO_STRING_PUBLIC int 246 trio_contains 247 TRIO_ARGS2((string, substring), 248 TRIO_CONST char *string, 249 TRIO_CONST char *substring) 250 { 251 assert(string); 252 assert(substring); 253 254 return (0 != strstr(string, substring)); 255 } 256 #endif /* !defined(TRIO_MINIMAL) */ 257 258 259 #if !defined(TRIO_MINIMAL) 260 /** 261 Copy @p source to @p target. 262 263 @param target Target string. 264 @param source Source string. 265 @return Boolean value indicating success or failure. 266 267 @pre @p target must point to a memory chunk with sufficient room to 268 contain the @p source string. 269 @pre No boundary checking is performed, so insufficient memory will 270 result in a buffer overrun. 271 @post @p target will be zero terminated. 272 */ 273 TRIO_STRING_PUBLIC int 274 trio_copy 275 TRIO_ARGS2((target, source), 276 char *target, 277 TRIO_CONST char *source) 278 { 279 assert(target); 280 assert(source); 281 282 (void)strcpy(target, source); 283 return TRUE; 284 } 285 #endif /* !defined(TRIO_MINIMAL) */ 286 287 288 /** 289 Copy at most @p max characters from @p source to @p target. 290 291 @param target Target string. 292 @param max Maximum number of characters to append. 293 @param source Source string. 294 @return Boolean value indicating success or failure. 295 296 @pre @p target must point to a memory chunk with sufficient room to 297 contain the @p source string (at most @p max characters). 298 @pre No boundary checking is performed, so insufficient memory will 299 result in a buffer overrun. 300 @post @p target will be zero terminated. 301 */ 302 TRIO_STRING_PUBLIC int 303 trio_copy_max 304 TRIO_ARGS3((target, max, source), 305 char *target, 306 size_t max, 307 TRIO_CONST char *source) 308 { 309 assert(target); 310 assert(source); 311 assert(max > 0); /* Includes != 0 */ 312 313 (void)strncpy(target, source, max - 1); 314 target[max - 1] = (char)0; 315 return TRUE; 316 } 317 318 319 /* 320 * TrioDuplicateMax 321 */ 322 TRIO_STRING_PRIVATE char * 323 TrioDuplicateMax 324 TRIO_ARGS2((source, size), 325 TRIO_CONST char *source, 326 size_t size) 327 { 328 char *target; 329 330 assert(source); 331 332 /* Make room for string plus a terminating zero */ 333 size++; 334 target = trio_create(size); 335 if (target) 336 { 337 trio_copy_max(target, size, source); 338 } 339 return target; 340 } 341 342 343 /** 344 Duplicate @p source. 345 346 @param source Source string. 347 @return A copy of the @p source string. 348 349 @post @p target will be zero terminated. 350 */ 351 TRIO_STRING_PUBLIC char * 352 trio_duplicate 353 TRIO_ARGS1((source), 354 TRIO_CONST char *source) 355 { 356 return TrioDuplicateMax(source, trio_length(source)); 357 } 358 359 360 #if !defined(TRIO_MINIMAL) 361 /** 362 Duplicate at most @p max characters of @p source. 363 364 @param source Source string. 365 @param max Maximum number of characters to duplicate. 366 @return A copy of the @p source string. 367 368 @post @p target will be zero terminated. 369 */ 370 TRIO_STRING_PUBLIC char * 371 trio_duplicate_max TRIO_ARGS2((source, max), 372 TRIO_CONST char *source, 373 size_t max) 374 { 375 size_t length; 376 377 assert(source); 378 assert(max > 0); 379 380 length = trio_length(source); 381 if (length > max) 382 { 383 length = max; 384 } 385 return TrioDuplicateMax(source, length); 386 } 387 #endif /* !defined(TRIO_MINIMAL) */ 388 389 390 /** 391 Compare if two strings are equal. 392 393 @param first First string. 394 @param second Second string. 395 @return Boolean indicating whether the two strings are equal or not. 396 397 Case-insensitive comparison. 398 */ 399 TRIO_STRING_PUBLIC int 400 trio_equal 401 TRIO_ARGS2((first, second), 402 TRIO_CONST char *first, 403 TRIO_CONST char *second) 404 { 405 assert(first); 406 assert(second); 407 408 if ((first != NULL) && (second != NULL)) 409 { 410 #if defined(USE_STRCASECMP) 411 return (0 == strcasecmp(first, second)); 412 #else 413 while ((*first != NIL) && (*second != NIL)) 414 { 415 if (trio_to_upper(*first) != trio_to_upper(*second)) 416 { 417 break; 418 } 419 first++; 420 second++; 421 } 422 return ((*first == NIL) && (*second == NIL)); 423 #endif 424 } 425 return FALSE; 426 } 427 428 429 /** 430 Compare if two strings are equal. 431 432 @param first First string. 433 @param second Second string. 434 @return Boolean indicating whether the two strings are equal or not. 435 436 Case-sensitive comparison. 437 */ 438 TRIO_STRING_PUBLIC int 439 trio_equal_case 440 TRIO_ARGS2((first, second), 441 TRIO_CONST char *first, 442 TRIO_CONST char *second) 443 { 444 assert(first); 445 assert(second); 446 447 if ((first != NULL) && (second != NULL)) 448 { 449 return (0 == strcmp(first, second)); 450 } 451 return FALSE; 452 } 453 454 455 #if !defined(TRIO_MINIMAL) 456 /** 457 Compare if two strings up until the first @p max characters are equal. 458 459 @param first First string. 460 @param max Maximum number of characters to compare. 461 @param second Second string. 462 @return Boolean indicating whether the two strings are equal or not. 463 464 Case-sensitive comparison. 465 */ 466 TRIO_STRING_PUBLIC int 467 trio_equal_case_max 468 TRIO_ARGS3((first, max, second), 469 TRIO_CONST char *first, 470 size_t max, 471 TRIO_CONST char *second) 472 { 473 assert(first); 474 assert(second); 475 476 if ((first != NULL) && (second != NULL)) 477 { 478 return (0 == strncmp(first, second, max)); 479 } 480 return FALSE; 481 } 482 #endif /* !defined(TRIO_MINIMAL) */ 483 484 485 /** 486 Compare if two strings are equal. 487 488 @param first First string. 489 @param second Second string. 490 @return Boolean indicating whether the two strings are equal or not. 491 492 Collating characters are considered equal. 493 */ 494 TRIO_STRING_PUBLIC int 495 trio_equal_locale 496 TRIO_ARGS2((first, second), 497 TRIO_CONST char *first, 498 TRIO_CONST char *second) 499 { 500 assert(first); 501 assert(second); 502 503 #if defined(LC_COLLATE) 504 return (strcoll(first, second) == 0); 505 #else 506 return trio_equal(first, second); 507 #endif 508 } 509 510 511 /** 512 Compare if two strings up until the first @p max characters are equal. 513 514 @param first First string. 515 @param max Maximum number of characters to compare. 516 @param second Second string. 517 @return Boolean indicating whether the two strings are equal or not. 518 519 Case-insensitive comparison. 520 */ 521 TRIO_STRING_PUBLIC int 522 trio_equal_max 523 TRIO_ARGS3((first, max, second), 524 TRIO_CONST char *first, 525 size_t max, 526 TRIO_CONST char *second) 527 { 528 assert(first); 529 assert(second); 530 531 if ((first != NULL) && (second != NULL)) 532 { 533 #if defined(USE_STRNCASECMP) 534 return (0 == strncasecmp(first, second, max)); 535 #else 536 /* Not adequately tested yet */ 537 size_t cnt = 0; 538 while ((*first != NIL) && (*second != NIL) && (cnt <= max)) 539 { 540 if (trio_to_upper(*first) != trio_to_upper(*second)) 541 { 542 break; 543 } 544 first++; 545 second++; 546 cnt++; 547 } 548 return ((cnt == max) || ((*first == NIL) && (*second == NIL))); 549 #endif 550 } 551 return FALSE; 552 } 553 554 555 /** 556 Provide a textual description of an error code (errno). 557 558 @param error_number Error number. 559 @return Textual description of @p error_number. 560 */ 561 TRIO_STRING_PUBLIC TRIO_CONST char * 562 trio_error 563 TRIO_ARGS1((error_number), 564 int error_number) 565 { 566 #if defined(USE_STRERROR) 567 568 return strerror(error_number); 569 570 #elif defined(USE_SYS_ERRLIST) 571 572 extern char *sys_errlist[]; 573 extern int sys_nerr; 574 575 return ((error_number < 0) || (error_number >= sys_nerr)) 576 ? "unknown" 577 : sys_errlist[error_number]; 578 579 #else 580 581 return "unknown"; 582 583 #endif 584 } 585 586 587 #if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) 588 /** 589 Format the date/time according to @p format. 590 591 @param target Target string. 592 @param max Maximum number of characters to format. 593 @param format Formatting string. 594 @param datetime Date/time structure. 595 @return Number of formatted characters. 596 597 The formatting string accepts the same specifiers as the standard C 598 function strftime. 599 */ 600 TRIO_STRING_PUBLIC size_t 601 trio_format_date_max 602 TRIO_ARGS4((target, max, format, datetime), 603 char *target, 604 size_t max, 605 TRIO_CONST char *format, 606 TRIO_CONST struct tm *datetime) 607 { 608 assert(target); 609 assert(format); 610 assert(datetime); 611 assert(max > 0); 612 613 return strftime(target, max, format, datetime); 614 } 615 #endif /* !defined(TRIO_MINIMAL) */ 616 617 618 #if !defined(TRIO_MINIMAL) 619 /** 620 Calculate a hash value for a string. 621 622 @param string String to be calculated on. 623 @param type Hash function. 624 @return Calculated hash value. 625 626 @p type can be one of the following 627 @li @c TRIO_HASH_PLAIN Plain hash function. 628 */ 629 TRIO_STRING_PUBLIC unsigned long 630 trio_hash 631 TRIO_ARGS2((string, type), 632 TRIO_CONST char *string, 633 int type) 634 { 635 unsigned long value = 0L; 636 char ch; 637 638 assert(string); 639 640 switch (type) 641 { 642 case TRIO_HASH_PLAIN: 643 while ( (ch = *string++) != NIL ) 644 { 645 value *= 31; 646 value += (unsigned long)ch; 647 } 648 break; 649 default: 650 assert(FALSE); 651 break; 652 } 653 return value; 654 } 655 #endif /* !defined(TRIO_MINIMAL) */ 656 657 658 #if !defined(TRIO_MINIMAL) 659 /** 660 Find first occurrence of a character in a string. 661 662 @param string String to be searched. 663 @param character Character to be found. 664 @param A pointer to the found character, or NULL if character was not found. 665 */ 666 TRIO_STRING_PUBLIC char * 667 trio_index 668 TRIO_ARGS2((string, character), 669 TRIO_CONST char *string, 670 int character) 671 { 672 assert(string); 673 674 return strchr(string, character); 675 } 676 #endif /* !defined(TRIO_MINIMAL) */ 677 678 679 #if !defined(TRIO_MINIMAL) 680 /** 681 Find last occurrence of a character in a string. 682 683 @param string String to be searched. 684 @param character Character to be found. 685 @param A pointer to the found character, or NULL if character was not found. 686 */ 687 TRIO_STRING_PUBLIC char * 688 trio_index_last 689 TRIO_ARGS2((string, character), 690 TRIO_CONST char *string, 691 int character) 692 { 693 assert(string); 694 695 return strchr(string, character); 696 } 697 #endif /* !defined(TRIO_MINIMAL) */ 698 699 700 #if !defined(TRIO_MINIMAL) 701 /** 702 Convert the alphabetic letters in the string to lower-case. 703 704 @param target String to be converted. 705 @return Number of processed characters (converted or not). 706 */ 707 TRIO_STRING_PUBLIC int 708 trio_lower 709 TRIO_ARGS1((target), 710 char *target) 711 { 712 assert(target); 713 714 return trio_span_function(target, target, trio_to_lower); 715 } 716 #endif /* !defined(TRIO_MINIMAL) */ 717 718 719 #if !defined(TRIO_MINIMAL) 720 /** 721 Compare two strings using wildcards. 722 723 @param string String to be searched. 724 @param pattern Pattern, including wildcards, to search for. 725 @return Boolean value indicating success or failure. 726 727 Case-insensitive comparison. 728 729 The following wildcards can be used 730 @li @c * Match any number of characters. 731 @li @c ? Match a single character. 732 */ 733 TRIO_STRING_PUBLIC int 734 trio_match 735 TRIO_ARGS2((string, pattern), 736 TRIO_CONST char *string, 737 TRIO_CONST char *pattern) 738 { 739 assert(string); 740 assert(pattern); 741 742 for (; ('*' != *pattern); ++pattern, ++string) 743 { 744 if (NIL == *string) 745 { 746 return (NIL == *pattern); 747 } 748 if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern)) 749 && ('?' != *pattern)) 750 { 751 return FALSE; 752 } 753 } 754 /* two-line patch to prevent *too* much recursiveness: */ 755 while ('*' == pattern[1]) 756 pattern++; 757 758 do 759 { 760 if ( trio_match(string, &pattern[1]) ) 761 { 762 return TRUE; 763 } 764 } 765 while (*string++); 766 767 return FALSE; 768 } 769 #endif /* !defined(TRIO_MINIMAL) */ 770 771 772 #if !defined(TRIO_MINIMAL) 773 /** 774 Compare two strings using wildcards. 775 776 @param string String to be searched. 777 @param pattern Pattern, including wildcards, to search for. 778 @return Boolean value indicating success or failure. 779 780 Case-sensitive comparison. 781 782 The following wildcards can be used 783 @li @c * Match any number of characters. 784 @li @c ? Match a single character. 785 */ 786 TRIO_STRING_PUBLIC int 787 trio_match_case 788 TRIO_ARGS2((string, pattern), 789 TRIO_CONST char *string, 790 TRIO_CONST char *pattern) 791 { 792 assert(string); 793 assert(pattern); 794 795 for (; ('*' != *pattern); ++pattern, ++string) 796 { 797 if (NIL == *string) 798 { 799 return (NIL == *pattern); 800 } 801 if ((*string != *pattern) 802 && ('?' != *pattern)) 803 { 804 return FALSE; 805 } 806 } 807 /* two-line patch to prevent *too* much recursiveness: */ 808 while ('*' == pattern[1]) 809 pattern++; 810 811 do 812 { 813 if ( trio_match_case(string, &pattern[1]) ) 814 { 815 return TRUE; 816 } 817 } 818 while (*string++); 819 820 return FALSE; 821 } 822 #endif /* !defined(TRIO_MINIMAL) */ 823 824 825 #if !defined(TRIO_MINIMAL) 826 /** 827 Execute a function on each character in string. 828 829 @param target Target string. 830 @param source Source string. 831 @param Function Function to be executed. 832 @return Number of processed characters. 833 */ 834 TRIO_STRING_PUBLIC size_t 835 trio_span_function 836 TRIO_ARGS3((target, source, Function), 837 char *target, 838 TRIO_CONST char *source, 839 int (*Function) TRIO_PROTO((int))) 840 { 841 size_t count = 0; 842 843 assert(target); 844 assert(source); 845 assert(Function); 846 847 while (*source != NIL) 848 { 849 *target++ = Function(*source++); 850 count++; 851 } 852 return count; 853 } 854 #endif /* !defined(TRIO_MINIMAL) */ 855 856 857 #if !defined(TRIO_MINIMAL) 858 /** 859 Search for a substring in a string. 860 861 @param string String to be searched. 862 @param substring String to be found. 863 @return Pointer to first occurrence of @p substring in @p string, or NULL 864 if no match was found. 865 */ 866 TRIO_STRING_PUBLIC char * 867 trio_substring 868 TRIO_ARGS2((string, substring), 869 TRIO_CONST char *string, 870 TRIO_CONST char *substring) 871 { 872 assert(string); 873 assert(substring); 874 875 return strstr(string, substring); 876 } 877 #endif /* !defined(TRIO_MINIMAL) */ 878 879 880 #if !defined(TRIO_MINIMAL) 881 /** 882 Search for a substring in the first @p max characters of a string. 883 884 @param string String to be searched. 885 @param max Maximum characters to be searched. 886 @param substring String to be found. 887 @return Pointer to first occurrence of @p substring in @p string, or NULL 888 if no match was found. 889 */ 890 TRIO_STRING_PUBLIC char * 891 trio_substring_max 892 TRIO_ARGS3((string, max, substring), 893 TRIO_CONST char *string, 894 size_t max, 895 TRIO_CONST char *substring) 896 { 897 size_t count; 898 size_t size; 899 char *result = NULL; 900 901 assert(string); 902 assert(substring); 903 904 size = trio_length(substring); 905 if (size <= max) 906 { 907 for (count = 0; count <= max - size; count++) 908 { 909 if (trio_equal_max(substring, size, &string[count])) 910 { 911 result = (char *)&string[count]; 912 break; 913 } 914 } 915 } 916 return result; 917 } 918 #endif /* !defined(TRIO_MINIMAL) */ 919 920 921 #if !defined(TRIO_MINIMAL) 922 /** 923 Tokenize string. 924 925 @param string String to be tokenized. 926 @param tokens String containing list of delimiting characters. 927 @return Start of new token. 928 929 @warning @p string will be destroyed. 930 */ 931 TRIO_STRING_PUBLIC char * 932 trio_tokenize 933 TRIO_ARGS2((string, delimiters), 934 char *string, 935 TRIO_CONST char *delimiters) 936 { 937 assert(delimiters); 938 939 return strtok(string, delimiters); 940 } 941 #endif /* !defined(TRIO_MINIMAL) */ 942 943 944 /** 945 Convert string to floating-point number. 946 947 @param source String to be converted. 948 @param endp Pointer to end of the converted string. 949 @return A floating-point number. 950 951 The following Extended Backus-Naur form is used 952 @verbatim 953 double ::= [ <sign> ] 954 ( <number> | 955 <number> <decimal_point> <number> | 956 <decimal_point> <number> ) 957 [ <exponential> [ <sign> ] <number> ] 958 number ::= 1*( <digit> ) 959 digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) 960 exponential ::= ( 'e' | 'E' ) 961 sign ::= ( '-' | '+' ) 962 decimal_point ::= '.' 963 @endverbatim 964 */ 965 /* FIXME: Add EBNF for hex-floats */ 966 TRIO_STRING_PUBLIC trio_long_double_t 967 trio_to_long_double 968 TRIO_ARGS2((source, endp), 969 TRIO_CONST char *source, 970 char **endp) 971 { 972 #if defined(USE_STRTOLD) 973 return strtold(source, endp); 974 #else 975 int isNegative = FALSE; 976 int isExponentNegative = FALSE; 977 trio_long_double_t integer = 0.0; 978 trio_long_double_t fraction = 0.0; 979 unsigned long exponent = 0; 980 trio_long_double_t base; 981 trio_long_double_t fracdiv = 1.0; 982 trio_long_double_t value = 0.0; 983 984 /* First try hex-floats */ 985 if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) 986 { 987 base = 16.0; 988 source += 2; 989 while (isxdigit((int)*source)) 990 { 991 integer *= base; 992 integer += (isdigit((int)*source) 993 ? (*source - '0') 994 : 10 + (trio_to_upper((int)*source) - 'A')); 995 source++; 996 } 997 if (*source == '.') 998 { 999 source++; 1000 while (isxdigit((int)*source)) 1001 { 1002 fracdiv /= base; 1003 fraction += fracdiv * (isdigit((int)*source) 1004 ? (*source - '0') 1005 : 10 + (trio_to_upper((int)*source) - 'A')); 1006 source++; 1007 } 1008 if ((*source == 'p') || (*source == 'P')) 1009 { 1010 source++; 1011 if ((*source == '+') || (*source == '-')) 1012 { 1013 isExponentNegative = (*source == '-'); 1014 source++; 1015 } 1016 while (isdigit((int)*source)) 1017 { 1018 exponent *= 10; 1019 exponent += (*source - '0'); 1020 source++; 1021 } 1022 } 1023 } 1024 /* For later use with exponent */ 1025 base = 2.0; 1026 } 1027 else /* Then try normal decimal floats */ 1028 { 1029 base = 10.0; 1030 isNegative = (*source == '-'); 1031 /* Skip sign */ 1032 if ((*source == '+') || (*source == '-')) 1033 source++; 1034 1035 /* Integer part */ 1036 while (isdigit((int)*source)) 1037 { 1038 integer *= base; 1039 integer += (*source - '0'); 1040 source++; 1041 } 1042 1043 if (*source == '.') 1044 { 1045 source++; /* skip decimal point */ 1046 while (isdigit((int)*source)) 1047 { 1048 fracdiv /= base; 1049 fraction += (*source - '0') * fracdiv; 1050 source++; 1051 } 1052 } 1053 if ((*source == 'e') 1054 || (*source == 'E') 1055 #if TRIO_MICROSOFT 1056 || (*source == 'd') 1057 || (*source == 'D') 1058 #endif 1059 ) 1060 { 1061 source++; /* Skip exponential indicator */ 1062 isExponentNegative = (*source == '-'); 1063 if ((*source == '+') || (*source == '-')) 1064 source++; 1065 while (isdigit((int)*source)) 1066 { 1067 exponent *= (int)base; 1068 exponent += (*source - '0'); 1069 source++; 1070 } 1071 } 1072 } 1073 1074 value = integer + fraction; 1075 if (exponent != 0) 1076 { 1077 if (isExponentNegative) 1078 value /= pow(base, (double)exponent); 1079 else 1080 value *= pow(base, (double)exponent); 1081 } 1082 if (isNegative) 1083 value = -value; 1084 1085 if (endp) 1086 *endp = (char *)source; 1087 return value; 1088 #endif 1089 } 1090 1091 1092 /** 1093 Convert string to floating-point number. 1094 1095 @param source String to be converted. 1096 @param endp Pointer to end of the converted string. 1097 @return A floating-point number. 1098 1099 See @ref trio_to_long_double. 1100 */ 1101 TRIO_STRING_PUBLIC double 1102 trio_to_double 1103 TRIO_ARGS2((source, endp), 1104 TRIO_CONST char *source, 1105 char **endp) 1106 { 1107 #if defined(USE_STRTOD) 1108 return strtod(source, endp); 1109 #else 1110 return (double)trio_to_long_double(source, endp); 1111 #endif 1112 } 1113 1114 #if !defined(TRIO_MINIMAL) 1115 /** 1116 Convert string to floating-point number. 1117 1118 @param source String to be converted. 1119 @param endp Pointer to end of the converted string. 1120 @return A floating-point number. 1121 1122 See @ref trio_to_long_double. 1123 */ 1124 TRIO_STRING_PUBLIC float 1125 trio_to_float 1126 TRIO_ARGS2((source, endp), 1127 TRIO_CONST char *source, 1128 char **endp) 1129 { 1130 #if defined(USE_STRTOF) 1131 return strtof(source, endp); 1132 #else 1133 return (float)trio_to_long_double(source, endp); 1134 #endif 1135 } 1136 #endif /* !defined(TRIO_MINIMAL) */ 1137 1138 1139 /** 1140 Convert string to signed integer. 1141 1142 @param string String to be converted. 1143 @param endp Pointer to end of converted string. 1144 @param base Radix number of number. 1145 */ 1146 TRIO_STRING_PUBLIC long 1147 trio_to_long 1148 TRIO_ARGS3((string, endp, base), 1149 TRIO_CONST char *string, 1150 char **endp, 1151 int base) 1152 { 1153 assert(string); 1154 assert((base >= 2) && (base <= 36)); 1155 1156 return strtol(string, endp, base); 1157 } 1158 1159 1160 #if !defined(TRIO_MINIMAL) 1161 /** 1162 Convert one alphabetic letter to lower-case. 1163 1164 @param source The letter to be converted. 1165 @return The converted letter. 1166 */ 1167 TRIO_STRING_PUBLIC int 1168 trio_to_lower 1169 TRIO_ARGS1((source), 1170 int source) 1171 { 1172 #if defined(USE_TOLOWER) 1173 1174 return tolower(source); 1175 1176 #else 1177 1178 /* Does not handle locales or non-contiguous alphabetic characters */ 1179 return ((source >= (int)'A') && (source <= (int)'Z')) 1180 ? source - 'A' + 'a' 1181 : source; 1182 1183 #endif 1184 } 1185 #endif /* !defined(TRIO_MINIMAL) */ 1186 1187 #if !defined(TRIO_MINIMAL) 1188 /** 1189 Convert string to unsigned integer. 1190 1191 @param string String to be converted. 1192 @param endp Pointer to end of converted string. 1193 @param base Radix number of number. 1194 */ 1195 TRIO_STRING_PUBLIC unsigned long 1196 trio_to_unsigned_long 1197 TRIO_ARGS3((string, endp, base), 1198 TRIO_CONST char *string, 1199 char **endp, 1200 int base) 1201 { 1202 assert(string); 1203 assert((base >= 2) && (base <= 36)); 1204 1205 return strtoul(string, endp, base); 1206 } 1207 #endif /* !defined(TRIO_MINIMAL) */ 1208 1209 1210 /** 1211 Convert one alphabetic letter to upper-case. 1212 1213 @param source The letter to be converted. 1214 @return The converted letter. 1215 */ 1216 TRIO_STRING_PUBLIC int 1217 trio_to_upper 1218 TRIO_ARGS1((source), 1219 int source) 1220 { 1221 #if defined(USE_TOUPPER) 1222 1223 return toupper(source); 1224 1225 #else 1226 1227 /* Does not handle locales or non-contiguous alphabetic characters */ 1228 return ((source >= (int)'a') && (source <= (int)'z')) 1229 ? source - 'a' + 'A' 1230 : source; 1231 1232 #endif 1233 } 1234 1235 #if !defined(TRIO_MINIMAL) 1236 /** 1237 Convert the alphabetic letters in the string to upper-case. 1238 1239 @param target The string to be converted. 1240 @return The number of processed characters (converted or not). 1241 */ 1242 TRIO_STRING_PUBLIC int 1243 trio_upper 1244 TRIO_ARGS1((target), 1245 char *target) 1246 { 1247 assert(target); 1248 1249 return trio_span_function(target, target, trio_to_upper); 1250 } 1251 #endif /* !defined(TRIO_MINIMAL) */ 1252 1253 1254 /** @} End of StaticStrings */ 1255 1256 1257 /************************************************************************* 1258 * Dynamic String Functions 1259 */ 1260 1261 #if defined(TRIO_DOCUMENTATION) 1262 # include "doc/doc_dynamic.h" 1263 #endif 1264 /** @addtogroup DynamicStrings 1265 @{ 1266 */ 1267 1268 /* 1269 * TrioStringAlloc 1270 */ 1271 TRIO_STRING_PRIVATE trio_string_t * 1272 TrioStringAlloc(TRIO_NOARGS) 1273 { 1274 trio_string_t *self; 1275 1276 self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); 1277 if (self) 1278 { 1279 self->content = NULL; 1280 self->length = 0; 1281 self->allocated = 0; 1282 } 1283 return self; 1284 } 1285 1286 1287 /* 1288 * TrioStringGrow 1289 * 1290 * The size of the string will be increased by 'delta' characters. If 1291 * 'delta' is zero, the size will be doubled. 1292 */ 1293 TRIO_STRING_PRIVATE BOOLEAN_T 1294 TrioStringGrow 1295 TRIO_ARGS2((self, delta), 1296 trio_string_t *self, 1297 size_t delta) 1298 { 1299 BOOLEAN_T status = FALSE; 1300 char *new_content; 1301 size_t new_size; 1302 1303 new_size = (delta == 0) 1304 ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) 1305 : self->allocated + delta; 1306 1307 new_content = (char *)TRIO_REALLOC(self->content, new_size); 1308 if (new_content) 1309 { 1310 self->content = new_content; 1311 self->allocated = new_size; 1312 status = TRUE; 1313 } 1314 return status; 1315 } 1316 1317 1318 #if !defined(TRIO_MINIMAL) 1319 /* 1320 * TrioStringGrowTo 1321 * 1322 * The size of the string will be increased to 'length' plus one characters. 1323 * If 'length' is less than the original size, the original size will be 1324 * used (that is, the size of the string is never decreased). 1325 */ 1326 TRIO_STRING_PRIVATE BOOLEAN_T 1327 TrioStringGrowTo 1328 TRIO_ARGS2((self, length), 1329 trio_string_t *self, 1330 size_t length) 1331 { 1332 length++; /* Room for terminating zero */ 1333 return (self->allocated < length) 1334 ? TrioStringGrow(self, length - self->allocated) 1335 : TRUE; 1336 } 1337 #endif /* !defined(TRIO_MINIMAL) */ 1338 1339 1340 #if !defined(TRIO_MINIMAL) 1341 /** 1342 Create a new dynamic string. 1343 1344 @param initial_size Initial size of the buffer. 1345 @return Newly allocated dynamic string, or NULL if memory allocation failed. 1346 */ 1347 TRIO_STRING_PUBLIC trio_string_t * 1348 trio_string_create 1349 TRIO_ARGS1((initial_size), 1350 int initial_size) 1351 { 1352 trio_string_t *self; 1353 1354 self = TrioStringAlloc(); 1355 if (self) 1356 { 1357 if (TrioStringGrow(self, 1358 (size_t)((initial_size > 0) ? initial_size : 1))) 1359 { 1360 self->content[0] = (char)0; 1361 self->allocated = initial_size; 1362 } 1363 else 1364 { 1365 trio_string_destroy(self); 1366 self = NULL; 1367 } 1368 } 1369 return self; 1370 } 1371 #endif /* !defined(TRIO_MINIMAL) */ 1372 1373 1374 /** 1375 Deallocate the dynamic string and its contents. 1376 1377 @param self Dynamic string 1378 */ 1379 TRIO_STRING_PUBLIC void 1380 trio_string_destroy 1381 TRIO_ARGS1((self), 1382 trio_string_t *self) 1383 { 1384 assert(self); 1385 1386 if (self) 1387 { 1388 trio_destroy(self->content); 1389 TRIO_FREE(self); 1390 } 1391 } 1392 1393 1394 #if !defined(TRIO_MINIMAL) 1395 /** 1396 Get a pointer to the content. 1397 1398 @param self Dynamic string. 1399 @param offset Offset into content. 1400 @return Pointer to the content. 1401 1402 @p Offset can be zero, positive, or negative. If @p offset is zero, 1403 then the start of the content will be returned. If @p offset is positive, 1404 then a pointer to @p offset number of characters from the beginning of the 1405 content is returned. If @p offset is negative, then a pointer to @p offset 1406 number of characters from the ending of the string, starting at the 1407 terminating zero, is returned. 1408 */ 1409 TRIO_STRING_PUBLIC char * 1410 trio_string_get 1411 TRIO_ARGS2((self, offset), 1412 trio_string_t *self, 1413 int offset) 1414 { 1415 char *result = NULL; 1416 1417 assert(self); 1418 1419 if (self->content != NULL) 1420 { 1421 if (self->length == 0) 1422 { 1423 (void)trio_string_length(self); 1424 } 1425 if (offset >= 0) 1426 { 1427 if (offset > (int)self->length) 1428 { 1429 offset = self->length; 1430 } 1431 } 1432 else 1433 { 1434 offset += self->length + 1; 1435 if (offset < 0) 1436 { 1437 offset = 0; 1438 } 1439 } 1440 result = &(self->content[offset]); 1441 } 1442 return result; 1443 } 1444 #endif /* !defined(TRIO_MINIMAL) */ 1445 1446 1447 /** 1448 Extract the content. 1449 1450 @param self Dynamic String 1451 @return Content of dynamic string. 1452 1453 The content is removed from the dynamic string. This enables destruction 1454 of the dynamic string without deallocation of the content. 1455 */ 1456 TRIO_STRING_PUBLIC char * 1457 trio_string_extract 1458 TRIO_ARGS1((self), 1459 trio_string_t *self) 1460 { 1461 char *result; 1462 1463 assert(self); 1464 1465 result = self->content; 1466 /* FIXME: Allocate new empty buffer? */ 1467 self->content = NULL; 1468 self->length = self->allocated = 0; 1469 return result; 1470 } 1471 1472 1473 #if !defined(TRIO_MINIMAL) 1474 /** 1475 Set the content of the dynamic string. 1476 1477 @param self Dynamic String 1478 @param buffer The new content. 1479 1480 Sets the content of the dynamic string to a copy @p buffer. 1481 An existing content will be deallocated first, if necessary. 1482 1483 @remark 1484 This function will make a copy of @p buffer. 1485 You are responsible for deallocating @p buffer yourself. 1486 */ 1487 TRIO_STRING_PUBLIC void 1488 trio_xstring_set 1489 TRIO_ARGS2((self, buffer), 1490 trio_string_t *self, 1491 char *buffer) 1492 { 1493 assert(self); 1494 1495 trio_destroy(self->content); 1496 self->content = trio_duplicate(buffer); 1497 } 1498 #endif /* !defined(TRIO_MINIMAL) */ 1499 1500 1501 /* 1502 * trio_string_size 1503 */ 1504 TRIO_STRING_PUBLIC int 1505 trio_string_size 1506 TRIO_ARGS1((self), 1507 trio_string_t *self) 1508 { 1509 assert(self); 1510 1511 return self->allocated; 1512 } 1513 1514 1515 /* 1516 * trio_string_terminate 1517 */ 1518 TRIO_STRING_PUBLIC void 1519 trio_string_terminate 1520 TRIO_ARGS1((self), 1521 trio_string_t *self) 1522 { 1523 trio_xstring_append_char(self, 0); 1524 } 1525 1526 1527 #if !defined(TRIO_MINIMAL) 1528 /** 1529 Append the second string to the first. 1530 1531 @param self Dynamic string to be modified. 1532 @param other Dynamic string to copy from. 1533 @return Boolean value indicating success or failure. 1534 */ 1535 TRIO_STRING_PUBLIC int 1536 trio_string_append 1537 TRIO_ARGS2((self, other), 1538 trio_string_t *self, 1539 trio_string_t *other) 1540 { 1541 size_t length; 1542 1543 assert(self); 1544 assert(other); 1545 1546 length = self->length + other->length; 1547 if (!TrioStringGrowTo(self, length)) 1548 goto error; 1549 trio_copy(&self->content[self->length], other->content); 1550 self->length = length; 1551 return TRUE; 1552 1553 error: 1554 return FALSE; 1555 } 1556 #endif /* !defined(TRIO_MINIMAL) */ 1557 1558 1559 #if !defined(TRIO_MINIMAL) 1560 /* 1561 * trio_xstring_append 1562 */ 1563 TRIO_STRING_PUBLIC int 1564 trio_xstring_append 1565 TRIO_ARGS2((self, other), 1566 trio_string_t *self, 1567 TRIO_CONST char *other) 1568 { 1569 size_t length; 1570 1571 assert(self); 1572 assert(other); 1573 1574 length = self->length + trio_length(other); 1575 if (!TrioStringGrowTo(self, length)) 1576 goto error; 1577 trio_copy(&self->content[self->length], other); 1578 self->length = length; 1579 return TRUE; 1580 1581 error: 1582 return FALSE; 1583 } 1584 #endif /* !defined(TRIO_MINIMAL) */ 1585 1586 1587 /* 1588 * trio_xstring_append_char 1589 */ 1590 TRIO_STRING_PUBLIC int 1591 trio_xstring_append_char 1592 TRIO_ARGS2((self, character), 1593 trio_string_t *self, 1594 char character) 1595 { 1596 assert(self); 1597 1598 if ((int)self->length >= trio_string_size(self)) 1599 { 1600 if (!TrioStringGrow(self, 0)) 1601 goto error; 1602 } 1603 self->content[self->length] = character; 1604 self->length++; 1605 return TRUE; 1606 1607 error: 1608 return FALSE; 1609 } 1610 1611 1612 #if !defined(TRIO_MINIMAL) 1613 /** 1614 Search for the first occurrence of second parameter in the first. 1615 1616 @param self Dynamic string to be modified. 1617 @param other Dynamic string to copy from. 1618 @return Boolean value indicating success or failure. 1619 */ 1620 TRIO_STRING_PUBLIC int 1621 trio_string_contains 1622 TRIO_ARGS2((self, other), 1623 trio_string_t *self, 1624 trio_string_t *other) 1625 { 1626 assert(self); 1627 assert(other); 1628 1629 return trio_contains(self->content, other->content); 1630 } 1631 #endif /* !defined(TRIO_MINIMAL) */ 1632 1633 1634 #if !defined(TRIO_MINIMAL) 1635 /* 1636 * trio_xstring_contains 1637 */ 1638 TRIO_STRING_PUBLIC int 1639 trio_xstring_contains 1640 TRIO_ARGS2((self, other), 1641 trio_string_t *self, 1642 TRIO_CONST char *other) 1643 { 1644 assert(self); 1645 assert(other); 1646 1647 return trio_contains(self->content, other); 1648 } 1649 #endif /* !defined(TRIO_MINIMAL) */ 1650 1651 1652 #if !defined(TRIO_MINIMAL) 1653 /* 1654 * trio_string_copy 1655 */ 1656 TRIO_STRING_PUBLIC int 1657 trio_string_copy 1658 TRIO_ARGS2((self, other), 1659 trio_string_t *self, 1660 trio_string_t *other) 1661 { 1662 assert(self); 1663 assert(other); 1664 1665 self->length = 0; 1666 return trio_string_append(self, other); 1667 } 1668 #endif /* !defined(TRIO_MINIMAL) */ 1669 1670 1671 #if !defined(TRIO_MINIMAL) 1672 /* 1673 * trio_xstring_copy 1674 */ 1675 TRIO_STRING_PUBLIC int 1676 trio_xstring_copy 1677 TRIO_ARGS2((self, other), 1678 trio_string_t *self, 1679 TRIO_CONST char *other) 1680 { 1681 assert(self); 1682 assert(other); 1683 1684 self->length = 0; 1685 return trio_xstring_append(self, other); 1686 } 1687 #endif /* !defined(TRIO_MINIMAL) */ 1688 1689 1690 #if !defined(TRIO_MINIMAL) 1691 /* 1692 * trio_string_duplicate 1693 */ 1694 TRIO_STRING_PUBLIC trio_string_t * 1695 trio_string_duplicate 1696 TRIO_ARGS1((other), 1697 trio_string_t *other) 1698 { 1699 trio_string_t *self; 1700 1701 assert(other); 1702 1703 self = TrioStringAlloc(); 1704 if (self) 1705 { 1706 self->content = TrioDuplicateMax(other->content, other->length); 1707 if (self->content) 1708 { 1709 self->length = other->length; 1710 self->allocated = self->length + 1; 1711 } 1712 else 1713 { 1714 self->length = self->allocated = 0; 1715 } 1716 } 1717 return self; 1718 } 1719 #endif /* !defined(TRIO_MINIMAL) */ 1720 1721 1722 /* 1723 * trio_xstring_duplicate 1724 */ 1725 TRIO_STRING_PUBLIC trio_string_t * 1726 trio_xstring_duplicate 1727 TRIO_ARGS1((other), 1728 TRIO_CONST char *other) 1729 { 1730 trio_string_t *self; 1731 1732 assert(other); 1733 1734 self = TrioStringAlloc(); 1735 if (self) 1736 { 1737 self->content = TrioDuplicateMax(other, trio_length(other)); 1738 if (self->content) 1739 { 1740 self->length = trio_length(self->content); 1741 self->allocated = self->length + 1; 1742 } 1743 else 1744 { 1745 self->length = self->allocated = 0; 1746 } 1747 } 1748 return self; 1749 } 1750 1751 1752 #if !defined(TRIO_MINIMAL) 1753 /* 1754 * trio_string_equal 1755 */ 1756 TRIO_STRING_PUBLIC int 1757 trio_string_equal 1758 TRIO_ARGS2((self, other), 1759 trio_string_t *self, 1760 trio_string_t *other) 1761 { 1762 assert(self); 1763 assert(other); 1764 1765 return trio_equal(self->content, other->content); 1766 } 1767 #endif /* !defined(TRIO_MINIMAL) */ 1768 1769 1770 #if !defined(TRIO_MINIMAL) 1771 /* 1772 * trio_xstring_equal 1773 */ 1774 TRIO_STRING_PUBLIC int 1775 trio_xstring_equal 1776 TRIO_ARGS2((self, other), 1777 trio_string_t *self, 1778 TRIO_CONST char *other) 1779 { 1780 assert(self); 1781 assert(other); 1782 1783 return trio_equal(self->content, other); 1784 } 1785 #endif /* !defined(TRIO_MINIMAL) */ 1786 1787 1788 #if !defined(TRIO_MINIMAL) 1789 /* 1790 * trio_string_equal_max 1791 */ 1792 TRIO_STRING_PUBLIC int 1793 trio_string_equal_max 1794 TRIO_ARGS3((self, max, other), 1795 trio_string_t *self, 1796 size_t max, 1797 trio_string_t *other) 1798 { 1799 assert(self); 1800 assert(other); 1801 1802 return trio_equal_max(self->content, max, other->content); 1803 } 1804 #endif /* !defined(TRIO_MINIMAL) */ 1805 1806 1807 #if !defined(TRIO_MINIMAL) 1808 /* 1809 * trio_xstring_equal_max 1810 */ 1811 TRIO_STRING_PUBLIC int 1812 trio_xstring_equal_max 1813 TRIO_ARGS3((self, max, other), 1814 trio_string_t *self, 1815 size_t max, 1816 TRIO_CONST char *other) 1817 { 1818 assert(self); 1819 assert(other); 1820 1821 return trio_equal_max(self->content, max, other); 1822 } 1823 #endif /* !defined(TRIO_MINIMAL) */ 1824 1825 1826 #if !defined(TRIO_MINIMAL) 1827 /* 1828 * trio_string_equal_case 1829 */ 1830 TRIO_STRING_PUBLIC int 1831 trio_string_equal_case 1832 TRIO_ARGS2((self, other), 1833 trio_string_t *self, 1834 trio_string_t *other) 1835 { 1836 assert(self); 1837 assert(other); 1838 1839 return trio_equal_case(self->content, other->content); 1840 } 1841 #endif /* !defined(TRIO_MINIMAL) */ 1842 1843 1844 #if !defined(TRIO_MINIMAL) 1845 /* 1846 * trio_xstring_equal_case 1847 */ 1848 TRIO_STRING_PUBLIC int 1849 trio_xstring_equal_case 1850 TRIO_ARGS2((self, other), 1851 trio_string_t *self, 1852 TRIO_CONST char *other) 1853 { 1854 assert(self); 1855 assert(other); 1856 1857 return trio_equal_case(self->content, other); 1858 } 1859 #endif /* !defined(TRIO_MINIMAL) */ 1860 1861 1862 #if !defined(TRIO_MINIMAL) 1863 /* 1864 * trio_string_equal_case_max 1865 */ 1866 TRIO_STRING_PUBLIC int 1867 trio_string_equal_case_max 1868 TRIO_ARGS3((self, max, other), 1869 trio_string_t *self, 1870 size_t max, 1871 trio_string_t *other) 1872 { 1873 assert(self); 1874 assert(other); 1875 1876 return trio_equal_case_max(self->content, max, other->content); 1877 } 1878 #endif /* !defined(TRIO_MINIMAL) */ 1879 1880 1881 #if !defined(TRIO_MINIMAL) 1882 /* 1883 * trio_xstring_equal_case_max 1884 */ 1885 TRIO_STRING_PUBLIC int 1886 trio_xstring_equal_case_max 1887 TRIO_ARGS3((self, max, other), 1888 trio_string_t *self, 1889 size_t max, 1890 TRIO_CONST char *other) 1891 { 1892 assert(self); 1893 assert(other); 1894 1895 return trio_equal_case_max(self->content, max, other); 1896 } 1897 #endif /* !defined(TRIO_MINIMAL) */ 1898 1899 1900 #if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) 1901 /* 1902 * trio_string_format_data_max 1903 */ 1904 TRIO_STRING_PUBLIC size_t 1905 trio_string_format_date_max 1906 TRIO_ARGS4((self, max, format, datetime), 1907 trio_string_t *self, 1908 size_t max, 1909 TRIO_CONST char *format, 1910 TRIO_CONST struct tm *datetime) 1911 { 1912 assert(self); 1913 1914 return trio_format_date_max(self->content, max, format, datetime); 1915 } 1916 #endif /* !defined(TRIO_MINIMAL) */ 1917 1918 1919 #if !defined(TRIO_MINIMAL) 1920 /* 1921 * trio_string_index 1922 */ 1923 TRIO_STRING_PUBLIC char * 1924 trio_string_index 1925 TRIO_ARGS2((self, character), 1926 trio_string_t *self, 1927 int character) 1928 { 1929 assert(self); 1930 1931 return trio_index(self->content, character); 1932 } 1933 #endif /* !defined(TRIO_MINIMAL) */ 1934 1935 1936 #if !defined(TRIO_MINIMAL) 1937 /* 1938 * trio_string_index_last 1939 */ 1940 TRIO_STRING_PUBLIC char * 1941 trio_string_index_last 1942 TRIO_ARGS2((self, character), 1943 trio_string_t *self, 1944 int character) 1945 { 1946 assert(self); 1947 1948 return trio_index_last(self->content, character); 1949 } 1950 #endif /* !defined(TRIO_MINIMAL) */ 1951 1952 1953 #if !defined(TRIO_MINIMAL) 1954 /* 1955 * trio_string_length 1956 */ 1957 TRIO_STRING_PUBLIC int 1958 trio_string_length 1959 TRIO_ARGS1((self), 1960 trio_string_t *self) 1961 { 1962 assert(self); 1963 1964 if (self->length == 0) 1965 { 1966 self->length = trio_length(self->content); 1967 } 1968 return self->length; 1969 } 1970 #endif /* !defined(TRIO_MINIMAL) */ 1971 1972 1973 #if !defined(TRIO_MINIMAL) 1974 /* 1975 * trio_string_lower 1976 */ 1977 TRIO_STRING_PUBLIC int 1978 trio_string_lower 1979 TRIO_ARGS1((self), 1980 trio_string_t *self) 1981 { 1982 assert(self); 1983 1984 return trio_lower(self->content); 1985 } 1986 #endif /* !defined(TRIO_MINIMAL) */ 1987 1988 1989 #if !defined(TRIO_MINIMAL) 1990 /* 1991 * trio_string_match 1992 */ 1993 TRIO_STRING_PUBLIC int 1994 trio_string_match 1995 TRIO_ARGS2((self, other), 1996 trio_string_t *self, 1997 trio_string_t *other) 1998 { 1999 assert(self); 2000 assert(other); 2001 2002 return trio_match(self->content, other->content); 2003 } 2004 #endif /* !defined(TRIO_MINIMAL) */ 2005 2006 2007 #if !defined(TRIO_MINIMAL) 2008 /* 2009 * trio_xstring_match 2010 */ 2011 TRIO_STRING_PUBLIC int 2012 trio_xstring_match 2013 TRIO_ARGS2((self, other), 2014 trio_string_t *self, 2015 TRIO_CONST char *other) 2016 { 2017 assert(self); 2018 assert(other); 2019 2020 return trio_match(self->content, other); 2021 } 2022 #endif /* !defined(TRIO_MINIMAL) */ 2023 2024 2025 #if !defined(TRIO_MINIMAL) 2026 /* 2027 * trio_string_match_case 2028 */ 2029 TRIO_STRING_PUBLIC int 2030 trio_string_match_case 2031 TRIO_ARGS2((self, other), 2032 trio_string_t *self, 2033 trio_string_t *other) 2034 { 2035 assert(self); 2036 assert(other); 2037 2038 return trio_match_case(self->content, other->content); 2039 } 2040 #endif /* !defined(TRIO_MINIMAL) */ 2041 2042 2043 #if !defined(TRIO_MINIMAL) 2044 /* 2045 * trio_xstring_match_case 2046 */ 2047 TRIO_STRING_PUBLIC int 2048 trio_xstring_match_case 2049 TRIO_ARGS2((self, other), 2050 trio_string_t *self, 2051 TRIO_CONST char *other) 2052 { 2053 assert(self); 2054 assert(other); 2055 2056 return trio_match_case(self->content, other); 2057 } 2058 #endif /* !defined(TRIO_MINIMAL) */ 2059 2060 2061 #if !defined(TRIO_MINIMAL) 2062 /* 2063 * trio_string_substring 2064 */ 2065 TRIO_STRING_PUBLIC char * 2066 trio_string_substring 2067 TRIO_ARGS2((self, other), 2068 trio_string_t *self, 2069 trio_string_t *other) 2070 { 2071 assert(self); 2072 assert(other); 2073 2074 return trio_substring(self->content, other->content); 2075 } 2076 #endif /* !defined(TRIO_MINIMAL) */ 2077 2078 2079 #if !defined(TRIO_MINIMAL) 2080 /* 2081 * trio_xstring_substring 2082 */ 2083 TRIO_STRING_PUBLIC char * 2084 trio_xstring_substring 2085 TRIO_ARGS2((self, other), 2086 trio_string_t *self, 2087 TRIO_CONST char *other) 2088 { 2089 assert(self); 2090 assert(other); 2091 2092 return trio_substring(self->content, other); 2093 } 2094 #endif /* !defined(TRIO_MINIMAL) */ 2095 2096 2097 #if !defined(TRIO_MINIMAL) 2098 /* 2099 * trio_string_upper 2100 */ 2101 TRIO_STRING_PUBLIC int 2102 trio_string_upper 2103 TRIO_ARGS1((self), 2104 trio_string_t *self) 2105 { 2106 assert(self); 2107 2108 return trio_upper(self->content); 2109 } 2110 #endif /* !defined(TRIO_MINIMAL) */ 2111 2112 /** @} End of DynamicStrings */ 2113