From 4ba0effa201030ae8f45597b29d4ca685b2d50a1 Mon Sep 17 00:00:00 2001 From: WATANABE Aoi <40206149+m12watanabe1a@users.noreply.github.com> Date: Wed, 1 May 2024 07:21:55 +0900 Subject: [PATCH] Implement `resize` function for String (#806) Signed-off-by: m12watanabe1a <40206149+m12watanabe1a@users.noreply.github.com> Signed-off-by: WATANABE Aoi <40206149+m12watanabe1a@users.noreply.github.com> --- .../rosidl_runtime_c/string_functions.h | 14 +++++++++++ rosidl_runtime_c/src/string_functions.c | 23 +++++++++++++++++++ .../test/test_string_functions.cpp | 12 ++++++++++ 3 files changed, 49 insertions(+) diff --git a/rosidl_runtime_c/include/rosidl_runtime_c/string_functions.h b/rosidl_runtime_c/include/rosidl_runtime_c/string_functions.h index 5f378220e..6f233944e 100644 --- a/rosidl_runtime_c/include/rosidl_runtime_c/string_functions.h +++ b/rosidl_runtime_c/include/rosidl_runtime_c/string_functions.h @@ -117,6 +117,20 @@ bool rosidl_runtime_c__String__assign( rosidl_runtime_c__String * str, const char * value); +/// Resize the char pointer. +/** + * This function resize the input value pointer. + * + * \param[inout] str a pointer to a rosidl_runtime_c__String structure + * \param[in] n the new size of the internal buffer + * \return true if successful, false if the passed string pointer is null + * or if the size is higher than SIZE_MAX or if the memory reallocation failed. + */ +ROSIDL_GENERATOR_C_PUBLIC +bool +rosidl_runtime_c__String__resize( + rosidl_runtime_c__String * str, size_t n); + /// Initialize a rosidl_runtime_c__String__Sequence__init structure. /** * The rosidl_runtime_c__String__Sequence is initialized with the size passed to the function. diff --git a/rosidl_runtime_c/src/string_functions.c b/rosidl_runtime_c/src/string_functions.c index ed44e6413..9bb6c60de 100644 --- a/rosidl_runtime_c/src/string_functions.c +++ b/rosidl_runtime_c/src/string_functions.c @@ -143,6 +143,29 @@ rosidl_runtime_c__String__copy( output, input->data, input->size); } +bool +rosidl_runtime_c__String__resize( + rosidl_runtime_c__String *str, size_t n) +{ + if(!str) { + return false; + } + // check valid range of n before allocating n + 1 characters + if(n > SIZE_MAX / sizeof(char) - 1) { + return false; + } + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + char * data = allocator.reallocate(str->data, (n + 1) * sizeof(char), allocator.state); + if(!data) { + return false; + } + data[n] = 0; + str->data = data; + str->size = n; + str->capacity = n + 1; + return true; +} + bool rosidl_runtime_c__String__Sequence__init( rosidl_runtime_c__String__Sequence * sequence, size_t size) diff --git a/rosidl_runtime_c/test/test_string_functions.cpp b/rosidl_runtime_c/test/test_string_functions.cpp index f3da91c58..0065c8dea 100644 --- a/rosidl_runtime_c/test/test_string_functions.cpp +++ b/rosidl_runtime_c/test/test_string_functions.cpp @@ -78,6 +78,18 @@ TEST(string_functions, resize_assignn) { EXPECT_TRUE(rosidl_runtime_c__String__init(&s)); EXPECT_TRUE(rosidl_runtime_c__String__init(&t)); + EXPECT_FALSE(rosidl_runtime_c__String__resize(nullptr, s_size)); + + // If you're here because this test crashed your computer, it might be because it just tried + // to allocate SIZE_MAX * 2 bytes, which means someone removed an important check. + EXPECT_FALSE(rosidl_runtime_c__String__resize(nullptr, SIZE_MAX * 2)); + + EXPECT_TRUE(rosidl_runtime_c__String__resize(&s, s_size)); + EXPECT_EQ(s.size, s_size); + EXPECT_EQ(s.capacity, s_size + 1u); + EXPECT_NE(s.data, nullptr); + EXPECT_EQ(s.data[s_size], 0); + EXPECT_FALSE(rosidl_runtime_c__String__assign(nullptr, nullptr)); EXPECT_FALSE(rosidl_runtime_c__String__assignn(nullptr, nullptr, 0)); EXPECT_FALSE(rosidl_runtime_c__String__assignn(&s, nullptr, 0));