universe@576: /* universe@576: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@576: * universe@576: * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. universe@576: * universe@576: * Redistribution and use in source and binary forms, with or without universe@576: * modification, are permitted provided that the following conditions are met: universe@576: * universe@576: * 1. Redistributions of source code must retain the above copyright universe@576: * notice, this list of conditions and the following disclaimer. universe@576: * universe@576: * 2. Redistributions in binary form must reproduce the above copyright universe@576: * notice, this list of conditions and the following disclaimer in the universe@576: * documentation and/or other materials provided with the distribution. universe@576: * universe@576: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@576: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@576: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@576: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@576: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@576: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@576: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@576: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@576: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@576: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@576: * POSSIBILITY OF SUCH DAMAGE. universe@576: */ universe@576: /** universe@576: * \file string.h universe@576: * \brief Strings that know their length. universe@576: * \author Mike Becker universe@576: * \author Olaf Wintermann universe@576: * \copyright 2-Clause BSD License universe@576: */ universe@576: universe@576: #ifndef UCX_STRING_H universe@576: #define UCX_STRING_H universe@576: universe@576: #include "common.h" universe@576: #include "allocator.h" universe@576: universe@576: /** universe@806: * The maximum length of the "needle" in cx_strstr() that can use SBO. universe@806: */ universe@806: extern unsigned const cx_strstr_sbo_size; universe@806: universe@806: /** universe@576: * The UCX string structure. universe@576: */ universe@577: struct cx_mutstr_s { universe@576: /** universe@576: * A pointer to the string. universe@576: * \note The string is not necessarily \c NULL terminated. universe@576: * Always use the length. universe@576: */ universe@576: char *ptr; universe@576: /** The length of the string */ universe@576: size_t length; universe@577: }; universe@576: universe@576: /** universe@576: * A mutable string. universe@576: */ universe@576: typedef struct cx_mutstr_s cxmutstr; universe@576: universe@576: /** universe@576: * The UCX string structure for immutable (constant) strings. universe@576: */ universe@577: struct cx_string_s { universe@576: /** universe@576: * A pointer to the immutable string. universe@576: * \note The string is not necessarily \c NULL terminated. universe@576: * Always use the length. universe@576: */ universe@576: char const *ptr; universe@576: /** The length of the string */ universe@576: size_t length; universe@577: }; universe@576: universe@576: /** universe@576: * An immutable string. universe@576: */ universe@576: typedef struct cx_string_s cxstring; universe@576: universe@583: /** universe@645: * Context for string tokenizing. universe@645: */ universe@645: struct cx_strtok_ctx_s { universe@645: /** universe@645: * The string to tokenize. universe@645: */ universe@645: cxstring str; universe@645: /** universe@645: * The primary delimiter. universe@645: */ universe@645: cxstring delim; universe@645: /** universe@645: * Optional array of more delimiters. universe@645: */ universe@645: cxstring const *delim_more; universe@645: /** universe@645: * Length of the array containing more delimiters. universe@645: */ universe@645: size_t delim_more_count; universe@645: /** universe@645: * Position of the currently active token in the source string. universe@645: */ universe@645: size_t pos; universe@645: /** universe@645: * Position of next delimiter in the source string. universe@645: * universe@645: * If the tokenizer has not yet returned a token, the content of this field universe@645: * is undefined. If the tokenizer reached the end of the string, this field universe@645: * contains the length of the source string. universe@645: */ universe@645: size_t delim_pos; universe@645: /** universe@645: * The position of the next token in the source string. universe@645: */ universe@645: size_t next_pos; universe@645: /** universe@645: * The number of already found tokens. universe@645: */ universe@645: size_t found; universe@645: /** universe@645: * The maximum number of tokens that shall be returned. universe@645: */ universe@645: size_t limit; universe@645: }; universe@645: universe@645: /** universe@645: * A string tokenizing context. universe@645: */ universe@645: typedef struct cx_strtok_ctx_s CxStrtokCtx; universe@645: universe@684: #ifdef __cplusplus universe@684: extern "C" { universe@684: universe@684: /** universe@684: * A literal initializer for an UCX string structure. universe@684: * universe@684: * @param literal the string literal universe@684: */ universe@684: #define CX_STR(literal) cxstring{literal, sizeof(literal) - 1} universe@684: universe@684: #else // __cplusplus universe@684: universe@645: /** universe@583: * A literal initializer for an UCX string structure. universe@583: * universe@583: * The argument MUST be a string (const char*) \em literal. universe@583: * universe@583: * @param literal the string literal universe@583: */ universe@684: #define CX_STR(literal) (cxstring){literal, sizeof(literal) - 1} universe@583: universe@576: #endif universe@576: universe@576: universe@576: /** universe@576: * Wraps a mutable string that must be zero-terminated. universe@576: * universe@576: * The length is implicitly inferred by using a call to \c strlen(). universe@576: * universe@576: * \note the wrapped string will share the specified pointer to the string. universe@576: * If you do want a copy, use cx_strdup() on the return value of this function. universe@576: * universe@576: * If you need to wrap a constant string, use cx_str(). universe@576: * universe@584: * @param cstring the string to wrap, must be zero-terminated universe@576: * @return the wrapped string universe@576: * universe@576: * @see cx_mutstrn() universe@576: */ universe@584: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: cxmutstr cx_mutstr(char *cstring); universe@576: universe@576: /** universe@576: * Wraps a string that does not need to be zero-terminated. universe@576: * universe@576: * The argument may be \c NULL if the length is zero. universe@576: * universe@576: * \note the wrapped string will share the specified pointer to the string. universe@576: * If you do want a copy, use cx_strdup() on the return value of this function. universe@576: * universe@576: * If you need to wrap a constant string, use cx_strn(). universe@576: * universe@584: * @param cstring the string to wrap (or \c NULL, only if the length is zero) universe@576: * @param length the length of the string universe@576: * @return the wrapped string universe@576: * universe@576: * @see cx_mutstr() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_mutstrn( universe@576: char *cstring, universe@576: size_t length universe@576: ); universe@576: universe@576: /** universe@576: * Wraps a string that must be zero-terminated. universe@576: * universe@576: * The length is implicitly inferred by using a call to \c strlen(). universe@576: * universe@576: * \note the wrapped string will share the specified pointer to the string. universe@576: * If you do want a copy, use cx_strdup() on the return value of this function. universe@576: * universe@576: * If you need to wrap a non-constant string, use cx_mutstr(). universe@576: * universe@584: * @param cstring the string to wrap, must be zero-terminated universe@576: * @return the wrapped string universe@576: * universe@576: * @see cx_strn() universe@576: */ universe@584: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: cxstring cx_str(char const *cstring); universe@576: universe@576: universe@576: /** universe@576: * Wraps a string that does not need to be zero-terminated. universe@576: * universe@576: * The argument may be \c NULL if the length is zero. universe@576: * universe@576: * \note the wrapped string will share the specified pointer to the string. universe@576: * If you do want a copy, use cx_strdup() on the return value of this function. universe@576: * universe@576: * If you need to wrap a non-constant string, use cx_mutstrn(). universe@576: * universe@584: * @param cstring the string to wrap (or \c NULL, only if the length is zero) universe@576: * @param length the length of the string universe@576: * @return the wrapped string universe@576: * universe@576: * @see cx_str() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strn( universe@576: char const *cstring, universe@576: size_t length universe@576: ); universe@576: universe@576: /** universe@576: * Casts a mutable string to an immutable string. universe@576: * universe@576: * \note This is not seriously a cast. Instead you get a copy universe@576: * of the struct with the desired pointer type. Both structs still universe@576: * point to the same location, though! universe@576: * universe@576: * @param str the mutable string to cast universe@576: * @return an immutable copy of the string pointer universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strcast(cxmutstr str); universe@576: universe@576: /** universe@576: * Passes the pointer in this string to \c free(). universe@576: * universe@576: * The pointer in the struct is set to \c NULL and the length is set to zero. universe@576: * universe@576: * \note There is no implementation for cxstring, because it is unlikely that universe@576: * you ever have a \c char \c const* you are really supposed to free. If you universe@576: * encounter such situation, you should double-check your code. universe@576: * universe@576: * @param str the string to free universe@576: */ universe@583: __attribute__((__nonnull__)) universe@576: void cx_strfree(cxmutstr *str); universe@576: universe@576: /** universe@583: * Passes the pointer in this string to the allocators free function. universe@583: * universe@583: * The pointer in the struct is set to \c NULL and the length is set to zero. universe@583: * universe@583: * \note There is no implementation for cxstring, because it is unlikely that universe@583: * you ever have a \c char \c const* you are really supposed to free. If you universe@583: * encounter such situation, you should double-check your code. universe@583: * universe@583: * @param alloc the allocator universe@583: * @param str the string to free universe@583: */ universe@583: __attribute__((__nonnull__)) universe@583: void cx_strfree_a( universe@693: CxAllocator const *alloc, universe@583: cxmutstr *str universe@583: ); universe@583: universe@583: /** universe@576: * Returns the accumulated length of all specified strings. universe@576: * universe@576: * \attention if the count argument is larger than the number of the universe@576: * specified strings, the behavior is undefined. universe@576: * universe@576: * @param count the total number of specified strings universe@576: * @param ... all strings universe@576: * @return the accumulated length of all strings universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: size_t cx_strlen( universe@576: size_t count, universe@576: ... universe@576: ); universe@576: universe@576: /** universe@697: * Concatenates strings. universe@576: * universe@576: * The resulting string will be allocated by the specified allocator. universe@697: * So developers \em must pass the return value to cx_strfree_a() eventually. universe@697: * universe@697: * If \p str already contains a string, the memory will be reallocated and universe@697: * the other strings are appended. Otherwise, new memory is allocated. universe@697: * universe@697: * \note It is guaranteed that there is only one allocation. universe@697: * It is also guaranteed that the returned string is zero-terminated. universe@576: * universe@576: * @param alloc the allocator to use universe@697: * @param str the string the other strings shall be concatenated to universe@697: * @param count the number of the other following strings to concatenate universe@697: * @param ... all other strings universe@576: * @return the concatenated string universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@697: cxmutstr cx_strcat_ma( universe@693: CxAllocator const *alloc, universe@697: cxmutstr str, universe@576: size_t count, universe@576: ... universe@576: ); universe@576: universe@576: /** universe@697: * Concatenates strings and returns a new string. universe@697: * universe@697: * The resulting string will be allocated by the specified allocator. universe@697: * So developers \em must pass the return value to cx_strfree_a() eventually. universe@697: * universe@697: * \note It is guaranteed that there is only one allocation. universe@697: * It is also guaranteed that the returned string is zero-terminated. universe@697: * universe@697: * @param alloc the allocator to use universe@697: * @param count the number of the other following strings to concatenate universe@697: * @param ... all other strings universe@697: * @return the concatenated string universe@697: */ universe@697: #define cx_strcat_a(alloc, count, ...) \ universe@697: cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__) universe@697: universe@697: /** universe@697: * Concatenates strings and returns a new string. universe@576: * universe@576: * The resulting string will be allocated by standard \c malloc(). universe@576: * So developers \em must pass the return value to cx_strfree() eventually. universe@576: * universe@589: * \note It is guaranteed that there is only one allocation. universe@589: * It is also guaranteed that the returned string is zero-terminated. universe@589: * universe@697: * @param count the number of the other following strings to concatenate universe@697: * @param ... all other strings universe@576: * @return the concatenated string universe@576: */ universe@576: #define cx_strcat(count, ...) \ universe@697: cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__) universe@697: universe@697: /** universe@697: * Concatenates strings. universe@697: * universe@697: * The resulting string will be allocated by standard \c malloc(). universe@697: * So developers \em must pass the return value to cx_strfree() eventually. universe@697: * universe@697: * If \p str already contains a string, the memory will be reallocated and universe@697: * the other strings are appended. Otherwise, new memory is allocated. universe@697: * universe@697: * \note It is guaranteed that there is only one allocation. universe@697: * It is also guaranteed that the returned string is zero-terminated. universe@697: * universe@697: * @param str the string the other strings shall be concatenated to universe@697: * @param count the number of the other following strings to concatenate universe@697: * @param ... all other strings universe@697: * @return the concatenated string universe@697: */ universe@697: #define cx_strcat_m(str, count, ...) \ universe@697: cx_strcat_ma(cxDefaultAllocator, str, count, __VA_ARGS__) universe@576: universe@576: /** universe@576: * Returns a substring starting at the specified location. universe@576: * universe@576: * \attention the new string references the same memory area as the universe@576: * input string and is usually \em not zero-terminated. universe@576: * Use cx_strdup() to get a copy. universe@576: * universe@576: * @param string input string universe@576: * @param start start location of the substring universe@576: * @return a substring of \p string starting at \p start universe@576: * universe@576: * @see cx_strsubsl() universe@576: * @see cx_strsubs_m() universe@576: * @see cx_strsubsl_m() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strsubs( universe@576: cxstring string, universe@576: size_t start universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the specified location. universe@576: * universe@576: * The returned string will be limited to \p length bytes or the number universe@576: * of bytes available in \p string, whichever is smaller. universe@576: * universe@576: * \attention the new string references the same memory area as the universe@576: * input string and is usually \em not zero-terminated. universe@576: * Use cx_strdup() to get a copy. universe@576: * universe@576: * @param string input string universe@576: * @param start start location of the substring universe@576: * @param length the maximum length of the returned string universe@576: * @return a substring of \p string starting at \p start universe@576: * universe@576: * @see cx_strsubs() universe@576: * @see cx_strsubs_m() universe@576: * @see cx_strsubsl_m() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strsubsl( universe@576: cxstring string, universe@576: size_t start, universe@576: size_t length universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the specified location. universe@576: * universe@576: * \attention the new string references the same memory area as the universe@576: * input string and is usually \em not zero-terminated. universe@576: * Use cx_strdup() to get a copy. universe@576: * universe@576: * @param string input string universe@576: * @param start start location of the substring universe@576: * @return a substring of \p string starting at \p start universe@576: * universe@576: * @see cx_strsubsl_m() universe@576: * @see cx_strsubs() universe@576: * @see cx_strsubsl() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strsubs_m( universe@576: cxmutstr string, universe@576: size_t start universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the specified location. universe@576: * universe@576: * The returned string will be limited to \p length bytes or the number universe@576: * of bytes available in \p string, whichever is smaller. universe@576: * universe@576: * \attention the new string references the same memory area as the universe@576: * input string and is usually \em not zero-terminated. universe@576: * Use cx_strdup() to get a copy. universe@576: * universe@576: * @param string input string universe@576: * @param start start location of the substring universe@576: * @param length the maximum length of the returned string universe@576: * @return a substring of \p string starting at \p start universe@576: * universe@576: * @see cx_strsubs_m() universe@576: * @see cx_strsubs() universe@576: * @see cx_strsubsl() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strsubsl_m( universe@576: cxmutstr string, universe@576: size_t start, universe@576: size_t length universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the first occurrence of the universe@576: * specified character. universe@576: * universe@576: * If the string does not contain the character, an empty string is returned. universe@576: * universe@576: * @param string the string where to locate the character universe@576: * @param chr the character to locate universe@576: * @return a substring starting at the first location of \p chr universe@576: * universe@576: * @see cx_strchr_m() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strchr( universe@576: cxstring string, universe@576: int chr universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the first occurrence of the universe@576: * specified character. universe@576: * universe@576: * If the string does not contain the character, an empty string is returned. universe@576: * universe@576: * @param string the string where to locate the character universe@576: * @param chr the character to locate universe@576: * @return a substring starting at the first location of \p chr universe@576: * universe@576: * @see cx_strchr() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strchr_m( universe@576: cxmutstr string, universe@576: int chr universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the last occurrence of the universe@576: * specified character. universe@576: * universe@576: * If the string does not contain the character, an empty string is returned. universe@576: * universe@576: * @param string the string where to locate the character universe@576: * @param chr the character to locate universe@576: * @return a substring starting at the last location of \p chr universe@576: * universe@576: * @see cx_strrchr_m() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strrchr( universe@576: cxstring string, universe@576: int chr universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the last occurrence of the universe@576: * specified character. universe@576: * universe@576: * If the string does not contain the character, an empty string is returned. universe@576: * universe@576: * @param string the string where to locate the character universe@576: * @param chr the character to locate universe@576: * @return a substring starting at the last location of \p chr universe@576: * universe@576: * @see cx_strrchr() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strrchr_m( universe@576: cxmutstr string, universe@576: int chr universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the first occurrence of the universe@576: * specified string. universe@576: * universe@576: * If \p haystack does not contain \p needle, an empty string is returned. universe@576: * universe@576: * If \p needle is an empty string, the complete \p haystack is universe@576: * returned. universe@576: * universe@576: * @param haystack the string to be scanned universe@576: * @param needle string containing the sequence of characters to match universe@576: * @return a substring starting at the first occurrence of universe@576: * \p needle, or an empty string, if the sequence is not universe@576: * contained universe@576: * @see cx_strstr_m() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strstr( universe@576: cxstring haystack, universe@576: cxstring needle universe@576: ); universe@576: universe@576: /** universe@576: * Returns a substring starting at the location of the first occurrence of the universe@576: * specified string. universe@576: * universe@576: * If \p haystack does not contain \p needle, an empty string is returned. universe@576: * universe@576: * If \p needle is an empty string, the complete \p haystack is universe@576: * returned. universe@576: * universe@576: * @param haystack the string to be scanned universe@576: * @param needle string containing the sequence of characters to match universe@576: * @return a substring starting at the first occurrence of universe@576: * \p needle, or an empty string, if the sequence is not universe@576: * contained universe@576: * @see cx_strstr() universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strstr_m( universe@576: cxmutstr haystack, universe@576: cxstring needle universe@576: ); universe@576: universe@576: /** universe@576: * Splits a given string using a delimiter string. universe@576: * universe@576: * \note The resulting array contains strings that point to the source universe@576: * \p string. Use cx_strdup() to get copies. universe@576: * universe@576: * @param string the string to split universe@576: * @param delim the delimiter universe@576: * @param limit the maximum number of split items universe@576: * @param output a pre-allocated array of at least \p limit length universe@576: * @return the actual number of split items universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: size_t cx_strsplit( universe@576: cxstring string, universe@576: cxstring delim, universe@576: size_t limit, universe@576: cxstring *output universe@576: ); universe@576: universe@576: /** universe@576: * Splits a given string using a delimiter string. universe@576: * universe@576: * The array pointed to by \p output will be allocated by \p allocator. universe@576: * universe@576: * \note The resulting array contains strings that point to the source universe@576: * \p string. Use cx_strdup() to get copies. universe@576: * universe@576: * \attention If allocation fails, the \c NULL pointer will be written to universe@576: * \p output and the number returned will be zero. universe@576: * universe@576: * @param allocator the allocator to use for allocating the resulting array universe@576: * @param string the string to split universe@576: * @param delim the delimiter universe@576: * @param limit the maximum number of split items universe@576: * @param output a pointer where the address of the allocated array shall be universe@576: * written to universe@576: * @return the actual number of split items universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: size_t cx_strsplit_a( universe@693: CxAllocator const *allocator, universe@576: cxstring string, universe@576: cxstring delim, universe@576: size_t limit, universe@576: cxstring **output universe@576: ); universe@576: universe@576: universe@576: /** universe@576: * Splits a given string using a delimiter string. universe@576: * universe@576: * \note The resulting array contains strings that point to the source universe@576: * \p string. Use cx_strdup() to get copies. universe@576: * universe@576: * @param string the string to split universe@576: * @param delim the delimiter universe@576: * @param limit the maximum number of split items universe@576: * @param output a pre-allocated array of at least \p limit length universe@576: * @return the actual number of split items universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: size_t cx_strsplit_m( universe@576: cxmutstr string, universe@576: cxstring delim, universe@576: size_t limit, universe@576: cxmutstr *output universe@576: ); universe@576: universe@576: /** universe@576: * Splits a given string using a delimiter string. universe@576: * universe@576: * The array pointed to by \p output will be allocated by \p allocator. universe@576: * universe@576: * \note The resulting array contains strings that point to the source universe@576: * \p string. Use cx_strdup() to get copies. universe@576: * universe@576: * \attention If allocation fails, the \c NULL pointer will be written to universe@576: * \p output and the number returned will be zero. universe@576: * universe@576: * @param allocator the allocator to use for allocating the resulting array universe@576: * @param string the string to split universe@576: * @param delim the delimiter universe@576: * @param limit the maximum number of split items universe@576: * @param output a pointer where the address of the allocated array shall be universe@576: * written to universe@576: * @return the actual number of split items universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: size_t cx_strsplit_ma( universe@693: CxAllocator const *allocator, universe@576: cxmutstr string, universe@576: cxstring delim, universe@576: size_t limit, universe@576: cxmutstr **output universe@576: ); universe@576: universe@576: /** universe@576: * Compares two strings. universe@576: * universe@576: * @param s1 the first string universe@576: * @param s2 the second string universe@576: * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger universe@576: * than \p s2, zero if both strings equal universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: int cx_strcmp( universe@576: cxstring s1, universe@576: cxstring s2 universe@576: ); universe@576: universe@576: /** universe@576: * Compares two strings ignoring case. universe@576: * universe@576: * @param s1 the first string universe@576: * @param s2 the second string universe@576: * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger universe@576: * than \p s2, zero if both strings equal ignoring case universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: int cx_strcasecmp( universe@576: cxstring s1, universe@576: cxstring s2 universe@576: ); universe@576: universe@657: /** universe@657: * Compares two strings. universe@657: * universe@677: * This function has a compatible signature for the use as a cx_compare_func. universe@657: * universe@657: * @param s1 the first string universe@657: * @param s2 the second string universe@657: * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger universe@657: * than \p s2, zero if both strings equal universe@657: */ universe@657: __attribute__((__warn_unused_result__, __nonnull__)) universe@657: int cx_strcmp_p( universe@657: void const *s1, universe@657: void const *s2 universe@657: ); universe@657: universe@657: /** universe@657: * Compares two strings ignoring case. universe@657: * universe@677: * This function has a compatible signature for the use as a cx_compare_func. universe@657: * universe@657: * @param s1 the first string universe@657: * @param s2 the second string universe@657: * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger universe@657: * than \p s2, zero if both strings equal ignoring case universe@657: */ universe@657: __attribute__((__warn_unused_result__, __nonnull__)) universe@657: int cx_strcasecmp_p( universe@657: void const *s1, universe@657: void const *s2 universe@657: ); universe@657: universe@576: universe@576: /** universe@576: * Creates a duplicate of the specified string. universe@576: * universe@576: * The new string will contain a copy allocated by \p allocator. universe@576: * universe@589: * \note The returned string is guaranteed to be zero-terminated. universe@576: * universe@576: * @param allocator the allocator to use universe@576: * @param string the string to duplicate universe@576: * @return a duplicate of the string universe@576: * @see cx_strdup() universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@576: cxmutstr cx_strdup_a( universe@693: CxAllocator const *allocator, universe@576: cxstring string universe@576: ); universe@576: universe@576: /** universe@578: * Creates a duplicate of the specified string. universe@578: * universe@578: * The new string will contain a copy allocated by standard universe@578: * \c malloc(). So developers \em must pass the return value to cx_strfree(). universe@578: * universe@589: * \note The returned string is guaranteed to be zero-terminated. universe@578: * universe@578: * @param string the string to duplicate universe@578: * @return a duplicate of the string universe@578: * @see cx_strdup_a() universe@578: */ universe@578: #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string) universe@578: universe@700: universe@700: /** universe@700: * Creates a duplicate of the specified string. universe@700: * universe@700: * The new string will contain a copy allocated by \p allocator. universe@700: * universe@700: * \note The returned string is guaranteed to be zero-terminated. universe@700: * universe@700: * @param allocator the allocator to use universe@700: * @param string the string to duplicate universe@700: * @return a duplicate of the string universe@700: * @see cx_strdup_m() universe@700: */ universe@700: #define cx_strdup_ma(allocator, string) cx_strdup_a(allocator, cx_strcast(string)) universe@700: universe@700: /** universe@700: * Creates a duplicate of the specified string. universe@700: * universe@700: * The new string will contain a copy allocated by standard universe@700: * \c malloc(). So developers \em must pass the return value to cx_strfree(). universe@700: * universe@700: * \note The returned string is guaranteed to be zero-terminated. universe@700: * universe@700: * @param string the string to duplicate universe@700: * @return a duplicate of the string universe@700: * @see cx_strdup_ma() universe@700: */ universe@700: #define cx_strdup_m(string) cx_strdup_a(cxDefaultAllocator, cx_strcast(string)) universe@700: universe@578: /** universe@576: * Omits leading and trailing spaces. universe@576: * universe@576: * \note the returned string references the same memory, thus you universe@576: * must \em not free the returned memory. universe@576: * universe@576: * @param string the string that shall be trimmed universe@576: * @return the trimmed string universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxstring cx_strtrim(cxstring string); universe@576: universe@576: /** universe@576: * Omits leading and trailing spaces. universe@576: * universe@576: * \note the returned string references the same memory, thus you universe@576: * must \em not free the returned memory. universe@576: * universe@576: * @param string the string that shall be trimmed universe@576: * @return the trimmed string universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: cxmutstr cx_strtrim_m(cxmutstr string); universe@576: universe@576: /** universe@576: * Checks, if a string has a specific prefix. universe@576: * universe@576: * @param string the string to check universe@576: * @param prefix the prefix the string should have universe@576: * @return \c true, if and only if the string has the specified prefix, universe@576: * \c false otherwise universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@576: bool cx_strprefix( universe@576: cxstring string, universe@576: cxstring prefix universe@576: ); universe@576: universe@576: /** universe@576: * Checks, if a string has a specific suffix. universe@576: * universe@576: * @param string the string to check universe@576: * @param suffix the suffix the string should have universe@576: * @return \c true, if and only if the string has the specified suffix, universe@576: * \c false otherwise universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@581: bool cx_strsuffix( universe@576: cxstring string, universe@576: cxstring suffix universe@576: ); universe@576: universe@576: /** universe@576: * Checks, if a string has a specific prefix, ignoring the case. universe@576: * universe@576: * @param string the string to check universe@576: * @param prefix the prefix the string should have universe@576: * @return \c true, if and only if the string has the specified prefix, universe@576: * \c false otherwise universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@581: bool cx_strcaseprefix( universe@576: cxstring string, universe@576: cxstring prefix universe@576: ); universe@576: universe@576: /** universe@576: * Checks, if a string has a specific suffix, ignoring the case. universe@576: * universe@576: * @param string the string to check universe@576: * @param suffix the suffix the string should have universe@576: * @return \c true, if and only if the string has the specified suffix, universe@576: * \c false otherwise universe@576: */ universe@576: __attribute__((__warn_unused_result__)) universe@581: bool cx_strcasesuffix( universe@576: cxstring string, universe@576: cxstring suffix universe@576: ); universe@576: universe@576: /** universe@576: * Converts the string to lower case. universe@576: * universe@576: * The change is made in-place. If you want a copy, use cx_strdup(), first. universe@576: * universe@576: * @param string the string to modify universe@576: * @see cx_strdup() universe@576: */ universe@576: void cx_strlower(cxmutstr string); universe@576: universe@576: /** universe@576: * Converts the string to upper case. universe@576: * universe@576: * The change is made in-place. If you want a copy, use cx_strdup(), first. universe@576: * universe@576: * @param string the string to modify universe@576: * @see cx_strdup() universe@576: */ universe@576: void cx_strupper(cxmutstr string); universe@576: universe@576: /** universe@576: * Replaces a pattern in a string with another string. universe@576: * universe@576: * The pattern is taken literally and is no regular expression. universe@576: * Replaces at most \p replmax occurrences. universe@576: * universe@589: * The returned string will be allocated by \p allocator and is guaranteed universe@589: * to be zero-terminated. universe@576: * universe@576: * If allocation fails, or the input string is empty, universe@583: * the returned string will be empty. universe@576: * universe@576: * @param allocator the allocator to use universe@576: * @param str the string where replacements should be applied universe@576: * @param pattern the pattern to search for universe@576: * @param replacement the replacement string universe@576: * @param replmax maximum number of replacements universe@576: * @return the resulting string after applying the replacements universe@576: */ universe@576: __attribute__((__warn_unused_result__, __nonnull__)) universe@583: cxmutstr cx_strreplacen_a( universe@693: CxAllocator const *allocator, universe@576: cxstring str, universe@576: cxstring pattern, universe@576: cxstring replacement, universe@576: size_t replmax universe@576: ); universe@576: universe@578: /** universe@578: * Replaces a pattern in a string with another string. universe@578: * universe@578: * The pattern is taken literally and is no regular expression. universe@578: * Replaces at most \p replmax occurrences. universe@578: * universe@589: * The returned string will be allocated by \c malloc() and is guaranteed universe@589: * to be zero-terminated. universe@578: * universe@578: * If allocation fails, or the input string is empty, universe@583: * the returned string will be empty. universe@578: * universe@578: * @param str the string where replacements should be applied universe@578: * @param pattern the pattern to search for universe@578: * @param replacement the replacement string universe@578: * @param replmax maximum number of replacements universe@578: * @return the resulting string after applying the replacements universe@578: */ universe@583: #define cx_strreplacen(str, pattern, replacement, replmax) \ universe@583: cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax) universe@583: universe@583: /** universe@583: * Replaces a pattern in a string with another string. universe@583: * universe@583: * The pattern is taken literally and is no regular expression. universe@583: * universe@589: * The returned string will be allocated by \p allocator and is guaranteed universe@589: * to be zero-terminated. universe@583: * universe@583: * If allocation fails, or the input string is empty, universe@583: * the returned string will be empty. universe@583: * universe@583: * @param allocator the allocator to use universe@583: * @param str the string where replacements should be applied universe@583: * @param pattern the pattern to search for universe@583: * @param replacement the replacement string universe@583: * @return the resulting string after applying the replacements universe@583: */ universe@583: #define cx_strreplace_a(allocator, str, pattern, replacement) \ universe@583: cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX) universe@583: universe@583: /** universe@583: * Replaces a pattern in a string with another string. universe@583: * universe@583: * The pattern is taken literally and is no regular expression. universe@583: * Replaces at most \p replmax occurrences. universe@583: * universe@589: * The returned string will be allocated by \c malloc() and is guaranteed universe@589: * to be zero-terminated. universe@583: * universe@583: * If allocation fails, or the input string is empty, universe@583: * the returned string will be empty. universe@583: * universe@583: * @param str the string where replacements should be applied universe@583: * @param pattern the pattern to search for universe@583: * @param replacement the replacement string universe@583: * @return the resulting string after applying the replacements universe@583: */ universe@583: #define cx_strreplace(str, pattern, replacement) \ universe@583: cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX) universe@578: universe@645: /** universe@645: * Creates a string tokenization context. universe@645: * universe@645: * @param str the string to tokenize universe@645: * @param delim the delimiter (must not be empty) universe@645: * @param limit the maximum number of tokens that shall be returned universe@645: * @return a new string tokenization context universe@645: */ universe@645: __attribute__((__warn_unused_result__)) universe@645: CxStrtokCtx cx_strtok( universe@645: cxstring str, universe@645: cxstring delim, universe@645: size_t limit universe@645: ); universe@645: universe@645: /** universe@645: * Creates a string tokenization context for a mutable string. universe@645: * universe@645: * @param str the string to tokenize universe@645: * @param delim the delimiter (must not be empty) universe@645: * @param limit the maximum number of tokens that shall be returned universe@645: * @return a new string tokenization context universe@645: */ universe@645: __attribute__((__warn_unused_result__)) universe@645: CxStrtokCtx cx_strtok_m( universe@645: cxmutstr str, universe@645: cxstring delim, universe@645: size_t limit universe@645: ); universe@645: universe@645: /** universe@645: * Returns the next token. universe@645: * universe@645: * The token will point to the source string. universe@645: * universe@645: * @param ctx the tokenization context universe@645: * @param token a pointer to memory where the next token shall be stored universe@645: * @return true if successful, false if the limit or the end of the string universe@645: * has been reached universe@645: */ universe@645: __attribute__((__warn_unused_result__, __nonnull__)) universe@645: bool cx_strtok_next( universe@645: CxStrtokCtx *ctx, universe@645: cxstring *token universe@645: ); universe@645: universe@645: /** universe@645: * Returns the next token of a mutable string. universe@645: * universe@645: * The token will point to the source string. universe@645: * If the context was not initialized over a mutable string, modifying universe@645: * the data of the returned token is undefined behavior. universe@645: * universe@645: * @param ctx the tokenization context universe@645: * @param token a pointer to memory where the next token shall be stored universe@645: * @return true if successful, false if the limit or the end of the string universe@645: * has been reached universe@645: */ universe@645: __attribute__((__warn_unused_result__, __nonnull__)) universe@645: bool cx_strtok_next_m( universe@645: CxStrtokCtx *ctx, universe@645: cxmutstr *token universe@645: ); universe@645: universe@645: /** universe@645: * Defines an array of more delimiters for the specified tokenization context. universe@645: * universe@645: * @param ctx the tokenization context universe@645: * @param delim array of more delimiters universe@645: * @param count number of elements in the array universe@645: */ universe@645: __attribute__((__nonnull__)) universe@645: void cx_strtok_delim( universe@645: CxStrtokCtx *ctx, universe@645: cxstring const *delim, universe@645: size_t count universe@645: ); universe@645: universe@645: universe@576: #ifdef __cplusplus universe@576: } // extern "C" universe@576: #endif universe@576: universe@576: #endif //UCX_STRING_H