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