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