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