Fri, 09 Sep 2022 20:19:08 +0200
add tests and missing implementations for strings
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 * As a special case, a \c NULL argument is treated like an empty string.
100 *
101 * \note the wrapped string will share the specified pointer to the string.
102 * If you do want a copy, use cx_strdup() on the return value of this function.
103 *
104 * If you need to wrap a constant string, use cx_str().
105 *
106 * @param cstring the string to wrap, must be zero-terminated (or \c NULL)
107 * @return the wrapped string
108 *
109 * @see cx_mutstrn()
110 */
111 __attribute__((__warn_unused_result__))
112 cxmutstr cx_mutstr(char *cstring);
114 /**
115 * Wraps a string that does not need to be zero-terminated.
116 *
117 * The argument may be \c NULL if the length is zero.
118 *
119 * \note the wrapped string will share the specified pointer to the string.
120 * If you do want a copy, use cx_strdup() on the return value of this function.
121 *
122 * If you need to wrap a constant string, use cx_strn().
123 *
124 * @param cstring the string to wrap (or \c NULL, if the length is zero)
125 * @param length the length of the string
126 * @return the wrapped string
127 *
128 * @see cx_mutstr()
129 */
130 __attribute__((__warn_unused_result__))
131 cxmutstr cx_mutstrn(
132 char *cstring,
133 size_t length
134 );
136 /**
137 * Wraps a string that must be zero-terminated.
138 *
139 * The length is implicitly inferred by using a call to \c strlen().
140 * As a special case, a \c NULL argument is treated like an empty string.
141 *
142 * \note the wrapped string will share the specified pointer to the string.
143 * If you do want a copy, use cx_strdup() on the return value of this function.
144 *
145 * If you need to wrap a non-constant string, use cx_mutstr().
146 *
147 * @param cstring the string to wrap, must be zero-terminated (or \c NULL)
148 * @return the wrapped string
149 *
150 * @see cx_strn()
151 */
152 __attribute__((__warn_unused_result__))
153 cxstring cx_str(char const *cstring);
156 /**
157 * Wraps a string that does not need to be zero-terminated.
158 *
159 * The argument may be \c NULL if the length is zero.
160 *
161 * \note the wrapped string will share the specified pointer to the string.
162 * If you do want a copy, use cx_strdup() on the return value of this function.
163 *
164 * If you need to wrap a non-constant string, use cx_mutstrn().
165 *
166 * @param cstring the string to wrap (or \c NULL, if the length is zero)
167 * @param length the length of the string
168 * @return the wrapped string
169 *
170 * @see cx_str()
171 */
172 __attribute__((__warn_unused_result__))
173 cxstring cx_strn(
174 char const *cstring,
175 size_t length
176 );
178 /**
179 * Casts a mutable string to an immutable string.
180 *
181 * \note This is not seriously a cast. Instead you get a copy
182 * of the struct with the desired pointer type. Both structs still
183 * point to the same location, though!
184 *
185 * @param str the mutable string to cast
186 * @return an immutable copy of the string pointer
187 */
188 __attribute__((__warn_unused_result__))
189 cxstring cx_strcast(cxmutstr str);
191 /**
192 * Passes the pointer in this string to \c free().
193 *
194 * The pointer in the struct is set to \c NULL and the length is set to zero.
195 *
196 * \note There is no implementation for cxstring, because it is unlikely that
197 * you ever have a \c char \c const* you are really supposed to free. If you
198 * encounter such situation, you should double-check your code.
199 *
200 * @param str the string to free
201 */
202 __attribute__((__nonnull__))
203 void cx_strfree(cxmutstr *str);
205 /**
206 * Passes the pointer in this string to the allocators free function.
207 *
208 * The pointer in the struct is set to \c NULL and the length is set to zero.
209 *
210 * \note There is no implementation for cxstring, because it is unlikely that
211 * you ever have a \c char \c const* you are really supposed to free. If you
212 * encounter such situation, you should double-check your code.
213 *
214 * @param alloc the allocator
215 * @param str the string to free
216 */
217 __attribute__((__nonnull__))
218 void cx_strfree_a(
219 CxAllocator *alloc,
220 cxmutstr *str
221 );
223 /**
224 * Returns the accumulated length of all specified strings.
225 *
226 * \attention if the count argument is larger than the number of the
227 * specified strings, the behavior is undefined.
228 *
229 * @param count the total number of specified strings
230 * @param ... all strings
231 * @return the accumulated length of all strings
232 */
233 __attribute__((__warn_unused_result__))
234 size_t cx_strlen(
235 size_t count,
236 ...
237 );
239 /**
240 * Concatenates two or more strings.
241 *
242 * The resulting string will be allocated by the specified allocator.
243 * So developers \em must pass the return value to cx_strfree() eventually.
244 *
245 * \note It is guaranteed that there is only one allocation.
246 *
247 * @param alloc the allocator to use
248 * @param count the total number of strings to concatenate
249 * @param ... all strings
250 * @return the concatenated string
251 */
252 __attribute__((__warn_unused_result__, __nonnull__))
253 cxmutstr cx_strcat_a(
254 CxAllocator *alloc,
255 size_t count,
256 ...
257 );
259 /**
260 * Concatenates two or more strings.
261 *
262 * The resulting string will be allocated by standard \c malloc().
263 * So developers \em must pass the return value to cx_strfree() eventually.
264 *
265 * @param count the total number of strings to concatenate
266 * @param ... all strings
267 * @return the concatenated string
268 */
269 #define cx_strcat(count, ...) \
270 cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__)
272 /**
273 * Returns a substring starting at the specified location.
274 *
275 * \attention the new string references the same memory area as the
276 * input string and is usually \em not zero-terminated.
277 * Use cx_strdup() to get a copy.
278 *
279 * @param string input string
280 * @param start start location of the substring
281 * @return a substring of \p string starting at \p start
282 *
283 * @see cx_strsubsl()
284 * @see cx_strsubs_m()
285 * @see cx_strsubsl_m()
286 */
287 __attribute__((__warn_unused_result__))
288 cxstring cx_strsubs(
289 cxstring string,
290 size_t start
291 );
293 /**
294 * Returns a substring starting at the specified location.
295 *
296 * The returned string will be limited to \p length bytes or the number
297 * of bytes available in \p string, whichever is smaller.
298 *
299 * \attention the new string references the same memory area as the
300 * input string and is usually \em not zero-terminated.
301 * Use cx_strdup() to get a copy.
302 *
303 * @param string input string
304 * @param start start location of the substring
305 * @param length the maximum length of the returned string
306 * @return a substring of \p string starting at \p start
307 *
308 * @see cx_strsubs()
309 * @see cx_strsubs_m()
310 * @see cx_strsubsl_m()
311 */
312 __attribute__((__warn_unused_result__))
313 cxstring cx_strsubsl(
314 cxstring string,
315 size_t start,
316 size_t length
317 );
319 /**
320 * Returns a substring starting at the specified location.
321 *
322 * \attention the new string references the same memory area as the
323 * input string and is usually \em not zero-terminated.
324 * Use cx_strdup() to get a copy.
325 *
326 * @param string input string
327 * @param start start location of the substring
328 * @return a substring of \p string starting at \p start
329 *
330 * @see cx_strsubsl_m()
331 * @see cx_strsubs()
332 * @see cx_strsubsl()
333 */
334 __attribute__((__warn_unused_result__))
335 cxmutstr cx_strsubs_m(
336 cxmutstr string,
337 size_t start
338 );
340 /**
341 * Returns a substring starting at the specified location.
342 *
343 * The returned string will be limited to \p length bytes or the number
344 * of bytes available in \p string, whichever is smaller.
345 *
346 * \attention the new string references the same memory area as the
347 * input string and is usually \em not zero-terminated.
348 * Use cx_strdup() to get a copy.
349 *
350 * @param string input string
351 * @param start start location of the substring
352 * @param length the maximum length of the returned string
353 * @return a substring of \p string starting at \p start
354 *
355 * @see cx_strsubs_m()
356 * @see cx_strsubs()
357 * @see cx_strsubsl()
358 */
359 __attribute__((__warn_unused_result__))
360 cxmutstr cx_strsubsl_m(
361 cxmutstr string,
362 size_t start,
363 size_t length
364 );
366 /**
367 * Returns a substring starting at the location of the first occurrence of the
368 * specified character.
369 *
370 * If the string does not contain the character, an empty string is returned.
371 *
372 * @param string the string where to locate the character
373 * @param chr the character to locate
374 * @return a substring starting at the first location of \p chr
375 *
376 * @see cx_strchr_m()
377 */
378 __attribute__((__warn_unused_result__))
379 cxstring cx_strchr(
380 cxstring string,
381 int chr
382 );
384 /**
385 * Returns a substring starting at the location of the first occurrence of the
386 * specified character.
387 *
388 * If the string does not contain the character, an empty string is returned.
389 *
390 * @param string the string where to locate the character
391 * @param chr the character to locate
392 * @return a substring starting at the first location of \p chr
393 *
394 * @see cx_strchr()
395 */
396 __attribute__((__warn_unused_result__))
397 cxmutstr cx_strchr_m(
398 cxmutstr string,
399 int chr
400 );
402 /**
403 * Returns a substring starting at the location of the last occurrence of the
404 * specified character.
405 *
406 * If the string does not contain the character, an empty string is returned.
407 *
408 * @param string the string where to locate the character
409 * @param chr the character to locate
410 * @return a substring starting at the last location of \p chr
411 *
412 * @see cx_strrchr_m()
413 */
414 __attribute__((__warn_unused_result__))
415 cxstring cx_strrchr(
416 cxstring string,
417 int chr
418 );
420 /**
421 * Returns a substring starting at the location of the last occurrence of the
422 * specified character.
423 *
424 * If the string does not contain the character, an empty string is returned.
425 *
426 * @param string the string where to locate the character
427 * @param chr the character to locate
428 * @return a substring starting at the last location of \p chr
429 *
430 * @see cx_strrchr()
431 */
432 __attribute__((__warn_unused_result__))
433 cxmutstr cx_strrchr_m(
434 cxmutstr string,
435 int chr
436 );
438 /**
439 * Returns a substring starting at the location of the first occurrence of the
440 * specified string.
441 *
442 * If \p haystack does not contain \p needle, an empty string is returned.
443 *
444 * If \p needle is an empty string, the complete \p haystack is
445 * returned.
446 *
447 * @param haystack the string to be scanned
448 * @param needle string containing the sequence of characters to match
449 * @return a substring starting at the first occurrence of
450 * \p needle, or an empty string, if the sequence is not
451 * contained
452 * @see cx_strstr_m()
453 */
454 __attribute__((__warn_unused_result__))
455 cxstring cx_strstr(
456 cxstring haystack,
457 cxstring needle
458 );
460 /**
461 * Returns a substring starting at the location of the first occurrence of the
462 * specified string.
463 *
464 * If \p haystack does not contain \p needle, an empty string is returned.
465 *
466 * If \p needle is an empty string, the complete \p haystack is
467 * returned.
468 *
469 * @param haystack the string to be scanned
470 * @param needle string containing the sequence of characters to match
471 * @return a substring starting at the first occurrence of
472 * \p needle, or an empty string, if the sequence is not
473 * contained
474 * @see cx_strstr()
475 */
476 __attribute__((__warn_unused_result__))
477 cxmutstr cx_strstr_m(
478 cxmutstr haystack,
479 cxstring needle
480 );
482 /**
483 * Splits a given string using a delimiter string.
484 *
485 * \note The resulting array contains strings that point to the source
486 * \p string. Use cx_strdup() to get copies.
487 *
488 * @param string the string to split
489 * @param delim the delimiter
490 * @param limit the maximum number of split items
491 * @param output a pre-allocated array of at least \p limit length
492 * @return the actual number of split items
493 */
494 __attribute__((__warn_unused_result__, __nonnull__))
495 size_t cx_strsplit(
496 cxstring string,
497 cxstring delim,
498 size_t limit,
499 cxstring *output
500 );
502 /**
503 * Splits a given string using a delimiter string.
504 *
505 * The array pointed to by \p output will be allocated by \p allocator.
506 *
507 * \note The resulting array contains strings that point to the source
508 * \p string. Use cx_strdup() to get copies.
509 *
510 * \attention If allocation fails, the \c NULL pointer will be written to
511 * \p output and the number returned will be zero.
512 *
513 * @param allocator the allocator to use for allocating the resulting array
514 * @param string the string to split
515 * @param delim the delimiter
516 * @param limit the maximum number of split items
517 * @param output a pointer where the address of the allocated array shall be
518 * written to
519 * @return the actual number of split items
520 */
521 __attribute__((__warn_unused_result__, __nonnull__))
522 size_t cx_strsplit_a(
523 CxAllocator *allocator,
524 cxstring string,
525 cxstring delim,
526 size_t limit,
527 cxstring **output
528 );
531 /**
532 * Splits a given string using a delimiter string.
533 *
534 * \note The resulting array contains strings that point to the source
535 * \p string. Use cx_strdup() to get copies.
536 *
537 * @param string the string to split
538 * @param delim the delimiter
539 * @param limit the maximum number of split items
540 * @param output a pre-allocated array of at least \p limit length
541 * @return the actual number of split items
542 */
543 __attribute__((__warn_unused_result__, __nonnull__))
544 size_t cx_strsplit_m(
545 cxmutstr string,
546 cxstring delim,
547 size_t limit,
548 cxmutstr *output
549 );
551 /**
552 * Splits a given string using a delimiter string.
553 *
554 * The array pointed to by \p output will be allocated by \p allocator.
555 *
556 * \note The resulting array contains strings that point to the source
557 * \p string. Use cx_strdup() to get copies.
558 *
559 * \attention If allocation fails, the \c NULL pointer will be written to
560 * \p output and the number returned will be zero.
561 *
562 * @param allocator the allocator to use for allocating the resulting array
563 * @param string the string to split
564 * @param delim the delimiter
565 * @param limit the maximum number of split items
566 * @param output a pointer where the address of the allocated array shall be
567 * written to
568 * @return the actual number of split items
569 */
570 __attribute__((__warn_unused_result__, __nonnull__))
571 size_t cx_strsplit_ma(
572 CxAllocator *allocator,
573 cxmutstr string,
574 cxstring delim,
575 size_t limit,
576 cxmutstr **output
577 );
579 /**
580 * Compares two strings.
581 *
582 * @param s1 the first string
583 * @param s2 the second string
584 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
585 * than \p s2, zero if both strings equal
586 */
587 __attribute__((__warn_unused_result__))
588 int cx_strcmp(
589 cxstring s1,
590 cxstring s2
591 );
593 /**
594 * Compares two strings ignoring case.
595 *
596 * @param s1 the first string
597 * @param s2 the second string
598 * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger
599 * than \p s2, zero if both strings equal ignoring case
600 */
601 __attribute__((__warn_unused_result__))
602 int cx_strcasecmp(
603 cxstring s1,
604 cxstring s2
605 );
608 /**
609 * Creates a duplicate of the specified string.
610 *
611 * The new string will contain a copy allocated by \p allocator.
612 *
613 * \note The returned string is guaranteed to be zero-terminated and can safely
614 * be passed to other APIs.
615 *
616 * @param allocator the allocator to use
617 * @param string the string to duplicate
618 * @return a duplicate of the string
619 * @see cx_strdup()
620 */
621 __attribute__((__warn_unused_result__, __nonnull__))
622 cxmutstr cx_strdup_a(
623 CxAllocator *allocator,
624 cxstring string
625 );
627 /**
628 * Creates a duplicate of the specified string.
629 *
630 * The new string will contain a copy allocated by standard
631 * \c malloc(). So developers \em must pass the return value to cx_strfree().
632 *
633 * \note The returned string is guaranteed to be zero-terminated and can safely
634 * be passed to other APIs.
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.
749 *
750 * If allocation fails, or the input string is empty,
751 * the returned string will be empty.
752 *
753 * @param allocator the allocator to use
754 * @param str the string where replacements should be applied
755 * @param pattern the pattern to search for
756 * @param replacement the replacement string
757 * @param replmax maximum number of replacements
758 * @return the resulting string after applying the replacements
759 */
760 __attribute__((__warn_unused_result__, __nonnull__))
761 cxmutstr cx_strreplacen_a(
762 CxAllocator *allocator,
763 cxstring str,
764 cxstring pattern,
765 cxstring replacement,
766 size_t replmax
767 );
769 /**
770 * Replaces a pattern in a string with another string.
771 *
772 * The pattern is taken literally and is no regular expression.
773 * Replaces at most \p replmax occurrences.
774 *
775 * The returned string will be allocated by \c malloc() and \em must be passed
776 * to cx_strfree() eventually.
777 *
778 * If allocation fails, or the input string is empty,
779 * the returned string will be empty.
780 *
781 * @param str the string where replacements should be applied
782 * @param pattern the pattern to search for
783 * @param replacement the replacement string
784 * @param replmax maximum number of replacements
785 * @return the resulting string after applying the replacements
786 */
787 #define cx_strreplacen(str, pattern, replacement, replmax) \
788 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax)
790 /**
791 * Replaces a pattern in a string with another string.
792 *
793 * The pattern is taken literally and is no regular expression.
794 *
795 * The returned string will be allocated by \p allocator.
796 *
797 * If allocation fails, or the input string is empty,
798 * the returned string will be empty.
799 *
800 * @param allocator the allocator to use
801 * @param str the string where replacements should be applied
802 * @param pattern the pattern to search for
803 * @param replacement the replacement string
804 * @return the resulting string after applying the replacements
805 */
806 #define cx_strreplace_a(allocator, str, pattern, replacement) \
807 cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX)
809 /**
810 * Replaces a pattern in a string with another string.
811 *
812 * The pattern is taken literally and is no regular expression.
813 * Replaces at most \p replmax occurrences.
814 *
815 * The returned string will be allocated by \c malloc() and \em must be passed
816 * to cx_strfree() eventually.
817 *
818 * If allocation fails, or the input string is empty,
819 * the returned string will be empty.
820 *
821 * @param str the string where replacements should be applied
822 * @param pattern the pattern to search for
823 * @param replacement the replacement string
824 * @return the resulting string after applying the replacements
825 */
826 #define cx_strreplace(str, pattern, replacement) \
827 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX)
829 #ifdef __cplusplus
830 } // extern "C"
831 #endif
833 #endif //UCX_STRING_H