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