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