src/cx/string.h

Tue, 04 Oct 2022 18:49:14 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 04 Oct 2022 18:49:14 +0200
changeset 589
c290f8fd979e
parent 584
184e9ebfc3cc
child 645
ec50abb285ad
permissions
-rw-r--r--

add zero-termination guarantees

     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  * A literal initializer for an UCX string structure.
    83  *
    84  * The argument MUST be a string (const char*) \em literal.
    85  *
    86  * @param literal the string literal
    87  */
    88 #define CX_STR(literal) {literal, sizeof(literal) - 1}
    90 #ifdef __cplusplus
    91 extern "C" {
    92 #endif
    95 /**
    96  * Wraps a mutable string that must be zero-terminated.
    97  *
    98  * The length is implicitly inferred by using a call to \c strlen().
    99  *
   100  * \note the wrapped string will share the specified pointer to the string.
   101  * If you do want a copy, use cx_strdup() on the return value of this function.
   102  *
   103  * If you need to wrap a constant string, use cx_str().
   104  *
   105  * @param cstring the string to wrap, must be zero-terminated
   106  * @return the wrapped string
   107  *
   108  * @see cx_mutstrn()
   109  */
   110 __attribute__((__warn_unused_result__, __nonnull__))
   111 cxmutstr cx_mutstr(char *cstring);
   113 /**
   114  * Wraps a string that does not need to be zero-terminated.
   115  *
   116  * The argument may be \c NULL if the length is zero.
   117  *
   118  * \note the wrapped string will share the specified pointer to the string.
   119  * If you do want a copy, use cx_strdup() on the return value of this function.
   120  *
   121  * If you need to wrap a constant string, use cx_strn().
   122  *
   123  * @param cstring  the string to wrap (or \c NULL, only if the length is zero)
   124  * @param length   the length of the string
   125  * @return the wrapped string
   126  *
   127  * @see cx_mutstr()
   128  */
   129 __attribute__((__warn_unused_result__))
   130 cxmutstr cx_mutstrn(
   131         char *cstring,
   132         size_t length
   133 );
   135 /**
   136  * Wraps a string that must be zero-terminated.
   137  *
   138  * The length is implicitly inferred by using a call to \c strlen().
   139  *
   140  * \note the wrapped string will share the specified pointer to the string.
   141  * If you do want a copy, use cx_strdup() on the return value of this function.
   142  *
   143  * If you need to wrap a non-constant string, use cx_mutstr().
   144  *
   145  * @param cstring the string to wrap, must be zero-terminated
   146  * @return the wrapped string
   147  *
   148  * @see cx_strn()
   149  */
   150 __attribute__((__warn_unused_result__, __nonnull__))
   151 cxstring cx_str(char const *cstring);
   154 /**
   155  * Wraps a string that does not need to be zero-terminated.
   156  *
   157  * The argument may be \c NULL if the length is zero.
   158  *
   159  * \note the wrapped string will share the specified pointer to the string.
   160  * If you do want a copy, use cx_strdup() on the return value of this function.
   161  *
   162  * If you need to wrap a non-constant string, use cx_mutstrn().
   163  *
   164  * @param cstring  the string to wrap (or \c NULL, only if the length is zero)
   165  * @param length   the length of the string
   166  * @return the wrapped string
   167  *
   168  * @see cx_str()
   169  */
   170 __attribute__((__warn_unused_result__))
   171 cxstring cx_strn(
   172         char const *cstring,
   173         size_t length
   174 );
   176 /**
   177 * Casts a mutable string to an immutable string.
   178 *
   179 * \note This is not seriously a cast. Instead you get a copy
   180 * of the struct with the desired pointer type. Both structs still
   181 * point to the same location, though!
   182 *
   183 * @param str the mutable string to cast
   184 * @return an immutable copy of the string pointer
   185 */
   186 __attribute__((__warn_unused_result__))
   187 cxstring cx_strcast(cxmutstr str);
   189 /**
   190  * Passes the pointer in this string to \c free().
   191  *
   192  * The pointer in the struct is set to \c NULL and the length is set to zero.
   193  *
   194  * \note There is no implementation for cxstring, because it is unlikely that
   195  * you ever have a \c char \c const* you are really supposed to free. If you
   196  * encounter such situation, you should double-check your code.
   197  *
   198  * @param str the string to free
   199  */
   200 __attribute__((__nonnull__))
   201 void cx_strfree(cxmutstr *str);
   203 /**
   204  * Passes the pointer in this string to the allocators free function.
   205  *
   206  * The pointer in the struct is set to \c NULL and the length is set to zero.
   207  *
   208  * \note There is no implementation for cxstring, because it is unlikely that
   209  * you ever have a \c char \c const* you are really supposed to free. If you
   210  * encounter such situation, you should double-check your code.
   211  *
   212  * @param alloc the allocator
   213  * @param str the string to free
   214  */
   215 __attribute__((__nonnull__))
   216 void cx_strfree_a(
   217         CxAllocator *alloc,
   218         cxmutstr *str
   219 );
   221 /**
   222  * Returns the accumulated length of all specified strings.
   223  *
   224  * \attention if the count argument is larger than the number of the
   225  * specified strings, the behavior is undefined.
   226  *
   227  * @param count    the total number of specified strings
   228  * @param ...      all strings
   229  * @return the accumulated length of all strings
   230  */
   231 __attribute__((__warn_unused_result__))
   232 size_t cx_strlen(
   233         size_t count,
   234         ...
   235 );
   237 /**
   238  * Concatenates two or more strings.
   239  *
   240  * The resulting string will be allocated by the specified allocator.
   241   * So developers \em must pass the return value to cx_strfree() eventually.
   242   *
   243   * \note It is guaranteed that there is only one allocation.
   244   * It is also guaranteed that the returned string is zero-terminated.
   245  *
   246  * @param alloc the allocator to use
   247  * @param count   the total number of strings to concatenate
   248  * @param ...     all strings
   249  * @return the concatenated string
   250  */
   251 __attribute__((__warn_unused_result__, __nonnull__))
   252 cxmutstr cx_strcat_a(
   253         CxAllocator *alloc,
   254         size_t count,
   255         ...
   256 );
   258 /**
   259  * Concatenates two or more strings.
   260  *
   261  * The resulting string will be allocated by standard \c malloc().
   262  * So developers \em must pass the return value to cx_strfree() eventually.
   263  *
   264  * \note It is guaranteed that there is only one allocation.
   265  * It is also guaranteed that the returned string is zero-terminated.
   266  *
   267  * @param count   the total number of strings to concatenate
   268  * @param ...     all strings
   269  * @return the concatenated string
   270  */
   271 #define cx_strcat(count, ...) \
   272 cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__)
   274 /**
   275  * Returns a substring starting at the specified location.
   276  *
   277  * \attention the new string references the same memory area as the
   278  * input string and is usually \em not zero-terminated.
   279  * Use cx_strdup() to get a copy.
   280  *
   281  * @param string input string
   282  * @param start  start location of the substring
   283  * @return a substring of \p string starting at \p start
   284  *
   285  * @see cx_strsubsl()
   286  * @see cx_strsubs_m()
   287  * @see cx_strsubsl_m()
   288  */
   289 __attribute__((__warn_unused_result__))
   290 cxstring cx_strsubs(
   291         cxstring string,
   292         size_t start
   293 );
   295 /**
   296  * Returns a substring starting at the specified location.
   297  *
   298  * The returned string will be limited to \p length bytes or the number
   299  * of bytes available in \p string, whichever is smaller.
   300  *
   301  * \attention the new string references the same memory area as the
   302  * input string and is usually \em not zero-terminated.
   303  * Use cx_strdup() to get a copy.
   304  *
   305  * @param string input string
   306  * @param start  start location of the substring
   307  * @param length the maximum length of the returned string
   308  * @return a substring of \p string starting at \p start
   309  *
   310  * @see cx_strsubs()
   311  * @see cx_strsubs_m()
   312  * @see cx_strsubsl_m()
   313  */
   314 __attribute__((__warn_unused_result__))
   315 cxstring cx_strsubsl(
   316         cxstring string,
   317         size_t start,
   318         size_t length
   319 );
   321 /**
   322  * Returns a substring starting at the specified location.
   323  *
   324  * \attention the new string references the same memory area as the
   325  * input string and is usually \em not zero-terminated.
   326  * Use cx_strdup() to get a copy.
   327  *
   328  * @param string input string
   329  * @param start  start location of the substring
   330  * @return a substring of \p string starting at \p start
   331  *
   332  * @see cx_strsubsl_m()
   333  * @see cx_strsubs()
   334  * @see cx_strsubsl()
   335  */
   336 __attribute__((__warn_unused_result__))
   337 cxmutstr cx_strsubs_m(
   338         cxmutstr string,
   339         size_t start
   340 );
   342 /**
   343  * Returns a substring starting at the specified location.
   344  *
   345  * The returned string will be limited to \p length bytes or the number
   346  * of bytes available in \p string, whichever is smaller.
   347  *
   348  * \attention the new string references the same memory area as the
   349  * input string and is usually \em not zero-terminated.
   350  * Use cx_strdup() to get a copy.
   351  *
   352  * @param string input string
   353  * @param start  start location of the substring
   354  * @param length the maximum length of the returned string
   355  * @return a substring of \p string starting at \p start
   356  *
   357  * @see cx_strsubs_m()
   358  * @see cx_strsubs()
   359  * @see cx_strsubsl()
   360  */
   361 __attribute__((__warn_unused_result__))
   362 cxmutstr cx_strsubsl_m(
   363         cxmutstr string,
   364         size_t start,
   365         size_t length
   366 );
   368 /**
   369  * Returns a substring starting at the location of the first occurrence of the
   370  * specified character.
   371  *
   372  * If the string does not contain the character, an empty string is returned.
   373  *
   374  * @param string the string where to locate the character
   375  * @param chr    the character to locate
   376  * @return       a substring starting at the first location of \p chr
   377  *
   378  * @see cx_strchr_m()
   379  */
   380 __attribute__((__warn_unused_result__))
   381 cxstring cx_strchr(
   382         cxstring string,
   383         int chr
   384 );
   386 /**
   387  * Returns a substring starting at the location of the first occurrence of the
   388  * specified character.
   389  *
   390  * If the string does not contain the character, an empty string is returned.
   391  *
   392  * @param string the string where to locate the character
   393  * @param chr    the character to locate
   394  * @return       a substring starting at the first location of \p chr
   395  *
   396  * @see cx_strchr()
   397  */
   398 __attribute__((__warn_unused_result__))
   399 cxmutstr cx_strchr_m(
   400         cxmutstr string,
   401         int chr
   402 );
   404 /**
   405  * Returns a substring starting at the location of the last occurrence of the
   406  * specified character.
   407  *
   408  * If the string does not contain the character, an empty string is returned.
   409  *
   410  * @param string the string where to locate the character
   411  * @param chr    the character to locate
   412  * @return       a substring starting at the last location of \p chr
   413  *
   414  * @see cx_strrchr_m()
   415  */
   416 __attribute__((__warn_unused_result__))
   417 cxstring cx_strrchr(
   418         cxstring string,
   419         int chr
   420 );
   422 /**
   423  * Returns a substring starting at the location of the last occurrence of the
   424  * specified character.
   425  *
   426  * If the string does not contain the character, an empty string is returned.
   427  *
   428  * @param string the string where to locate the character
   429  * @param chr    the character to locate
   430  * @return       a substring starting at the last location of \p chr
   431  *
   432  * @see cx_strrchr()
   433  */
   434 __attribute__((__warn_unused_result__))
   435 cxmutstr cx_strrchr_m(
   436         cxmutstr string,
   437         int chr
   438 );
   440 /**
   441  * Returns a substring starting at the location of the first occurrence of the
   442  * specified string.
   443  *
   444  * If \p haystack does not contain \p needle, an empty string is returned.
   445  *
   446  * If \p needle is an empty string, the complete \p haystack is
   447  * returned.
   448  *
   449  * @param haystack the string to be scanned
   450  * @param needle  string containing the sequence of characters to match
   451  * @return       a substring starting at the first occurrence of
   452  *               \p needle, or an empty string, if the sequence is not
   453  *               contained
   454  * @see cx_strstr_m()
   455  */
   456 __attribute__((__warn_unused_result__))
   457 cxstring cx_strstr(
   458         cxstring haystack,
   459         cxstring needle
   460 );
   462 /**
   463  * Returns a substring starting at the location of the first occurrence of the
   464  * specified string.
   465  *
   466  * If \p haystack does not contain \p needle, an empty string is returned.
   467  *
   468  * If \p needle is an empty string, the complete \p haystack is
   469  * returned.
   470  *
   471  * @param haystack the string to be scanned
   472  * @param needle  string containing the sequence of characters to match
   473  * @return       a substring starting at the first occurrence of
   474  *               \p needle, or an empty string, if the sequence is not
   475  *               contained
   476  * @see cx_strstr()
   477  */
   478 __attribute__((__warn_unused_result__))
   479 cxmutstr cx_strstr_m(
   480         cxmutstr haystack,
   481         cxstring needle
   482 );
   484 /**
   485  * Splits a given string using a delimiter string.
   486  *
   487  * \note The resulting array contains strings that point to the source
   488  * \p string. Use cx_strdup() to get copies.
   489  *
   490  * @param string the string to split
   491  * @param delim  the delimiter
   492  * @param limit the maximum number of split items
   493  * @param output a pre-allocated array of at least \p limit length
   494  * @return the actual number of split items
   495  */
   496 __attribute__((__warn_unused_result__, __nonnull__))
   497 size_t cx_strsplit(
   498         cxstring string,
   499         cxstring delim,
   500         size_t limit,
   501         cxstring *output
   502 );
   504 /**
   505  * Splits a given string using a delimiter string.
   506  *
   507  * The array pointed to by \p output will be allocated by \p allocator.
   508  *
   509  * \note The resulting array contains strings that point to the source
   510  * \p string. Use cx_strdup() to get copies.
   511  *
   512  * \attention If allocation fails, the \c NULL pointer will be written to
   513  * \p output and the number returned will be zero.
   514  *
   515  * @param allocator the allocator to use for allocating the resulting array
   516  * @param string the string to split
   517  * @param delim  the delimiter
   518  * @param limit the maximum number of split items
   519  * @param output a pointer where the address of the allocated array shall be
   520  * written to
   521  * @return the actual number of split items
   522  */
   523 __attribute__((__warn_unused_result__, __nonnull__))
   524 size_t cx_strsplit_a(
   525         CxAllocator *allocator,
   526         cxstring string,
   527         cxstring delim,
   528         size_t limit,
   529         cxstring **output
   530 );
   533 /**
   534  * Splits a given string using a delimiter string.
   535  *
   536  * \note The resulting array contains strings that point to the source
   537  * \p string. Use cx_strdup() to get copies.
   538  *
   539  * @param string the string to split
   540  * @param delim  the delimiter
   541  * @param limit the maximum number of split items
   542  * @param output a pre-allocated array of at least \p limit length
   543  * @return the actual number of split items
   544  */
   545 __attribute__((__warn_unused_result__, __nonnull__))
   546 size_t cx_strsplit_m(
   547         cxmutstr string,
   548         cxstring delim,
   549         size_t limit,
   550         cxmutstr *output
   551 );
   553 /**
   554  * Splits a given string using a delimiter string.
   555  *
   556  * The array pointed to by \p output will be allocated by \p allocator.
   557  *
   558  * \note The resulting array contains strings that point to the source
   559  * \p string. Use cx_strdup() to get copies.
   560  *
   561  * \attention If allocation fails, the \c NULL pointer will be written to
   562  * \p output and the number returned will be zero.
   563  *
   564  * @param allocator the allocator to use for allocating the resulting array
   565  * @param string the string to split
   566  * @param delim  the delimiter
   567  * @param limit the maximum number of split items
   568  * @param output a pointer where the address of the allocated array shall be
   569  * written to
   570  * @return the actual number of split items
   571  */
   572 __attribute__((__warn_unused_result__, __nonnull__))
   573 size_t cx_strsplit_ma(
   574         CxAllocator *allocator,
   575         cxmutstr string,
   576         cxstring delim,
   577         size_t limit,
   578         cxmutstr **output
   579 );
   581 /**
   582  * Compares two strings.
   583  *
   584  * @param s1 the first string
   585  * @param s2 the second string
   586  * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
   587  * than \p s2, zero if both strings equal
   588  */
   589 __attribute__((__warn_unused_result__))
   590 int cx_strcmp(
   591         cxstring s1,
   592         cxstring s2
   593 );
   595 /**
   596  * Compares two strings ignoring case.
   597  *
   598  * @param s1 the first string
   599  * @param s2 the second string
   600  * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
   601  * than \p s2, zero if both strings equal ignoring case
   602  */
   603 __attribute__((__warn_unused_result__))
   604 int cx_strcasecmp(
   605         cxstring s1,
   606         cxstring s2
   607 );
   610 /**
   611  * Creates a duplicate of the specified string.
   612  *
   613  * The new string will contain a copy allocated by \p allocator.
   614  *
   615  * \note The returned string is guaranteed to be zero-terminated.
   616  *
   617  * @param allocator the allocator to use
   618  * @param string the string to duplicate
   619  * @return a duplicate of the string
   620  * @see cx_strdup()
   621  */
   622 __attribute__((__warn_unused_result__, __nonnull__))
   623 cxmutstr cx_strdup_a(
   624         CxAllocator *allocator,
   625         cxstring string
   626 );
   628 /**
   629  * Creates a duplicate of the specified string.
   630  *
   631  * The new string will contain a copy allocated by standard
   632  * \c malloc(). So developers \em must pass the return value to cx_strfree().
   633  *
   634  * \note The returned string is guaranteed to be zero-terminated.
   635  *
   636  * @param string the string to duplicate
   637  * @return a duplicate of the string
   638  * @see cx_strdup_a()
   639  */
   640 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
   642 /**
   643  * Omits leading and trailing spaces.
   644  *
   645  * \note the returned string references the same memory, thus you
   646  * must \em not free the returned memory.
   647  *
   648  * @param string the string that shall be trimmed
   649  * @return the trimmed string
   650  */
   651 __attribute__((__warn_unused_result__))
   652 cxstring cx_strtrim(cxstring string);
   654 /**
   655  * Omits leading and trailing spaces.
   656  *
   657  * \note the returned string references the same memory, thus you
   658  * must \em not free the returned memory.
   659  *
   660  * @param string the string that shall be trimmed
   661  * @return the trimmed string
   662  */
   663 __attribute__((__warn_unused_result__))
   664 cxmutstr cx_strtrim_m(cxmutstr string);
   666 /**
   667  * Checks, if a string has a specific prefix.
   668  *
   669  * @param string the string to check
   670  * @param prefix the prefix the string should have
   671  * @return \c true, if and only if the string has the specified prefix,
   672  * \c false otherwise
   673  */
   674 __attribute__((__warn_unused_result__))
   675 bool cx_strprefix(
   676         cxstring string,
   677         cxstring prefix
   678 );
   680 /**
   681  * Checks, if a string has a specific suffix.
   682  *
   683  * @param string the string to check
   684  * @param suffix the suffix the string should have
   685  * @return \c true, if and only if the string has the specified suffix,
   686  * \c false otherwise
   687  */
   688 __attribute__((__warn_unused_result__))
   689 bool cx_strsuffix(
   690         cxstring string,
   691         cxstring suffix
   692 );
   694 /**
   695  * Checks, if a string has a specific prefix, ignoring the case.
   696  *
   697  * @param string the string to check
   698  * @param prefix the prefix the string should have
   699  * @return \c true, if and only if the string has the specified prefix,
   700  * \c false otherwise
   701  */
   702 __attribute__((__warn_unused_result__))
   703 bool cx_strcaseprefix(
   704         cxstring string,
   705         cxstring prefix
   706 );
   708 /**
   709  * Checks, if a string has a specific suffix, ignoring the case.
   710  *
   711  * @param string the string to check
   712  * @param suffix the suffix the string should have
   713  * @return \c true, if and only if the string has the specified suffix,
   714  * \c false otherwise
   715  */
   716 __attribute__((__warn_unused_result__))
   717 bool cx_strcasesuffix(
   718         cxstring string,
   719         cxstring suffix
   720 );
   722 /**
   723  * Converts the string to lower case.
   724  *
   725  * The change is made in-place. If you want a copy, use cx_strdup(), first.
   726  *
   727  * @param string the string to modify
   728  * @see cx_strdup()
   729  */
   730 void cx_strlower(cxmutstr string);
   732 /**
   733  * Converts the string to upper case.
   734  *
   735  * The change is made in-place. If you want a copy, use cx_strdup(), first.
   736  *
   737  * @param string the string to modify
   738  * @see cx_strdup()
   739  */
   740 void cx_strupper(cxmutstr string);
   742 /**
   743  * Replaces a pattern in a string with another string.
   744  *
   745  * The pattern is taken literally and is no regular expression.
   746  * Replaces at most \p replmax occurrences.
   747  *
   748  * The returned string will be allocated by \p allocator and is guaranteed
   749  * to be zero-terminated.
   750  *
   751  * If allocation fails, or the input string is empty,
   752  * the returned string will be empty.
   753  *
   754  * @param allocator the allocator to use
   755  * @param str the string where replacements should be applied
   756  * @param pattern the pattern to search for
   757  * @param replacement the replacement string
   758  * @param replmax maximum number of replacements
   759  * @return the resulting string after applying the replacements
   760  */
   761 __attribute__((__warn_unused_result__, __nonnull__))
   762 cxmutstr cx_strreplacen_a(
   763         CxAllocator *allocator,
   764         cxstring str,
   765         cxstring pattern,
   766         cxstring replacement,
   767         size_t replmax
   768 );
   770 /**
   771  * Replaces a pattern in a string with another string.
   772  *
   773  * The pattern is taken literally and is no regular expression.
   774  * Replaces at most \p replmax occurrences.
   775  *
   776  * The returned string will be allocated by \c malloc() and is guaranteed
   777  * to be zero-terminated.
   778  *
   779  * If allocation fails, or the input string is empty,
   780  * the returned string will be empty.
   781  *
   782  * @param str the string where replacements should be applied
   783  * @param pattern the pattern to search for
   784  * @param replacement the replacement string
   785  * @param replmax maximum number of replacements
   786  * @return the resulting string after applying the replacements
   787  */
   788 #define cx_strreplacen(str, pattern, replacement, replmax) \
   789 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax)
   791 /**
   792  * Replaces a pattern in a string with another string.
   793  *
   794  * The pattern is taken literally and is no regular expression.
   795  *
   796  * The returned string will be allocated by \p allocator and is guaranteed
   797  * to be zero-terminated.
   798  *
   799  * If allocation fails, or the input string is empty,
   800  * the returned string will be empty.
   801  *
   802  * @param allocator the allocator to use
   803  * @param str the string where replacements should be applied
   804  * @param pattern the pattern to search for
   805  * @param replacement the replacement string
   806  * @return the resulting string after applying the replacements
   807  */
   808 #define cx_strreplace_a(allocator, str, pattern, replacement) \
   809 cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX)
   811 /**
   812  * Replaces a pattern in a string with another string.
   813  *
   814  * The pattern is taken literally and is no regular expression.
   815  * Replaces at most \p replmax occurrences.
   816  *
   817  * The returned string will be allocated by \c malloc() and is guaranteed
   818  * to be zero-terminated.
   819  *
   820  * If allocation fails, or the input string is empty,
   821  * the returned string will be empty.
   822  *
   823  * @param str the string where replacements should be applied
   824  * @param pattern the pattern to search for
   825  * @param replacement the replacement string
   826  * @return the resulting string after applying the replacements
   827  */
   828 #define cx_strreplace(str, pattern, replacement) \
   829 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX)
   831 #ifdef __cplusplus
   832 } // extern "C"
   833 #endif
   835 #endif //UCX_STRING_H

mercurial