2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * \brief Strings that know their length.
32 * \author Olaf Wintermann
34 * \copyright 2-Clause BSD License
41 #include "allocator.h"
44 * The UCX string structure.
48 * A pointer to the string.
49 * \note The string is not necessarily \c NULL terminated.
50 * Always use the length.
53 /** The length of the string */
60 typedef struct cx_mutstr_s cxmutstr;
63 * The UCX string structure for immutable (constant) strings.
67 * A pointer to the immutable string.
68 * \note The string is not necessarily \c NULL terminated.
69 * Always use the length.
72 /** The length of the string */
77 * An immutable string.
79 typedef struct cx_string_s cxstring;
82 * Context for string tokenizing.
84 struct cx_strtok_ctx_s {
86 * The string to tokenize.
90 * The primary delimiter.
94 * Optional array of more delimiters.
96 cxstring const *delim_more;
98 * Length of the array containing more delimiters.
100 size_t delim_more_count;
102 * Position of the currently active token in the source string.
106 * Position of next delimiter in the source string.
108 * If the tokenizer has not yet returned a token, the content of this field
109 * is undefined. If the tokenizer reached the end of the string, this field
110 * contains the length of the source string.
114 * The position of the next token in the source string.
118 * The number of already found tokens.
122 * The maximum number of tokens that shall be returned.
128 * A string tokenizing context.
130 typedef struct cx_strtok_ctx_s CxStrtokCtx;
133 * A literal initializer for an UCX string structure.
135 * The argument MUST be a string (const char*) \em literal.
137 * @param literal the string literal
139 #define CX_STR(literal) {literal, sizeof(literal) - 1}
147 * Wraps a mutable string that must be zero-terminated.
149 * The length is implicitly inferred by using a call to \c strlen().
151 * \note the wrapped string will share the specified pointer to the string.
152 * If you do want a copy, use cx_strdup() on the return value of this function.
154 * If you need to wrap a constant string, use cx_str().
156 * @param cstring the string to wrap, must be zero-terminated
157 * @return the wrapped string
161 __attribute__((__warn_unused_result__, __nonnull__))
162 cxmutstr cx_mutstr(char *cstring);
165 * Wraps a string that does not need to be zero-terminated.
167 * The argument may be \c NULL if the length is zero.
169 * \note the wrapped string will share the specified pointer to the string.
170 * If you do want a copy, use cx_strdup() on the return value of this function.
172 * If you need to wrap a constant string, use cx_strn().
174 * @param cstring the string to wrap (or \c NULL, only if the length is zero)
175 * @param length the length of the string
176 * @return the wrapped string
180 __attribute__((__warn_unused_result__))
187 * Wraps a string that must be zero-terminated.
189 * The length is implicitly inferred by using a call to \c strlen().
191 * \note the wrapped string will share the specified pointer to the string.
192 * If you do want a copy, use cx_strdup() on the return value of this function.
194 * If you need to wrap a non-constant string, use cx_mutstr().
196 * @param cstring the string to wrap, must be zero-terminated
197 * @return the wrapped string
201 __attribute__((__warn_unused_result__, __nonnull__))
202 cxstring cx_str(char const *cstring);
206 * Wraps a string that does not need to be zero-terminated.
208 * The argument may be \c NULL if the length is zero.
210 * \note the wrapped string will share the specified pointer to the string.
211 * If you do want a copy, use cx_strdup() on the return value of this function.
213 * If you need to wrap a non-constant string, use cx_mutstrn().
215 * @param cstring the string to wrap (or \c NULL, only if the length is zero)
216 * @param length the length of the string
217 * @return the wrapped string
221 __attribute__((__warn_unused_result__))
228 * Casts a mutable string to an immutable string.
230 * \note This is not seriously a cast. Instead you get a copy
231 * of the struct with the desired pointer type. Both structs still
232 * point to the same location, though!
234 * @param str the mutable string to cast
235 * @return an immutable copy of the string pointer
237 __attribute__((__warn_unused_result__))
238 cxstring cx_strcast(cxmutstr str);
241 * Passes the pointer in this string to \c free().
243 * The pointer in the struct is set to \c NULL and the length is set to zero.
245 * \note There is no implementation for cxstring, because it is unlikely that
246 * you ever have a \c char \c const* you are really supposed to free. If you
247 * encounter such situation, you should double-check your code.
249 * @param str the string to free
251 __attribute__((__nonnull__))
252 void cx_strfree(cxmutstr *str);
255 * Passes the pointer in this string to the allocators free function.
257 * The pointer in the struct is set to \c NULL and the length is set to zero.
259 * \note There is no implementation for cxstring, because it is unlikely that
260 * you ever have a \c char \c const* you are really supposed to free. If you
261 * encounter such situation, you should double-check your code.
263 * @param alloc the allocator
264 * @param str the string to free
266 __attribute__((__nonnull__))
273 * Returns the accumulated length of all specified strings.
275 * \attention if the count argument is larger than the number of the
276 * specified strings, the behavior is undefined.
278 * @param count the total number of specified strings
279 * @param ... all strings
280 * @return the accumulated length of all strings
282 __attribute__((__warn_unused_result__))
289 * Concatenates two or more strings.
291 * The resulting string will be allocated by the specified allocator.
292 * So developers \em must pass the return value to cx_strfree() eventually.
294 * \note It is guaranteed that there is only one allocation.
295 * It is also guaranteed that the returned string is zero-terminated.
297 * @param alloc the allocator to use
298 * @param count the total number of strings to concatenate
299 * @param ... all strings
300 * @return the concatenated string
302 __attribute__((__warn_unused_result__, __nonnull__))
303 cxmutstr cx_strcat_a(
310 * Concatenates two or more strings.
312 * The resulting string will be allocated by standard \c malloc().
313 * So developers \em must pass the return value to cx_strfree() eventually.
315 * \note It is guaranteed that there is only one allocation.
316 * It is also guaranteed that the returned string is zero-terminated.
318 * @param count the total number of strings to concatenate
319 * @param ... all strings
320 * @return the concatenated string
322 #define cx_strcat(count, ...) \
323 cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__)
326 * Returns a substring starting at the specified location.
328 * \attention the new string references the same memory area as the
329 * input string and is usually \em not zero-terminated.
330 * Use cx_strdup() to get a copy.
332 * @param string input string
333 * @param start start location of the substring
334 * @return a substring of \p string starting at \p start
337 * @see cx_strsubs_m()
338 * @see cx_strsubsl_m()
340 __attribute__((__warn_unused_result__))
347 * Returns a substring starting at the specified location.
349 * The returned string will be limited to \p length bytes or the number
350 * of bytes available in \p string, whichever is smaller.
352 * \attention the new string references the same memory area as the
353 * input string and is usually \em not zero-terminated.
354 * Use cx_strdup() to get a copy.
356 * @param string input string
357 * @param start start location of the substring
358 * @param length the maximum length of the returned string
359 * @return a substring of \p string starting at \p start
362 * @see cx_strsubs_m()
363 * @see cx_strsubsl_m()
365 __attribute__((__warn_unused_result__))
366 cxstring cx_strsubsl(
373 * Returns a substring starting at the specified location.
375 * \attention the new string references the same memory area as the
376 * input string and is usually \em not zero-terminated.
377 * Use cx_strdup() to get a copy.
379 * @param string input string
380 * @param start start location of the substring
381 * @return a substring of \p string starting at \p start
383 * @see cx_strsubsl_m()
387 __attribute__((__warn_unused_result__))
388 cxmutstr cx_strsubs_m(
394 * Returns a substring starting at the specified location.
396 * The returned string will be limited to \p length bytes or the number
397 * of bytes available in \p string, whichever is smaller.
399 * \attention the new string references the same memory area as the
400 * input string and is usually \em not zero-terminated.
401 * Use cx_strdup() to get a copy.
403 * @param string input string
404 * @param start start location of the substring
405 * @param length the maximum length of the returned string
406 * @return a substring of \p string starting at \p start
408 * @see cx_strsubs_m()
412 __attribute__((__warn_unused_result__))
413 cxmutstr cx_strsubsl_m(
420 * Returns a substring starting at the location of the first occurrence of the
421 * specified character.
423 * If the string does not contain the character, an empty string is returned.
425 * @param string the string where to locate the character
426 * @param chr the character to locate
427 * @return a substring starting at the first location of \p chr
431 __attribute__((__warn_unused_result__))
438 * Returns a substring starting at the location of the first occurrence of the
439 * specified character.
441 * If the string does not contain the character, an empty string is returned.
443 * @param string the string where to locate the character
444 * @param chr the character to locate
445 * @return a substring starting at the first location of \p chr
449 __attribute__((__warn_unused_result__))
450 cxmutstr cx_strchr_m(
456 * Returns a substring starting at the location of the last occurrence of the
457 * specified character.
459 * If the string does not contain the character, an empty string is returned.
461 * @param string the string where to locate the character
462 * @param chr the character to locate
463 * @return a substring starting at the last location of \p chr
465 * @see cx_strrchr_m()
467 __attribute__((__warn_unused_result__))
474 * Returns a substring starting at the location of the last occurrence of the
475 * specified character.
477 * If the string does not contain the character, an empty string is returned.
479 * @param string the string where to locate the character
480 * @param chr the character to locate
481 * @return a substring starting at the last location of \p chr
485 __attribute__((__warn_unused_result__))
486 cxmutstr cx_strrchr_m(
492 * Returns a substring starting at the location of the first occurrence of the
495 * If \p haystack does not contain \p needle, an empty string is returned.
497 * If \p needle is an empty string, the complete \p haystack is
500 * @param haystack the string to be scanned
501 * @param needle string containing the sequence of characters to match
502 * @return a substring starting at the first occurrence of
503 * \p needle, or an empty string, if the sequence is not
507 __attribute__((__warn_unused_result__))
514 * Returns a substring starting at the location of the first occurrence of the
517 * If \p haystack does not contain \p needle, an empty string is returned.
519 * If \p needle is an empty string, the complete \p haystack is
522 * @param haystack the string to be scanned
523 * @param needle string containing the sequence of characters to match
524 * @return a substring starting at the first occurrence of
525 * \p needle, or an empty string, if the sequence is not
529 __attribute__((__warn_unused_result__))
530 cxmutstr cx_strstr_m(
536 * Splits a given string using a delimiter string.
538 * \note The resulting array contains strings that point to the source
539 * \p string. Use cx_strdup() to get copies.
541 * @param string the string to split
542 * @param delim the delimiter
543 * @param limit the maximum number of split items
544 * @param output a pre-allocated array of at least \p limit length
545 * @return the actual number of split items
547 __attribute__((__warn_unused_result__, __nonnull__))
556 * Splits a given string using a delimiter string.
558 * The array pointed to by \p output will be allocated by \p allocator.
560 * \note The resulting array contains strings that point to the source
561 * \p string. Use cx_strdup() to get copies.
563 * \attention If allocation fails, the \c NULL pointer will be written to
564 * \p output and the number returned will be zero.
566 * @param allocator the allocator to use for allocating the resulting array
567 * @param string the string to split
568 * @param delim the delimiter
569 * @param limit the maximum number of split items
570 * @param output a pointer where the address of the allocated array shall be
572 * @return the actual number of split items
574 __attribute__((__warn_unused_result__, __nonnull__))
575 size_t cx_strsplit_a(
576 CxAllocator *allocator,
585 * Splits a given string using a delimiter string.
587 * \note The resulting array contains strings that point to the source
588 * \p string. Use cx_strdup() to get copies.
590 * @param string the string to split
591 * @param delim the delimiter
592 * @param limit the maximum number of split items
593 * @param output a pre-allocated array of at least \p limit length
594 * @return the actual number of split items
596 __attribute__((__warn_unused_result__, __nonnull__))
597 size_t cx_strsplit_m(
605 * Splits a given string using a delimiter string.
607 * The array pointed to by \p output will be allocated by \p allocator.
609 * \note The resulting array contains strings that point to the source
610 * \p string. Use cx_strdup() to get copies.
612 * \attention If allocation fails, the \c NULL pointer will be written to
613 * \p output and the number returned will be zero.
615 * @param allocator the allocator to use for allocating the resulting array
616 * @param string the string to split
617 * @param delim the delimiter
618 * @param limit the maximum number of split items
619 * @param output a pointer where the address of the allocated array shall be
621 * @return the actual number of split items
623 __attribute__((__warn_unused_result__, __nonnull__))
624 size_t cx_strsplit_ma(
625 CxAllocator *allocator,
633 * Compares two strings.
635 * @param s1 the first string
636 * @param s2 the second string
637 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
638 * than \p s2, zero if both strings equal
640 __attribute__((__warn_unused_result__))
647 * Compares two strings ignoring case.
649 * @param s1 the first string
650 * @param s2 the second string
651 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
652 * than \p s2, zero if both strings equal ignoring case
654 __attribute__((__warn_unused_result__))
661 * Compares two strings.
663 * This function has a compatible signature for the use as a CxListComparator.
665 * @param s1 the first string
666 * @param s2 the second string
667 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
668 * than \p s2, zero if both strings equal
670 __attribute__((__warn_unused_result__, __nonnull__))
677 * Compares two strings ignoring case.
679 * This function has a compatible signature for the use as a CxListComparator.
681 * @param s1 the first string
682 * @param s2 the second string
683 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
684 * than \p s2, zero if both strings equal ignoring case
686 __attribute__((__warn_unused_result__, __nonnull__))
694 * Creates a duplicate of the specified string.
696 * The new string will contain a copy allocated by \p allocator.
698 * \note The returned string is guaranteed to be zero-terminated.
700 * @param allocator the allocator to use
701 * @param string the string to duplicate
702 * @return a duplicate of the string
705 __attribute__((__warn_unused_result__, __nonnull__))
706 cxmutstr cx_strdup_a(
707 CxAllocator *allocator,
712 * Creates a duplicate of the specified string.
714 * The new string will contain a copy allocated by standard
715 * \c malloc(). So developers \em must pass the return value to cx_strfree().
717 * \note The returned string is guaranteed to be zero-terminated.
719 * @param string the string to duplicate
720 * @return a duplicate of the string
723 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
726 * Omits leading and trailing spaces.
728 * \note the returned string references the same memory, thus you
729 * must \em not free the returned memory.
731 * @param string the string that shall be trimmed
732 * @return the trimmed string
734 __attribute__((__warn_unused_result__))
735 cxstring cx_strtrim(cxstring string);
738 * Omits leading and trailing spaces.
740 * \note the returned string references the same memory, thus you
741 * must \em not free the returned memory.
743 * @param string the string that shall be trimmed
744 * @return the trimmed string
746 __attribute__((__warn_unused_result__))
747 cxmutstr cx_strtrim_m(cxmutstr string);
750 * Checks, if a string has a specific prefix.
752 * @param string the string to check
753 * @param prefix the prefix the string should have
754 * @return \c true, if and only if the string has the specified prefix,
757 __attribute__((__warn_unused_result__))
764 * Checks, if a string has a specific suffix.
766 * @param string the string to check
767 * @param suffix the suffix the string should have
768 * @return \c true, if and only if the string has the specified suffix,
771 __attribute__((__warn_unused_result__))
778 * Checks, if a string has a specific prefix, ignoring the case.
780 * @param string the string to check
781 * @param prefix the prefix the string should have
782 * @return \c true, if and only if the string has the specified prefix,
785 __attribute__((__warn_unused_result__))
786 bool cx_strcaseprefix(
792 * Checks, if a string has a specific suffix, ignoring the case.
794 * @param string the string to check
795 * @param suffix the suffix the string should have
796 * @return \c true, if and only if the string has the specified suffix,
799 __attribute__((__warn_unused_result__))
800 bool cx_strcasesuffix(
806 * Converts the string to lower case.
808 * The change is made in-place. If you want a copy, use cx_strdup(), first.
810 * @param string the string to modify
813 void cx_strlower(cxmutstr string);
816 * Converts the string to upper case.
818 * The change is made in-place. If you want a copy, use cx_strdup(), first.
820 * @param string the string to modify
823 void cx_strupper(cxmutstr string);
826 * Replaces a pattern in a string with another string.
828 * The pattern is taken literally and is no regular expression.
829 * Replaces at most \p replmax occurrences.
831 * The returned string will be allocated by \p allocator and is guaranteed
832 * to be zero-terminated.
834 * If allocation fails, or the input string is empty,
835 * the returned string will be empty.
837 * @param allocator the allocator to use
838 * @param str the string where replacements should be applied
839 * @param pattern the pattern to search for
840 * @param replacement the replacement string
841 * @param replmax maximum number of replacements
842 * @return the resulting string after applying the replacements
844 __attribute__((__warn_unused_result__, __nonnull__))
845 cxmutstr cx_strreplacen_a(
846 CxAllocator *allocator,
849 cxstring replacement,
854 * Replaces a pattern in a string with another string.
856 * The pattern is taken literally and is no regular expression.
857 * Replaces at most \p replmax occurrences.
859 * The returned string will be allocated by \c malloc() and is guaranteed
860 * to be zero-terminated.
862 * If allocation fails, or the input string is empty,
863 * the returned string will be empty.
865 * @param str the string where replacements should be applied
866 * @param pattern the pattern to search for
867 * @param replacement the replacement string
868 * @param replmax maximum number of replacements
869 * @return the resulting string after applying the replacements
871 #define cx_strreplacen(str, pattern, replacement, replmax) \
872 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax)
875 * Replaces a pattern in a string with another string.
877 * The pattern is taken literally and is no regular expression.
879 * The returned string will be allocated by \p allocator and is guaranteed
880 * to be zero-terminated.
882 * If allocation fails, or the input string is empty,
883 * the returned string will be empty.
885 * @param allocator the allocator to use
886 * @param str the string where replacements should be applied
887 * @param pattern the pattern to search for
888 * @param replacement the replacement string
889 * @return the resulting string after applying the replacements
891 #define cx_strreplace_a(allocator, str, pattern, replacement) \
892 cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX)
895 * Replaces a pattern in a string with another string.
897 * The pattern is taken literally and is no regular expression.
898 * Replaces at most \p replmax occurrences.
900 * The returned string will be allocated by \c malloc() and is guaranteed
901 * to be zero-terminated.
903 * If allocation fails, or the input string is empty,
904 * the returned string will be empty.
906 * @param str the string where replacements should be applied
907 * @param pattern the pattern to search for
908 * @param replacement the replacement string
909 * @return the resulting string after applying the replacements
911 #define cx_strreplace(str, pattern, replacement) \
912 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX)
915 * Creates a string tokenization context.
917 * @param str the string to tokenize
918 * @param delim the delimiter (must not be empty)
919 * @param limit the maximum number of tokens that shall be returned
920 * @return a new string tokenization context
922 __attribute__((__warn_unused_result__))
923 CxStrtokCtx cx_strtok(
930 * Creates a string tokenization context for a mutable string.
932 * @param str the string to tokenize
933 * @param delim the delimiter (must not be empty)
934 * @param limit the maximum number of tokens that shall be returned
935 * @return a new string tokenization context
937 __attribute__((__warn_unused_result__))
938 CxStrtokCtx cx_strtok_m(
945 * Returns the next token.
947 * The token will point to the source string.
949 * @param ctx the tokenization context
950 * @param token a pointer to memory where the next token shall be stored
951 * @return true if successful, false if the limit or the end of the string
954 __attribute__((__warn_unused_result__, __nonnull__))
961 * Returns the next token of a mutable string.
963 * The token will point to the source string.
964 * If the context was not initialized over a mutable string, modifying
965 * the data of the returned token is undefined behavior.
967 * @param ctx the tokenization context
968 * @param token a pointer to memory where the next token shall be stored
969 * @return true if successful, false if the limit or the end of the string
972 __attribute__((__warn_unused_result__, __nonnull__))
973 bool cx_strtok_next_m(
979 * Defines an array of more delimiters for the specified tokenization context.
981 * @param ctx the tokenization context
982 * @param delim array of more delimiters
983 * @param count number of elements in the array
985 __attribute__((__nonnull__))
986 void cx_strtok_delim(
988 cxstring const *delim,
997 #endif //UCX_STRING_H