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