1 /*
2 Functions for replacing substrings in strings.
3
4 Copyright (C) 2013-2025
5 Free Software Foundation, Inc.
6
7 Written by:
8 Slava Zanko <slavazanko@gmail.com>, 2013;
9
10 This file is part of the Midnight Commander.
11
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
16
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
26 #include <config.h>
27
28 #include "lib/global.h"
29 #include "lib/strutil.h"
30
31 /*** global variables ****************************************************************************/
32
33 /*** file scope macro definitions ****************************************************************/
34
35 /*** file scope type declarations ****************************************************************/
36
37 /*** forward declarations (file scope functions) *************************************************/
38
39 /*** file scope variables ************************************************************************/
40
41 /* --------------------------------------------------------------------------------------------- */
42 /*** file scope functions ************************************************************************/
43 /* --------------------------------------------------------------------------------------------- */
44
45 /* --------------------------------------------------------------------------------------------- */
46 /*** public functions ****************************************************************************/
47 /* --------------------------------------------------------------------------------------------- */
48 /**
49 * Replace all substrings 'needle' in string 'haystack' by 'replacement'.
50 * If the 'needle' in the 'haystack' is escaped by backslash,
51 * then this occurrence isn't be replaced.
52 *
53 * @param haystack string contains substrings for replacement. Cannot be NULL.
54 * @param needle string for search. Cannot be NULL.
55 * @param replacement string for replace. Cannot be NULL.
56 * @return newly allocated string with replaced substrings or NULL if @haystack is empty.
57 */
58
59 char *
60 str_replace_all (const char *haystack, const char *needle, const char *replacement)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
61 {
62 size_t needle_len, replacement_len;
63 GString *return_str = NULL;
64 char *needle_in_str;
65
66 needle_len = strlen (needle);
67 replacement_len = strlen (replacement);
68
69 while ((needle_in_str = strstr (haystack, needle)) != NULL)
70 {
71 if (return_str == NULL)
72 return_str = g_string_sized_new (32);
73
74 if (str_is_char_escaped (haystack, needle_in_str))
75 {
76 char *backslash = needle_in_str - 1;
77
78 if (haystack != backslash)
79 g_string_append_len (return_str, haystack, backslash - haystack);
80 g_string_append_len (return_str, needle_in_str, needle_in_str - backslash);
81 haystack = needle_in_str + 1;
82 }
83 else
84 {
85 if (needle_in_str != haystack)
86 g_string_append_len (return_str, haystack, needle_in_str - haystack);
87 g_string_append_len (return_str, replacement, replacement_len);
88 haystack = needle_in_str + needle_len;
89 }
90 }
91
92 if (*haystack != '\0')
93 {
94 if (return_str == NULL)
95 return g_strdup (haystack);
96
97 g_string_append (return_str, haystack);
98 }
99
100 return (return_str != NULL ? g_string_free (return_str, FALSE) : NULL);
101 }
102
103 /* --------------------------------------------------------------------------------------------- */