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 98struct _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) 110static 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*/ 130TRIO_STRING_PUBLIC char * 131trio_create 132TRIO_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*/ 144TRIO_STRING_PUBLIC void 145trio_destroy 146TRIO_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*/ 162TRIO_STRING_PUBLIC size_t 163trio_length 164TRIO_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*/ 185TRIO_STRING_PUBLIC int 186trio_append 187TRIO_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*/ 214TRIO_STRING_PUBLIC int 215trio_append_max 216TRIO_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*/ 245TRIO_STRING_PUBLIC int 246trio_contains 247TRIO_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*/ 273TRIO_STRING_PUBLIC int 274trio_copy 275TRIO_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*/ 302TRIO_STRING_PUBLIC int 303trio_copy_max 304TRIO_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 */ 322TRIO_STRING_PRIVATE char * 323TrioDuplicateMax 324TRIO_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*/ 351TRIO_STRING_PUBLIC char * 352trio_duplicate 353TRIO_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*/ 370TRIO_STRING_PUBLIC char * 371trio_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*/ 399TRIO_STRING_PUBLIC int 400trio_equal 401TRIO_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*/ 438TRIO_STRING_PUBLIC int 439trio_equal_case 440TRIO_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*/ 466TRIO_STRING_PUBLIC int 467trio_equal_case_max 468TRIO_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*/ 494TRIO_STRING_PUBLIC int 495trio_equal_locale 496TRIO_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*/ 521TRIO_STRING_PUBLIC int 522trio_equal_max 523TRIO_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*/ 561TRIO_STRING_PUBLIC TRIO_CONST char * 562trio_error 563TRIO_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*/ 600TRIO_STRING_PUBLIC size_t 601trio_format_date_max 602TRIO_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*/ 629TRIO_STRING_PUBLIC unsigned long 630trio_hash 631TRIO_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 */ 666TRIO_STRING_PUBLIC char * 667trio_index 668TRIO_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 */ 687TRIO_STRING_PUBLIC char * 688trio_index_last 689TRIO_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*/ 707TRIO_STRING_PUBLIC int 708trio_lower 709TRIO_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*/ 733TRIO_STRING_PUBLIC int 734trio_match 735TRIO_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*/ 786TRIO_STRING_PUBLIC int 787trio_match_case 788TRIO_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*/ 834TRIO_STRING_PUBLIC size_t 835trio_span_function 836TRIO_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*/ 866TRIO_STRING_PUBLIC char * 867trio_substring 868TRIO_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*/ 890TRIO_STRING_PUBLIC char * 891trio_substring_max 892TRIO_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*/ 931TRIO_STRING_PUBLIC char * 932trio_tokenize 933TRIO_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 */ 966TRIO_STRING_PUBLIC trio_long_double_t 967trio_to_long_double 968TRIO_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*/ 1101TRIO_STRING_PUBLIC double 1102trio_to_double 1103TRIO_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*/ 1124TRIO_STRING_PUBLIC float 1125trio_to_float 1126TRIO_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*/ 1146TRIO_STRING_PUBLIC long 1147trio_to_long 1148TRIO_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*/ 1167TRIO_STRING_PUBLIC int 1168trio_to_lower 1169TRIO_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*/ 1195TRIO_STRING_PUBLIC unsigned long 1196trio_to_unsigned_long 1197TRIO_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*/ 1216TRIO_STRING_PUBLIC int 1217trio_to_upper 1218TRIO_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*/ 1242TRIO_STRING_PUBLIC int 1243trio_upper 1244TRIO_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 */ 1271TRIO_STRING_PRIVATE trio_string_t * 1272TrioStringAlloc(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 */ 1293TRIO_STRING_PRIVATE BOOLEAN_T 1294TrioStringGrow 1295TRIO_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 */ 1326TRIO_STRING_PRIVATE BOOLEAN_T 1327TrioStringGrowTo 1328TRIO_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*/ 1347TRIO_STRING_PUBLIC trio_string_t * 1348trio_string_create 1349TRIO_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*/ 1379TRIO_STRING_PUBLIC void 1380trio_string_destroy 1381TRIO_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*/ 1409TRIO_STRING_PUBLIC char * 1410trio_string_get 1411TRIO_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*/ 1456TRIO_STRING_PUBLIC char * 1457trio_string_extract 1458TRIO_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*/ 1487TRIO_STRING_PUBLIC void 1488trio_xstring_set 1489TRIO_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 */ 1504TRIO_STRING_PUBLIC int 1505trio_string_size 1506TRIO_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 */ 1518TRIO_STRING_PUBLIC void 1519trio_string_terminate 1520TRIO_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*/ 1535TRIO_STRING_PUBLIC int 1536trio_string_append 1537TRIO_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 */ 1563TRIO_STRING_PUBLIC int 1564trio_xstring_append 1565TRIO_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 */ 1590TRIO_STRING_PUBLIC int 1591trio_xstring_append_char 1592TRIO_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*/ 1620TRIO_STRING_PUBLIC int 1621trio_string_contains 1622TRIO_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 */ 1638TRIO_STRING_PUBLIC int 1639trio_xstring_contains 1640TRIO_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 */ 1656TRIO_STRING_PUBLIC int 1657trio_string_copy 1658TRIO_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 */ 1675TRIO_STRING_PUBLIC int 1676trio_xstring_copy 1677TRIO_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 */ 1694TRIO_STRING_PUBLIC trio_string_t * 1695trio_string_duplicate 1696TRIO_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 */ 1725TRIO_STRING_PUBLIC trio_string_t * 1726trio_xstring_duplicate 1727TRIO_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 */ 1756TRIO_STRING_PUBLIC int 1757trio_string_equal 1758TRIO_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 */ 1774TRIO_STRING_PUBLIC int 1775trio_xstring_equal 1776TRIO_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 */ 1792TRIO_STRING_PUBLIC int 1793trio_string_equal_max 1794TRIO_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 */ 1811TRIO_STRING_PUBLIC int 1812trio_xstring_equal_max 1813TRIO_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 */ 1830TRIO_STRING_PUBLIC int 1831trio_string_equal_case 1832TRIO_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 */ 1848TRIO_STRING_PUBLIC int 1849trio_xstring_equal_case 1850TRIO_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 */ 1866TRIO_STRING_PUBLIC int 1867trio_string_equal_case_max 1868TRIO_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 */ 1885TRIO_STRING_PUBLIC int 1886trio_xstring_equal_case_max 1887TRIO_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 */ 1904TRIO_STRING_PUBLIC size_t 1905trio_string_format_date_max 1906TRIO_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 */ 1923TRIO_STRING_PUBLIC char * 1924trio_string_index 1925TRIO_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 */ 1940TRIO_STRING_PUBLIC char * 1941trio_string_index_last 1942TRIO_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 */ 1957TRIO_STRING_PUBLIC int 1958trio_string_length 1959TRIO_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 */ 1977TRIO_STRING_PUBLIC int 1978trio_string_lower 1979TRIO_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 */ 1993TRIO_STRING_PUBLIC int 1994trio_string_match 1995TRIO_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 */ 2011TRIO_STRING_PUBLIC int 2012trio_xstring_match 2013TRIO_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 */ 2029TRIO_STRING_PUBLIC int 2030trio_string_match_case 2031TRIO_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 */ 2047TRIO_STRING_PUBLIC int 2048trio_xstring_match_case 2049TRIO_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 */ 2065TRIO_STRING_PUBLIC char * 2066trio_string_substring 2067TRIO_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 */ 2083TRIO_STRING_PUBLIC char * 2084trio_xstring_substring 2085TRIO_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 */ 2101TRIO_STRING_PUBLIC int 2102trio_string_upper 2103TRIO_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