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