util: Add spdk_strcpy_replace() to replace substrings

spdk_nvme_cpl_get_status_string() returns a string which contains upper
cases, spaces, and hyphens. To use the returned string for JSON RPC, we
have to convert it to a string which contains only lowercases and
underscores.

For our convenience, add a new API spdk_strcpy_replace() to replace
all occurrences of the search string with the replacement string.

Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: I3ca9774d0bfb2d0bb7bd7412bc671e6f69104b7d
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16054
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2022-12-21 21:57:32 +09:00 committed by Tomasz Zawadzki
parent 60fd5c554d
commit d6e57b5389
5 changed files with 136 additions and 0 deletions

View File

@ -85,6 +85,9 @@ available trace point groups and mask of the available trace points for each gro
New API `spdk_fd_group_get_epoll_event` that returns the epoll(7) event that
caused a function callback in file descriptor group to execute.
A new API `spdk_strcpy_replace` was added to replace all occurrences of the search string
with the replacement string.
### json
Added API `spdk_json_write_double` and `spdk_json_write_named_double` to allow

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2015 Intel Corporation.
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*/
@ -265,6 +266,22 @@ char **spdk_strarray_dup(const char **strarray);
*/
void spdk_strarray_free(char **strarray);
/**
* Copy a string into a fixed-size buffer with all occurrences of the search string
* replaced with the given replace substring. The fixed-size buffer must not be less
* than the string with the replaced values including the terminating null byte.
*
* \param dst Pointer to destination fixed-size buffer to fill.
* \param size Size of the destination fixed-size buffer in bytes.
* \param src Pointer to source null-terminated string to copy into dst.
* \param search The string being searched for.
* \param replace the replacement substring the replaces the found search substring.
*
* \return 0 on success, or negated errno on failure.
*/
int spdk_strcpy_replace(char *dst, size_t size, const char *src, const char *search,
const char *replace);
#ifdef __cplusplus
}
#endif

View File

@ -126,6 +126,7 @@
spdk_strarray_from_string;
spdk_strarray_dup;
spdk_strarray_free;
spdk_strcpy_replace;
# public functions in util.h
spdk_u32log2;

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2015 Intel Corporation.
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*/
@ -542,3 +543,49 @@ spdk_strarray_dup(const char **strarray)
return result;
}
int
spdk_strcpy_replace(char *dst, size_t size, const char *src, const char *search,
const char *replace)
{
const char *p, *q;
char *r;
size_t c, search_size, replace_size, dst_size;
if (dst == NULL || src == NULL || search == NULL || replace == NULL) {
return -EINVAL;
}
search_size = strlen(search);
replace_size = strlen(replace);
c = 0;
for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
c++;
}
dst_size = strlen(src) + (replace_size - search_size) * c;
if (dst_size >= size) {
return -EINVAL;
}
q = src;
r = dst;
for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
memcpy(r, q, p - q);
r += p - q;
memcpy(r, replace, replace_size);
r += replace_size;
q = p + search_size;
}
memcpy(r, q, strlen(q));
r += strlen(q);
*r = '\0';
return 0;
}

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2017 Intel Corporation.
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*/
@ -436,6 +437,72 @@ test_strarray(void)
spdk_strarray_free(r2);
}
static void
test_strcpy_replace(void)
{
const char *original = "good morning, hello, thank you";
const char *search1 = "evening";
const char *replace1 = "unexpected";
const char *search2 = "morning";
const char *replace2 = "afternoon";
const char *expected2 = "good afternoon, hello, thank you";
const char *search3 = "morning";
const char *replace3 = "night";
const char *expected3 = "good night, hello, thank you";
const char *search4 = "hello";
const char *replace4 = "good bye";
const char *expected4 = "good morning, good bye, thank you";
const char *search5 = "thank you";
const char *replace5 = "you are welcome";
const char *expected5 = "good morning, hello, you are welcome";
const char *search6 = " ";
const char *replace6 = "-";
const char *expected6 = "good-morning,-hello,-thank-you";
const char *search7 = ",";
const char *replace7 = ".";
const char *expected7 = "good morning. hello. thank you";
char result[256];
int rc;
rc = spdk_strcpy_replace(NULL, 0, NULL, NULL, NULL);
CU_ASSERT(rc == -EINVAL);
rc = spdk_strcpy_replace(result, sizeof(result), original, search1, replace1);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, original) == 0);
rc = spdk_strcpy_replace(result, sizeof(result), original, search2, replace2);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected2) == 0);
/* A case that sizeof(replace) is less than sizeof(search), and the result array is
* smaller than the original string. */
rc = spdk_strcpy_replace(result, strlen(expected3) + 1, original, search3, replace3);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected3) == 0);
/* An error case that the result array is smaller than the string with replaced values
* and a terminated null byte. */
rc = spdk_strcpy_replace(result, strlen(expected3), original, search3, replace3);
CU_ASSERT(rc == -EINVAL);
rc = spdk_strcpy_replace(result, sizeof(result), original, search4, replace4);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected4) == 0);
rc = spdk_strcpy_replace(result, sizeof(result), original, search5, replace5);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected5) == 0);
rc = spdk_strcpy_replace(result, sizeof(result), original, search6, replace6);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected6) == 0);
rc = spdk_strcpy_replace(result, sizeof(result), original, search7, replace7);
CU_ASSERT(rc == 0);
CU_ASSERT(strcmp(result, expected7) == 0);
}
int
main(int argc, char **argv)
{
@ -454,6 +521,7 @@ main(int argc, char **argv)
CU_ADD_TEST(suite, test_strtol);
CU_ADD_TEST(suite, test_strtoll);
CU_ADD_TEST(suite, test_strarray);
CU_ADD_TEST(suite, test_strcpy_replace);
CU_basic_set_mode(CU_BRM_VERBOSE);