mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
Add virStringReplace method for substring replacement
Add a virStringReplace method to virstring.{h,c} to perform substring matching and replacement Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
12aa71dfde
commit
66e3a3e914
@ -1798,6 +1798,7 @@ virStringArrayHasString;
|
|||||||
virStringFreeList;
|
virStringFreeList;
|
||||||
virStringJoin;
|
virStringJoin;
|
||||||
virStringListLength;
|
virStringListLength;
|
||||||
|
virStringReplace;
|
||||||
virStringSearch;
|
virStringSearch;
|
||||||
virStringSortCompare;
|
virStringSortCompare;
|
||||||
virStringSortRevCompare;
|
virStringSortRevCompare;
|
||||||
|
@ -749,3 +749,48 @@ cleanup:
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virStringReplace:
|
||||||
|
* @haystack: the source string to process
|
||||||
|
* @oldneedle: the substring to locate
|
||||||
|
* @newneedle: the substring to insert
|
||||||
|
*
|
||||||
|
* Search @haystack and replace all occurences of @oldneedle with @newneedle.
|
||||||
|
*
|
||||||
|
* Returns: a new string with all the replacements, or NULL on error
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
virStringReplace(const char *haystack,
|
||||||
|
const char *oldneedle,
|
||||||
|
const char *newneedle)
|
||||||
|
{
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
const char *tmp1, *tmp2;
|
||||||
|
size_t oldneedlelen = strlen(oldneedle);
|
||||||
|
size_t newneedlelen = strlen(newneedle);
|
||||||
|
|
||||||
|
tmp1 = haystack;
|
||||||
|
tmp2 = NULL;
|
||||||
|
|
||||||
|
while (tmp1) {
|
||||||
|
tmp2 = strstr(tmp1, oldneedle);
|
||||||
|
|
||||||
|
if (tmp2) {
|
||||||
|
virBufferAdd(&buf, tmp1, (tmp2 - tmp1));
|
||||||
|
virBufferAdd(&buf, newneedle, newneedlelen);
|
||||||
|
tmp2 += oldneedlelen;
|
||||||
|
} else {
|
||||||
|
virBufferAdd(&buf, tmp1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp1 = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virBufferError(&buf)) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virBufferContentAndReset(&buf);
|
||||||
|
}
|
||||||
|
@ -232,5 +232,10 @@ ssize_t virStringSearch(const char *str,
|
|||||||
char ***matches)
|
char ***matches)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
|
||||||
|
|
||||||
|
char *virStringReplace(const char *haystack,
|
||||||
|
const char *oldneedle,
|
||||||
|
const char *newneedle)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __VIR_STRING_H__ */
|
#endif /* __VIR_STRING_H__ */
|
||||||
|
@ -338,6 +338,39 @@ testStringSearch(const void *opaque ATTRIBUTE_UNUSED)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct stringReplaceData {
|
||||||
|
const char *haystack;
|
||||||
|
const char *oldneedle;
|
||||||
|
const char *newneedle;
|
||||||
|
const char *result;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
testStringReplace(const void *opaque ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
const struct stringReplaceData *data = opaque;
|
||||||
|
char *result;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
result = virStringReplace(data->haystack,
|
||||||
|
data->oldneedle,
|
||||||
|
data->newneedle);
|
||||||
|
|
||||||
|
if (STRNEQ_NULLABLE(data->result, result)) {
|
||||||
|
fprintf(stderr, "Expected '%s' but got '%s'\n",
|
||||||
|
data->result, NULLSTR(result));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(result);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mymain(void)
|
mymain(void)
|
||||||
{
|
{
|
||||||
@ -428,6 +461,37 @@ mymain(void)
|
|||||||
const char *matches3[] = { "foo", "bar" };
|
const char *matches3[] = { "foo", "bar" };
|
||||||
TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false);
|
TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false);
|
||||||
|
|
||||||
|
#define TEST_REPLACE(h, o, n, r) \
|
||||||
|
do { \
|
||||||
|
struct stringReplaceData data = { \
|
||||||
|
.haystack = h, \
|
||||||
|
.oldneedle = o, \
|
||||||
|
.newneedle = n, \
|
||||||
|
.result = r \
|
||||||
|
}; \
|
||||||
|
if (virtTestRun("virStringReplace " h, testStringReplace, &data) < 0) \
|
||||||
|
ret = -1; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* no matches */
|
||||||
|
TEST_REPLACE("foo", "bar", "eek", "foo");
|
||||||
|
|
||||||
|
/* complete match */
|
||||||
|
TEST_REPLACE("foo", "foo", "bar", "bar");
|
||||||
|
|
||||||
|
/* middle match */
|
||||||
|
TEST_REPLACE("foobarwizz", "bar", "eek", "fooeekwizz");
|
||||||
|
|
||||||
|
/* many matches */
|
||||||
|
TEST_REPLACE("foofoofoofoo", "foo", "bar", "barbarbarbar");
|
||||||
|
|
||||||
|
/* many matches */
|
||||||
|
TEST_REPLACE("fooooofoooo", "foo", "bar", "barooobaroo");
|
||||||
|
|
||||||
|
/* different length old/new needles */
|
||||||
|
TEST_REPLACE("fooooofoooo", "foo", "barwizzeek", "barwizzeekooobarwizzeekoo");
|
||||||
|
TEST_REPLACE("fooooofoooo", "foooo", "foo", "fooofoo");
|
||||||
|
|
||||||
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user