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
88 struct _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)
100 static 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 */
120 TRIO_STRING_PUBLIC char *
121 trio_create
122 TRIO_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 */
134 TRIO_STRING_PUBLIC void
135 trio_destroy
136 TRIO_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 */
152 TRIO_STRING_PUBLIC size_t
153 trio_length
154 TRIO_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 */
175 TRIO_STRING_PUBLIC int
176 trio_append
177 TRIO_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 */
204 TRIO_STRING_PUBLIC int
205 trio_append_max
206 TRIO_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 */
235 TRIO_STRING_PUBLIC int
236 trio_contains
237 TRIO_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 */
263 TRIO_STRING_PUBLIC int
264 trio_copy
265 TRIO_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 */
292 TRIO_STRING_PUBLIC int
293 trio_copy_max
294 TRIO_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 */
312 TRIO_STRING_PRIVATE char *
313 TrioDuplicateMax
314 TRIO_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 */
341 TRIO_STRING_PUBLIC char *
342 trio_duplicate
343 TRIO_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 */
360 TRIO_STRING_PUBLIC char *
361 trio_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 */
389 TRIO_STRING_PUBLIC int
390 trio_equal
391 TRIO_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 */
428 TRIO_STRING_PUBLIC int
429 trio_equal_case
430 TRIO_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 */
456 TRIO_STRING_PUBLIC int
457 trio_equal_case_max
458 TRIO_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 */
484 TRIO_STRING_PUBLIC int
485 trio_equal_locale
486 TRIO_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 */
511 TRIO_STRING_PUBLIC int
512 trio_equal_max
513 TRIO_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 */
551 TRIO_STRING_PUBLIC TRIO_CONST char *
552 trio_error
553 TRIO_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 */
590 TRIO_STRING_PUBLIC size_t
591 trio_format_date_max
592 TRIO_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 */
619 TRIO_STRING_PUBLIC unsigned long
620 trio_hash
621 TRIO_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 */
656 TRIO_STRING_PUBLIC char *
657 trio_index
658 TRIO_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 */
677 TRIO_STRING_PUBLIC char *
678 trio_index_last
679 TRIO_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 */
697 TRIO_STRING_PUBLIC int
698 trio_lower
699 TRIO_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 */
723 TRIO_STRING_PUBLIC int
724 trio_match
725 TRIO_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 */
776 TRIO_STRING_PUBLIC int
777 trio_match_case
778 TRIO_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 */
824 TRIO_STRING_PUBLIC size_t
825 trio_span_function
826 TRIO_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 */
856 TRIO_STRING_PUBLIC char *
857 trio_substring
858 TRIO_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 */
880 TRIO_STRING_PUBLIC char *
881 trio_substring_max
882 TRIO_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 */
921 TRIO_STRING_PUBLIC char *
922 trio_tokenize
923 TRIO_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 */
956 TRIO_STRING_PUBLIC trio_long_double_t
957 trio_to_long_double
958 TRIO_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 */
1091 TRIO_STRING_PUBLIC double
1092 trio_to_double
1093 TRIO_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 */
1114 TRIO_STRING_PUBLIC float
1115 trio_to_float
1116 TRIO_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 */
1136 TRIO_STRING_PUBLIC long
1137 trio_to_long
1138 TRIO_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 */
1157 TRIO_STRING_PUBLIC int
1158 trio_to_lower
1159 TRIO_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 */
1185 TRIO_STRING_PUBLIC unsigned long
1186 trio_to_unsigned_long
1187 TRIO_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 */
1206 TRIO_STRING_PUBLIC int
1207 trio_to_upper
1208 TRIO_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 */
1232 TRIO_STRING_PUBLIC int
1233 trio_upper
1234 TRIO_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 */
1261 TRIO_STRING_PRIVATE trio_string_t *
TrioStringAlloc(TRIO_NOARGS)1262 TrioStringAlloc(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 */
1283 TRIO_STRING_PRIVATE BOOLEAN_T
1284 TrioStringGrow
1285 TRIO_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 */
1316 TRIO_STRING_PRIVATE BOOLEAN_T
1317 TrioStringGrowTo
1318 TRIO_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 */
1337 TRIO_STRING_PUBLIC trio_string_t *
1338 trio_string_create
1339 TRIO_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 */
1369 TRIO_STRING_PUBLIC void
1370 trio_string_destroy
1371 TRIO_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 */
1399 TRIO_STRING_PUBLIC char *
1400 trio_string_get
1401 TRIO_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 */
1446 TRIO_STRING_PUBLIC char *
1447 trio_string_extract
1448 TRIO_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 */
1477 TRIO_STRING_PUBLIC void
1478 trio_xstring_set
1479 TRIO_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 */
1494 TRIO_STRING_PUBLIC int
1495 trio_string_size
1496 TRIO_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 */
1508 TRIO_STRING_PUBLIC void
1509 trio_string_terminate
1510 TRIO_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 */
1525 TRIO_STRING_PUBLIC int
1526 trio_string_append
1527 TRIO_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 */
1553 TRIO_STRING_PUBLIC int
1554 trio_xstring_append
1555 TRIO_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 */
1580 TRIO_STRING_PUBLIC int
1581 trio_xstring_append_char
1582 TRIO_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 */
1610 TRIO_STRING_PUBLIC int
1611 trio_string_contains
1612 TRIO_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 */
1628 TRIO_STRING_PUBLIC int
1629 trio_xstring_contains
1630 TRIO_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 */
1646 TRIO_STRING_PUBLIC int
1647 trio_string_copy
1648 TRIO_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 */
1665 TRIO_STRING_PUBLIC int
1666 trio_xstring_copy
1667 TRIO_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 */
1684 TRIO_STRING_PUBLIC trio_string_t *
1685 trio_string_duplicate
1686 TRIO_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 */
1715 TRIO_STRING_PUBLIC trio_string_t *
1716 trio_xstring_duplicate
1717 TRIO_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 */
1746 TRIO_STRING_PUBLIC int
1747 trio_string_equal
1748 TRIO_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 */
1764 TRIO_STRING_PUBLIC int
1765 trio_xstring_equal
1766 TRIO_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 */
1782 TRIO_STRING_PUBLIC int
1783 trio_string_equal_max
1784 TRIO_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 */
1801 TRIO_STRING_PUBLIC int
1802 trio_xstring_equal_max
1803 TRIO_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 */
1820 TRIO_STRING_PUBLIC int
1821 trio_string_equal_case
1822 TRIO_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 */
1838 TRIO_STRING_PUBLIC int
1839 trio_xstring_equal_case
1840 TRIO_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 */
1856 TRIO_STRING_PUBLIC int
1857 trio_string_equal_case_max
1858 TRIO_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 */
1875 TRIO_STRING_PUBLIC int
1876 trio_xstring_equal_case_max
1877 TRIO_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 */
1894 TRIO_STRING_PUBLIC size_t
1895 trio_string_format_date_max
1896 TRIO_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 */
1913 TRIO_STRING_PUBLIC char *
1914 trio_string_index
1915 TRIO_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 */
1930 TRIO_STRING_PUBLIC char *
1931 trio_string_index_last
1932 TRIO_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 */
1947 TRIO_STRING_PUBLIC int
1948 trio_string_length
1949 TRIO_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 */
1967 TRIO_STRING_PUBLIC int
1968 trio_string_lower
1969 TRIO_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 */
1983 TRIO_STRING_PUBLIC int
1984 trio_string_match
1985 TRIO_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 */
2001 TRIO_STRING_PUBLIC int
2002 trio_xstring_match
2003 TRIO_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 */
2019 TRIO_STRING_PUBLIC int
2020 trio_string_match_case
2021 TRIO_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 */
2037 TRIO_STRING_PUBLIC int
2038 trio_xstring_match_case
2039 TRIO_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 */
2055 TRIO_STRING_PUBLIC char *
2056 trio_string_substring
2057 TRIO_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 */
2073 TRIO_STRING_PUBLIC char *
2074 trio_xstring_substring
2075 TRIO_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 */
2091 TRIO_STRING_PUBLIC int
2092 trio_string_upper
2093 TRIO_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