aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2025-11-18 14:54:47 +0000
committerWerner Koch <[email protected]>2025-11-18 14:54:47 +0000
commitbe9b1404e66157ac00bf3ae488ad2af1becffe25 (patch)
tree0bcadacebbe332986ad12154dc7ef5cd5452735e
parentgpg: Include ADSK keys in a key listing with fingerprints. (diff)
downloadgnupg-be9b1404e66157ac00bf3ae488ad2af1becffe25.tar.gz
gnupg-be9b1404e66157ac00bf3ae488ad2af1becffe25.zip
common: New function replace_substr.
* common/stringhelp.c (replace_substr): New. * common/t-stringhelp.c (test_replace_substr): New test.
-rw-r--r--common/stringhelp.c33
-rw-r--r--common/stringhelp.h7
-rw-r--r--common/t-stringhelp.c112
3 files changed, 151 insertions, 1 deletions
diff --git a/common/stringhelp.c b/common/stringhelp.c
index 9347c3551..8bbc68ab1 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -2,7 +2,7 @@
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
* 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
- * Copyright (C) 2015, 2021 g10 Code GmbH
+ * Copyright (C) 2015, 2021, 2025 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -1721,6 +1721,37 @@ format_text (const char *text_in, int target_cols, int max_cols)
}
+/* In STRING replace the first occurance of SUBSTR by the string
+ * REPLACE. Return a new malloced string or set ERRNO and set NULL on
+ * error. If SUBSTR is not found a verbatim copy of STRING is
+ * returned. */
+char *
+replace_substr (const char *string, const char *substr, const char *replace)
+{
+ size_t stringlen, substrlen, replacelen, n;
+ const char *s;
+ char *buffer;
+
+ stringlen = strlen (string);
+ substrlen = strlen (substr);
+ replacelen = strlen (replace);
+
+ if (stringlen < substrlen || !(s = strstr (string, substr)))
+ return xtrystrdup (string);
+
+ stringlen -= substrlen; /* Found thus sryinglen >= substrlen */
+ buffer = xtrymalloc (stringlen + replacelen +1);
+ if (!buffer)
+ return NULL;
+ memcpy (buffer, string, n=(s-string));
+ memcpy (buffer+n, replace, replacelen);
+ strcpy (buffer+n+replacelen, s+substrlen);
+
+
+ return buffer;
+}
+
+
/* Substitute variables in STRING and return a new string. GETVAL is
* a function which maps NAME to its value; that value is a string
* which may not change during the execution time of this function.
diff --git a/common/stringhelp.h b/common/stringhelp.h
index d93373ec5..037ee8139 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -170,6 +170,13 @@ int compare_version_strings (const char *my_version, const char *req_version);
/* Format a string so that it fits within about TARGET_COLS columns. */
char *format_text (const char *text, int target_cols, int max_cols);
+
+/* Return a new malloced string with the first occurance of SUBSTR in
+ * STRING replaced by REPLACE. Returns NULL on memory error. */
+char *replace_substr (const char *string,
+ const char *substr, const char *replace);
+
+
/* Substitute variables in STRING. */
char *substitute_vars (const char *string,
const char *(*getval)(void *cookie, const char *name),
diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c
index b43bb7932..3bd9ba928 100644
--- a/common/t-stringhelp.c
+++ b/common/t-stringhelp.c
@@ -1202,6 +1202,117 @@ test_compare_version_strings (void)
static void
+test_replace_substr (void)
+{
+ struct {
+ const char *string;
+ const char *substr;
+ const char *replace;
+ const char *result;
+ } t[] = {
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ "view ",
+ "Look afar and view the end from the beginning."
+ },
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ "xxx ",
+ "Look afar and xxx the end from the beginning."
+ },
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ "xx ",
+ "Look afar and xx the end from the beginning."
+ },
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ "x ",
+ "Look afar and x the end from the beginning."
+ },
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ " ",
+ "Look afar and the end from the beginning."
+ },
+ { "Look afar and see the end from the beginning.",
+ "see ",
+ "",
+ "Look afar and the end from the beginning."
+ },
+ { "Be different: conform.",
+ "",
+ "xxx",
+ "xxxBe different: conform."
+ },
+ { "Be different: conform.",
+ "foo",
+ "bar",
+ "Be different: conform."
+ },
+ { "Be different: conform.",
+ "different",
+ "unlike",
+ "Be unlike: conform."
+ },
+ { "Be different: conform.",
+ "B",
+ "Bee",
+ "Beee different: conform."
+ },
+ { "Be different: conform.",
+ ".",
+ "",
+ "Be different: conform"
+ },
+ { "Be different: conform.",
+ ".",
+ "!",
+ "Be different: conform!"
+ },
+ { "Be different: conform.",
+ ".",
+ "...",
+ "Be different: conform..."
+ },
+ { "Be different: conform.",
+ ":",
+ " - this is a very long replacement string - ",
+ "Be different - this is a very long replacement string - conform."
+ },
+ { "",
+ "",
+ "",
+ ""
+ }
+ };
+ int idx;
+ char *res;
+
+ for (idx=0; idx < DIM(t); idx++)
+ {
+ res = replace_substr (t[idx].string, t[idx].substr, t[idx].replace);
+ if (!res)
+ {
+ fprintf (stderr,"error replacing in '%s' (test %d): %s\n",
+ t[idx].string, idx, strerror (errno));
+ exit (2);
+ }
+ if (strcmp (res, t[idx].result))
+ {
+ fprintf (stderr, "string is '%s'\n", t[idx].string);
+ fprintf (stderr, " substr '%s'\n", t[idx].substr);
+ fprintf (stderr, " replace '%s'\n", t[idx].replace);
+ fprintf (stderr, " expected '%s'\n", t[idx].result);
+ fprintf (stderr, " got '%s'\n", res);
+ fail (idx);
+ }
+ xfree (res);
+ }
+}
+
+
+static void
test_substitute_envvars (void)
{
struct {
@@ -1317,6 +1428,7 @@ main (int argc, char **argv)
test_split_fields_colon ();
test_compare_version_strings ();
test_format_text ();
+ test_replace_substr ();
test_substitute_envvars ();
xfree (home_buffer);