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