Commit d6e57b53 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

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: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: I3ca9774d0bfb2d0bb7bd7412bc671e6f69104b7d
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16054


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 60fd5c55
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+17 −0
Original line number Diff line number Diff line
/*   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
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@
	spdk_strarray_from_string;
	spdk_strarray_dup;
	spdk_strarray_free;
	spdk_strcpy_replace;

	# public functions in util.h
	spdk_u32log2;
+47 −0
Original line number Diff line number Diff line
/*   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;
}
+68 −0
Original line number Diff line number Diff line
/*   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);