src/cx/string.h

Mon, 03 Apr 2023 19:09:31 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 03 Apr 2023 19:09:31 +0200
changeset 673
60fb6aec157d
parent 657
3eeadf666d6b
child 677
b09aae58bba4
permissions
-rw-r--r--

make allocator in cxBufferInit optional

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    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.
    15  *
    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.
    27  */
    28 /**
    29  * \file string.h
    30  * \brief Strings that know their length.
    31  * \author Mike Becker
    32  * \author Olaf Wintermann
    33  * \version 3.0
    34  * \copyright 2-Clause BSD License
    35  */
    37 #ifndef UCX_STRING_H
    38 #define UCX_STRING_H
    40 #include "common.h"
    41 #include "allocator.h"
    43 /**
    44  * The UCX string structure.
    45  */
    46 struct cx_mutstr_s {
    47     /**
    48      * A pointer to the string.
    49      * \note The string is not necessarily \c NULL terminated.
    50      * Always use the length.
    51      */
    52     char *ptr;
    53     /** The length of the string */
    54     size_t length;
    55 };
    57 /**
    58  * A mutable string.
    59  */
    60 typedef struct cx_mutstr_s cxmutstr;
    62 /**
    63  * The UCX string structure for immutable (constant) strings.
    64  */
    65 struct cx_string_s {
    66     /**
    67      * A pointer to the immutable string.
    68      * \note The string is not necessarily \c NULL terminated.
    69      * Always use the length.
    70      */
    71     char const *ptr;
    72     /** The length of the string */
    73     size_t length;
    74 };
    76 /**
    77  * An immutable string.
    78  */
    79 typedef struct cx_string_s cxstring;
    81 /**
    82  * Context for string tokenizing.
    83  */
    84 struct cx_strtok_ctx_s {
    85     /**
    86      * The string to tokenize.
    87      */
    88     cxstring str;
    89     /**
    90      * The primary delimiter.
    91      */
    92     cxstring delim;
    93     /**
    94      * Optional array of more delimiters.
    95      */
    96     cxstring const *delim_more;
    97     /**
    98      * Length of the array containing more delimiters.
    99      */
   100     size_t delim_more_count;
   101     /**
   102      * Position of the currently active token in the source string.
   103      */
   104     size_t pos;
   105     /**
   106      * Position of next delimiter in the source string.
   107      *
   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.
   111      */
   112     size_t delim_pos;
   113     /**
   114      * The position of the next token in the source string.
   115      */
   116     size_t next_pos;
   117     /**
   118      * The number of already found tokens.
   119      */
   120     size_t found;
   121     /**
   122      * The maximum number of tokens that shall be returned.
   123      */
   124     size_t limit;
   125 };
   127 /**
   128  * A string tokenizing context.
   129  */
   130 typedef struct cx_strtok_ctx_s CxStrtokCtx;
   132 /**
   133  * A literal initializer for an UCX string structure.
   134  *
   135  * The argument MUST be a string (const char*) \em literal.
   136  *
   137  * @param literal the string literal
   138  */
   139 #define CX_STR(literal) {literal, sizeof(literal) - 1}
   141 #ifdef __cplusplus
   142 extern "C" {
   143 #endif
   146 /**
   147  * Wraps a mutable string that must be zero-terminated.
   148  *
   149  * The length is implicitly inferred by using a call to \c strlen().
   150  *
   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.
   153  *
   154  * If you need to wrap a constant string, use cx_str().
   155  *
   156  * @param cstring the string to wrap, must be zero-terminated
   157  * @return the wrapped string
   158  *
   159  * @see cx_mutstrn()
   160  */
   161 __attribute__((__warn_unused_result__, __nonnull__))
   162 cxmutstr cx_mutstr(char *cstring);
   164 /**
   165  * Wraps a string that does not need to be zero-terminated.
   166  *
   167  * The argument may be \c NULL if the length is zero.
   168  *
   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.
   171  *
   172  * If you need to wrap a constant string, use cx_strn().
   173  *
   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
   177  *
   178  * @see cx_mutstr()
   179  */
   180 __attribute__((__warn_unused_result__))
   181 cxmutstr cx_mutstrn(
   182         char *cstring,
   183         size_t length
   184 );
   186 /**
   187  * Wraps a string that must be zero-terminated.
   188  *
   189  * The length is implicitly inferred by using a call to \c strlen().
   190  *
   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.
   193  *
   194  * If you need to wrap a non-constant string, use cx_mutstr().
   195  *
   196  * @param cstring the string to wrap, must be zero-terminated
   197  * @return the wrapped string
   198  *
   199  * @see cx_strn()
   200  */
   201 __attribute__((__warn_unused_result__, __nonnull__))
   202 cxstring cx_str(char const *cstring);
   205 /**
   206  * Wraps a string that does not need to be zero-terminated.
   207  *
   208  * The argument may be \c NULL if the length is zero.
   209  *
   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.
   212  *
   213  * If you need to wrap a non-constant string, use cx_mutstrn().
   214  *
   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
   218  *
   219  * @see cx_str()
   220  */
   221 __attribute__((__warn_unused_result__))
   222 cxstring cx_strn(
   223         char const *cstring,
   224         size_t length
   225 );
   227 /**
   228 * Casts a mutable string to an immutable string.
   229 *
   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!
   233 *
   234 * @param str the mutable string to cast
   235 * @return an immutable copy of the string pointer
   236 */
   237 __attribute__((__warn_unused_result__))
   238 cxstring cx_strcast(cxmutstr str);
   240 /**
   241  * Passes the pointer in this string to \c free().
   242  *
   243  * The pointer in the struct is set to \c NULL and the length is set to zero.
   244  *
   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.
   248  *
   249  * @param str the string to free
   250  */
   251 __attribute__((__nonnull__))
   252 void cx_strfree(cxmutstr *str);
   254 /**
   255  * Passes the pointer in this string to the allocators free function.
   256  *
   257  * The pointer in the struct is set to \c NULL and the length is set to zero.
   258  *
   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.
   262  *
   263  * @param alloc the allocator
   264  * @param str the string to free
   265  */
   266 __attribute__((__nonnull__))
   267 void cx_strfree_a(
   268         CxAllocator *alloc,
   269         cxmutstr *str
   270 );
   272 /**
   273  * Returns the accumulated length of all specified strings.
   274  *
   275  * \attention if the count argument is larger than the number of the
   276  * specified strings, the behavior is undefined.
   277  *
   278  * @param count    the total number of specified strings
   279  * @param ...      all strings
   280  * @return the accumulated length of all strings
   281  */
   282 __attribute__((__warn_unused_result__))
   283 size_t cx_strlen(
   284         size_t count,
   285         ...
   286 );
   288 /**
   289  * Concatenates two or more strings.
   290  *
   291  * The resulting string will be allocated by the specified allocator.
   292   * So developers \em must pass the return value to cx_strfree() eventually.
   293   *
   294   * \note It is guaranteed that there is only one allocation.
   295   * It is also guaranteed that the returned string is zero-terminated.
   296  *
   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
   301  */
   302 __attribute__((__warn_unused_result__, __nonnull__))
   303 cxmutstr cx_strcat_a(
   304         CxAllocator *alloc,
   305         size_t count,
   306         ...
   307 );
   309 /**
   310  * Concatenates two or more strings.
   311  *
   312  * The resulting string will be allocated by standard \c malloc().
   313  * So developers \em must pass the return value to cx_strfree() eventually.
   314  *
   315  * \note It is guaranteed that there is only one allocation.
   316  * It is also guaranteed that the returned string is zero-terminated.
   317  *
   318  * @param count   the total number of strings to concatenate
   319  * @param ...     all strings
   320  * @return the concatenated string
   321  */
   322 #define cx_strcat(count, ...) \
   323 cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__)
   325 /**
   326  * Returns a substring starting at the specified location.
   327  *
   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.
   331  *
   332  * @param string input string
   333  * @param start  start location of the substring
   334  * @return a substring of \p string starting at \p start
   335  *
   336  * @see cx_strsubsl()
   337  * @see cx_strsubs_m()
   338  * @see cx_strsubsl_m()
   339  */
   340 __attribute__((__warn_unused_result__))
   341 cxstring cx_strsubs(
   342         cxstring string,
   343         size_t start
   344 );
   346 /**
   347  * Returns a substring starting at the specified location.
   348  *
   349  * The returned string will be limited to \p length bytes or the number
   350  * of bytes available in \p string, whichever is smaller.
   351  *
   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.
   355  *
   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
   360  *
   361  * @see cx_strsubs()
   362  * @see cx_strsubs_m()
   363  * @see cx_strsubsl_m()
   364  */
   365 __attribute__((__warn_unused_result__))
   366 cxstring cx_strsubsl(
   367         cxstring string,
   368         size_t start,
   369         size_t length
   370 );
   372 /**
   373  * Returns a substring starting at the specified location.
   374  *
   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.
   378  *
   379  * @param string input string
   380  * @param start  start location of the substring
   381  * @return a substring of \p string starting at \p start
   382  *
   383  * @see cx_strsubsl_m()
   384  * @see cx_strsubs()
   385  * @see cx_strsubsl()
   386  */
   387 __attribute__((__warn_unused_result__))
   388 cxmutstr cx_strsubs_m(
   389         cxmutstr string,
   390         size_t start
   391 );
   393 /**
   394  * Returns a substring starting at the specified location.
   395  *
   396  * The returned string will be limited to \p length bytes or the number
   397  * of bytes available in \p string, whichever is smaller.
   398  *
   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.
   402  *
   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
   407  *
   408  * @see cx_strsubs_m()
   409  * @see cx_strsubs()
   410  * @see cx_strsubsl()
   411  */
   412 __attribute__((__warn_unused_result__))
   413 cxmutstr cx_strsubsl_m(
   414         cxmutstr string,
   415         size_t start,
   416         size_t length
   417 );
   419 /**
   420  * Returns a substring starting at the location of the first occurrence of the
   421  * specified character.
   422  *
   423  * If the string does not contain the character, an empty string is returned.
   424  *
   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
   428  *
   429  * @see cx_strchr_m()
   430  */
   431 __attribute__((__warn_unused_result__))
   432 cxstring cx_strchr(
   433         cxstring string,
   434         int chr
   435 );
   437 /**
   438  * Returns a substring starting at the location of the first occurrence of the
   439  * specified character.
   440  *
   441  * If the string does not contain the character, an empty string is returned.
   442  *
   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
   446  *
   447  * @see cx_strchr()
   448  */
   449 __attribute__((__warn_unused_result__))
   450 cxmutstr cx_strchr_m(
   451         cxmutstr string,
   452         int chr
   453 );
   455 /**
   456  * Returns a substring starting at the location of the last occurrence of the
   457  * specified character.
   458  *
   459  * If the string does not contain the character, an empty string is returned.
   460  *
   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
   464  *
   465  * @see cx_strrchr_m()
   466  */
   467 __attribute__((__warn_unused_result__))
   468 cxstring cx_strrchr(
   469         cxstring string,
   470         int chr
   471 );
   473 /**
   474  * Returns a substring starting at the location of the last occurrence of the
   475  * specified character.
   476  *
   477  * If the string does not contain the character, an empty string is returned.
   478  *
   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
   482  *
   483  * @see cx_strrchr()
   484  */
   485 __attribute__((__warn_unused_result__))
   486 cxmutstr cx_strrchr_m(
   487         cxmutstr string,
   488         int chr
   489 );
   491 /**
   492  * Returns a substring starting at the location of the first occurrence of the
   493  * specified string.
   494  *
   495  * If \p haystack does not contain \p needle, an empty string is returned.
   496  *
   497  * If \p needle is an empty string, the complete \p haystack is
   498  * returned.
   499  *
   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
   504  *               contained
   505  * @see cx_strstr_m()
   506  */
   507 __attribute__((__warn_unused_result__))
   508 cxstring cx_strstr(
   509         cxstring haystack,
   510         cxstring needle
   511 );
   513 /**
   514  * Returns a substring starting at the location of the first occurrence of the
   515  * specified string.
   516  *
   517  * If \p haystack does not contain \p needle, an empty string is returned.
   518  *
   519  * If \p needle is an empty string, the complete \p haystack is
   520  * returned.
   521  *
   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
   526  *               contained
   527  * @see cx_strstr()
   528  */
   529 __attribute__((__warn_unused_result__))
   530 cxmutstr cx_strstr_m(
   531         cxmutstr haystack,
   532         cxstring needle
   533 );
   535 /**
   536  * Splits a given string using a delimiter string.
   537  *
   538  * \note The resulting array contains strings that point to the source
   539  * \p string. Use cx_strdup() to get copies.
   540  *
   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
   546  */
   547 __attribute__((__warn_unused_result__, __nonnull__))
   548 size_t cx_strsplit(
   549         cxstring string,
   550         cxstring delim,
   551         size_t limit,
   552         cxstring *output
   553 );
   555 /**
   556  * Splits a given string using a delimiter string.
   557  *
   558  * The array pointed to by \p output will be allocated by \p allocator.
   559  *
   560  * \note The resulting array contains strings that point to the source
   561  * \p string. Use cx_strdup() to get copies.
   562  *
   563  * \attention If allocation fails, the \c NULL pointer will be written to
   564  * \p output and the number returned will be zero.
   565  *
   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
   571  * written to
   572  * @return the actual number of split items
   573  */
   574 __attribute__((__warn_unused_result__, __nonnull__))
   575 size_t cx_strsplit_a(
   576         CxAllocator *allocator,
   577         cxstring string,
   578         cxstring delim,
   579         size_t limit,
   580         cxstring **output
   581 );
   584 /**
   585  * Splits a given string using a delimiter string.
   586  *
   587  * \note The resulting array contains strings that point to the source
   588  * \p string. Use cx_strdup() to get copies.
   589  *
   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
   595  */
   596 __attribute__((__warn_unused_result__, __nonnull__))
   597 size_t cx_strsplit_m(
   598         cxmutstr string,
   599         cxstring delim,
   600         size_t limit,
   601         cxmutstr *output
   602 );
   604 /**
   605  * Splits a given string using a delimiter string.
   606  *
   607  * The array pointed to by \p output will be allocated by \p allocator.
   608  *
   609  * \note The resulting array contains strings that point to the source
   610  * \p string. Use cx_strdup() to get copies.
   611  *
   612  * \attention If allocation fails, the \c NULL pointer will be written to
   613  * \p output and the number returned will be zero.
   614  *
   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
   620  * written to
   621  * @return the actual number of split items
   622  */
   623 __attribute__((__warn_unused_result__, __nonnull__))
   624 size_t cx_strsplit_ma(
   625         CxAllocator *allocator,
   626         cxmutstr string,
   627         cxstring delim,
   628         size_t limit,
   629         cxmutstr **output
   630 );
   632 /**
   633  * Compares two strings.
   634  *
   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
   639  */
   640 __attribute__((__warn_unused_result__))
   641 int cx_strcmp(
   642         cxstring s1,
   643         cxstring s2
   644 );
   646 /**
   647  * Compares two strings ignoring case.
   648  *
   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
   653  */
   654 __attribute__((__warn_unused_result__))
   655 int cx_strcasecmp(
   656         cxstring s1,
   657         cxstring s2
   658 );
   660 /**
   661  * Compares two strings.
   662  *
   663  * This function has a compatible signature for the use as a CxListComparator.
   664  *
   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
   669  */
   670 __attribute__((__warn_unused_result__, __nonnull__))
   671 int cx_strcmp_p(
   672         void const *s1,
   673         void const *s2
   674 );
   676 /**
   677  * Compares two strings ignoring case.
   678  *
   679  * This function has a compatible signature for the use as a CxListComparator.
   680  *
   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
   685  */
   686 __attribute__((__warn_unused_result__, __nonnull__))
   687 int cx_strcasecmp_p(
   688         void const *s1,
   689         void const *s2
   690 );
   693 /**
   694  * Creates a duplicate of the specified string.
   695  *
   696  * The new string will contain a copy allocated by \p allocator.
   697  *
   698  * \note The returned string is guaranteed to be zero-terminated.
   699  *
   700  * @param allocator the allocator to use
   701  * @param string the string to duplicate
   702  * @return a duplicate of the string
   703  * @see cx_strdup()
   704  */
   705 __attribute__((__warn_unused_result__, __nonnull__))
   706 cxmutstr cx_strdup_a(
   707         CxAllocator *allocator,
   708         cxstring string
   709 );
   711 /**
   712  * Creates a duplicate of the specified string.
   713  *
   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().
   716  *
   717  * \note The returned string is guaranteed to be zero-terminated.
   718  *
   719  * @param string the string to duplicate
   720  * @return a duplicate of the string
   721  * @see cx_strdup_a()
   722  */
   723 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
   725 /**
   726  * Omits leading and trailing spaces.
   727  *
   728  * \note the returned string references the same memory, thus you
   729  * must \em not free the returned memory.
   730  *
   731  * @param string the string that shall be trimmed
   732  * @return the trimmed string
   733  */
   734 __attribute__((__warn_unused_result__))
   735 cxstring cx_strtrim(cxstring string);
   737 /**
   738  * Omits leading and trailing spaces.
   739  *
   740  * \note the returned string references the same memory, thus you
   741  * must \em not free the returned memory.
   742  *
   743  * @param string the string that shall be trimmed
   744  * @return the trimmed string
   745  */
   746 __attribute__((__warn_unused_result__))
   747 cxmutstr cx_strtrim_m(cxmutstr string);
   749 /**
   750  * Checks, if a string has a specific prefix.
   751  *
   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,
   755  * \c false otherwise
   756  */
   757 __attribute__((__warn_unused_result__))
   758 bool cx_strprefix(
   759         cxstring string,
   760         cxstring prefix
   761 );
   763 /**
   764  * Checks, if a string has a specific suffix.
   765  *
   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,
   769  * \c false otherwise
   770  */
   771 __attribute__((__warn_unused_result__))
   772 bool cx_strsuffix(
   773         cxstring string,
   774         cxstring suffix
   775 );
   777 /**
   778  * Checks, if a string has a specific prefix, ignoring the case.
   779  *
   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,
   783  * \c false otherwise
   784  */
   785 __attribute__((__warn_unused_result__))
   786 bool cx_strcaseprefix(
   787         cxstring string,
   788         cxstring prefix
   789 );
   791 /**
   792  * Checks, if a string has a specific suffix, ignoring the case.
   793  *
   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,
   797  * \c false otherwise
   798  */
   799 __attribute__((__warn_unused_result__))
   800 bool cx_strcasesuffix(
   801         cxstring string,
   802         cxstring suffix
   803 );
   805 /**
   806  * Converts the string to lower case.
   807  *
   808  * The change is made in-place. If you want a copy, use cx_strdup(), first.
   809  *
   810  * @param string the string to modify
   811  * @see cx_strdup()
   812  */
   813 void cx_strlower(cxmutstr string);
   815 /**
   816  * Converts the string to upper case.
   817  *
   818  * The change is made in-place. If you want a copy, use cx_strdup(), first.
   819  *
   820  * @param string the string to modify
   821  * @see cx_strdup()
   822  */
   823 void cx_strupper(cxmutstr string);
   825 /**
   826  * Replaces a pattern in a string with another string.
   827  *
   828  * The pattern is taken literally and is no regular expression.
   829  * Replaces at most \p replmax occurrences.
   830  *
   831  * The returned string will be allocated by \p allocator and is guaranteed
   832  * to be zero-terminated.
   833  *
   834  * If allocation fails, or the input string is empty,
   835  * the returned string will be empty.
   836  *
   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
   843  */
   844 __attribute__((__warn_unused_result__, __nonnull__))
   845 cxmutstr cx_strreplacen_a(
   846         CxAllocator *allocator,
   847         cxstring str,
   848         cxstring pattern,
   849         cxstring replacement,
   850         size_t replmax
   851 );
   853 /**
   854  * Replaces a pattern in a string with another string.
   855  *
   856  * The pattern is taken literally and is no regular expression.
   857  * Replaces at most \p replmax occurrences.
   858  *
   859  * The returned string will be allocated by \c malloc() and is guaranteed
   860  * to be zero-terminated.
   861  *
   862  * If allocation fails, or the input string is empty,
   863  * the returned string will be empty.
   864  *
   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
   870  */
   871 #define cx_strreplacen(str, pattern, replacement, replmax) \
   872 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax)
   874 /**
   875  * Replaces a pattern in a string with another string.
   876  *
   877  * The pattern is taken literally and is no regular expression.
   878  *
   879  * The returned string will be allocated by \p allocator and is guaranteed
   880  * to be zero-terminated.
   881  *
   882  * If allocation fails, or the input string is empty,
   883  * the returned string will be empty.
   884  *
   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
   890  */
   891 #define cx_strreplace_a(allocator, str, pattern, replacement) \
   892 cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX)
   894 /**
   895  * Replaces a pattern in a string with another string.
   896  *
   897  * The pattern is taken literally and is no regular expression.
   898  * Replaces at most \p replmax occurrences.
   899  *
   900  * The returned string will be allocated by \c malloc() and is guaranteed
   901  * to be zero-terminated.
   902  *
   903  * If allocation fails, or the input string is empty,
   904  * the returned string will be empty.
   905  *
   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
   910  */
   911 #define cx_strreplace(str, pattern, replacement) \
   912 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX)
   914 /**
   915  * Creates a string tokenization context.
   916  *
   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
   921  */
   922 __attribute__((__warn_unused_result__))
   923 CxStrtokCtx cx_strtok(
   924         cxstring str,
   925         cxstring delim,
   926         size_t limit
   927 );
   929 /**
   930 * Creates a string tokenization context for a mutable string.
   931 *
   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
   936 */
   937 __attribute__((__warn_unused_result__))
   938 CxStrtokCtx cx_strtok_m(
   939         cxmutstr str,
   940         cxstring delim,
   941         size_t limit
   942 );
   944 /**
   945  * Returns the next token.
   946  *
   947  * The token will point to the source string.
   948  *
   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
   952  * has been reached
   953  */
   954 __attribute__((__warn_unused_result__, __nonnull__))
   955 bool cx_strtok_next(
   956         CxStrtokCtx *ctx,
   957         cxstring *token
   958 );
   960 /**
   961  * Returns the next token of a mutable string.
   962  *
   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.
   966  *
   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
   970  * has been reached
   971  */
   972 __attribute__((__warn_unused_result__, __nonnull__))
   973 bool cx_strtok_next_m(
   974         CxStrtokCtx *ctx,
   975         cxmutstr *token
   976 );
   978 /**
   979  * Defines an array of more delimiters for the specified tokenization context.
   980  *
   981  * @param ctx the tokenization context
   982  * @param delim array of more delimiters
   983  * @param count number of elements in the array
   984  */
   985 __attribute__((__nonnull__))
   986 void cx_strtok_delim(
   987         CxStrtokCtx *ctx,
   988         cxstring const *delim,
   989         size_t count
   990 );
   993 #ifdef __cplusplus
   994 } // extern "C"
   995 #endif
   997 #endif //UCX_STRING_H

mercurial