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