• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
92 struct _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)
104 static 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 */
124 TRIO_STRING_PUBLIC char *
125 trio_create
126 TRIO_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 */
138 TRIO_STRING_PUBLIC void
139 trio_destroy
140 TRIO_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 */
156 TRIO_STRING_PUBLIC size_t
157 trio_length
158 TRIO_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 */
179 TRIO_STRING_PUBLIC int
180 trio_append
181 TRIO_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 */
208 TRIO_STRING_PUBLIC int
209 trio_append_max
210 TRIO_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 */
239 TRIO_STRING_PUBLIC int
240 trio_contains
241 TRIO_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 */
267 TRIO_STRING_PUBLIC int
268 trio_copy
269 TRIO_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 */
296 TRIO_STRING_PUBLIC int
297 trio_copy_max
298 TRIO_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  */
316 TRIO_STRING_PRIVATE char *
317 TrioDuplicateMax
318 TRIO_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 */
345 TRIO_STRING_PUBLIC char *
346 trio_duplicate
347 TRIO_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 */
364 TRIO_STRING_PUBLIC char *
365 trio_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 */
393 TRIO_STRING_PUBLIC int
394 trio_equal
395 TRIO_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 */
432 TRIO_STRING_PUBLIC int
433 trio_equal_case
434 TRIO_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 */
460 TRIO_STRING_PUBLIC int
461 trio_equal_case_max
462 TRIO_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 */
488 TRIO_STRING_PUBLIC int
489 trio_equal_locale
490 TRIO_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 */
515 TRIO_STRING_PUBLIC int
516 trio_equal_max
517 TRIO_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 */
555 TRIO_STRING_PUBLIC TRIO_CONST char *
556 trio_error
557 TRIO_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 */
594 TRIO_STRING_PUBLIC size_t
595 trio_format_date_max
596 TRIO_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 */
623 TRIO_STRING_PUBLIC unsigned long
624 trio_hash
625 TRIO_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  */
660 TRIO_STRING_PUBLIC char *
661 trio_index
662 TRIO_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  */
681 TRIO_STRING_PUBLIC char *
682 trio_index_last
683 TRIO_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 */
701 TRIO_STRING_PUBLIC int
702 trio_lower
703 TRIO_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 */
727 TRIO_STRING_PUBLIC int
728 trio_match
729 TRIO_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 */
780 TRIO_STRING_PUBLIC int
781 trio_match_case
782 TRIO_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 */
828 TRIO_STRING_PUBLIC size_t
829 trio_span_function
830 TRIO_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 */
860 TRIO_STRING_PUBLIC char *
861 trio_substring
862 TRIO_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 */
884 TRIO_STRING_PUBLIC char *
885 trio_substring_max
886 TRIO_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 */
925 TRIO_STRING_PUBLIC char *
926 trio_tokenize
927 TRIO_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 */
960 TRIO_STRING_PUBLIC trio_long_double_t
961 trio_to_long_double
962 TRIO_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 */
1095 TRIO_STRING_PUBLIC double
1096 trio_to_double
1097 TRIO_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 */
1118 TRIO_STRING_PUBLIC float
1119 trio_to_float
1120 TRIO_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 */
1140 TRIO_STRING_PUBLIC long
1141 trio_to_long
1142 TRIO_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 */
1161 TRIO_STRING_PUBLIC int
1162 trio_to_lower
1163 TRIO_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 */
1189 TRIO_STRING_PUBLIC unsigned long
1190 trio_to_unsigned_long
1191 TRIO_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 */
1210 TRIO_STRING_PUBLIC int
1211 trio_to_upper
1212 TRIO_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 */
1236 TRIO_STRING_PUBLIC int
1237 trio_upper
1238 TRIO_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  */
1265 TRIO_STRING_PRIVATE trio_string_t *
TrioStringAlloc(TRIO_NOARGS)1266 TrioStringAlloc(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  */
1287 TRIO_STRING_PRIVATE BOOLEAN_T
1288 TrioStringGrow
1289 TRIO_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  */
1320 TRIO_STRING_PRIVATE BOOLEAN_T
1321 TrioStringGrowTo
1322 TRIO_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 */
1341 TRIO_STRING_PUBLIC trio_string_t *
1342 trio_string_create
1343 TRIO_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 */
1373 TRIO_STRING_PUBLIC void
1374 trio_string_destroy
1375 TRIO_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 */
1403 TRIO_STRING_PUBLIC char *
1404 trio_string_get
1405 TRIO_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 */
1450 TRIO_STRING_PUBLIC char *
1451 trio_string_extract
1452 TRIO_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 */
1481 TRIO_STRING_PUBLIC void
1482 trio_xstring_set
1483 TRIO_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  */
1498 TRIO_STRING_PUBLIC int
1499 trio_string_size
1500 TRIO_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  */
1512 TRIO_STRING_PUBLIC void
1513 trio_string_terminate
1514 TRIO_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 */
1529 TRIO_STRING_PUBLIC int
1530 trio_string_append
1531 TRIO_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  */
1557 TRIO_STRING_PUBLIC int
1558 trio_xstring_append
1559 TRIO_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  */
1584 TRIO_STRING_PUBLIC int
1585 trio_xstring_append_char
1586 TRIO_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 */
1614 TRIO_STRING_PUBLIC int
1615 trio_string_contains
1616 TRIO_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  */
1632 TRIO_STRING_PUBLIC int
1633 trio_xstring_contains
1634 TRIO_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  */
1650 TRIO_STRING_PUBLIC int
1651 trio_string_copy
1652 TRIO_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  */
1669 TRIO_STRING_PUBLIC int
1670 trio_xstring_copy
1671 TRIO_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  */
1688 TRIO_STRING_PUBLIC trio_string_t *
1689 trio_string_duplicate
1690 TRIO_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  */
1719 TRIO_STRING_PUBLIC trio_string_t *
1720 trio_xstring_duplicate
1721 TRIO_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  */
1750 TRIO_STRING_PUBLIC int
1751 trio_string_equal
1752 TRIO_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  */
1768 TRIO_STRING_PUBLIC int
1769 trio_xstring_equal
1770 TRIO_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  */
1786 TRIO_STRING_PUBLIC int
1787 trio_string_equal_max
1788 TRIO_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  */
1805 TRIO_STRING_PUBLIC int
1806 trio_xstring_equal_max
1807 TRIO_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  */
1824 TRIO_STRING_PUBLIC int
1825 trio_string_equal_case
1826 TRIO_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  */
1842 TRIO_STRING_PUBLIC int
1843 trio_xstring_equal_case
1844 TRIO_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  */
1860 TRIO_STRING_PUBLIC int
1861 trio_string_equal_case_max
1862 TRIO_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  */
1879 TRIO_STRING_PUBLIC int
1880 trio_xstring_equal_case_max
1881 TRIO_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  */
1898 TRIO_STRING_PUBLIC size_t
1899 trio_string_format_date_max
1900 TRIO_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  */
1917 TRIO_STRING_PUBLIC char *
1918 trio_string_index
1919 TRIO_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  */
1934 TRIO_STRING_PUBLIC char *
1935 trio_string_index_last
1936 TRIO_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  */
1951 TRIO_STRING_PUBLIC int
1952 trio_string_length
1953 TRIO_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  */
1971 TRIO_STRING_PUBLIC int
1972 trio_string_lower
1973 TRIO_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  */
1987 TRIO_STRING_PUBLIC int
1988 trio_string_match
1989 TRIO_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  */
2005 TRIO_STRING_PUBLIC int
2006 trio_xstring_match
2007 TRIO_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  */
2023 TRIO_STRING_PUBLIC int
2024 trio_string_match_case
2025 TRIO_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  */
2041 TRIO_STRING_PUBLIC int
2042 trio_xstring_match_case
2043 TRIO_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  */
2059 TRIO_STRING_PUBLIC char *
2060 trio_string_substring
2061 TRIO_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  */
2077 TRIO_STRING_PUBLIC char *
2078 trio_xstring_substring
2079 TRIO_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  */
2095 TRIO_STRING_PUBLIC int
2096 trio_string_upper
2097 TRIO_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