Skip to content

Commit

Permalink
Implement type name string replacement
Browse files Browse the repository at this point in the history
Signed-off-by: methylDragon <methylDragon@gmail.com>
  • Loading branch information
methylDragon committed Mar 24, 2023
1 parent 48c8dbb commit 4155c36
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -604,11 +604,53 @@ ROSIDL_GENERATOR_C_PUBLIC
rcutils_ret_t
rosidl_runtime_c_type_description_utils_get_referenced_type_description_as_type_description(
const rosidl_runtime_c__type_description__IndividualTypeDescription__Sequence *
referenced_descriptions,
referenced_descriptions,
const rosidl_runtime_c__type_description__IndividualTypeDescription * referenced_description,
rosidl_runtime_c__type_description__TypeDescription ** output_description,
bool coerce_to_valid);

// Create a type description from a referenced description, then validate if coerce_to_valid is true
// This is done by copy!! This allocates memory and the caller is responsible for deallocating the
// output
ROSIDL_GENERATOR_C_PUBLIC
rcutils_ret_t
rosidl_runtime_c_type_description_utils_get_referenced_type_description_as_type_description(
const rosidl_runtime_c__type_description__IndividualTypeDescription__Sequence *
referenced_descriptions,
const rosidl_runtime_c__type_description__IndividualTypeDescription * referenced_description,
rosidl_runtime_c__type_description__TypeDescription ** output_description,
bool coerce_to_valid);

/// In-place replace substrings in an individual description's type name and nested names in fields
/**
* This means the `IndividualTypeDescription`'s' type_name will get replaced and all references
* to any nested_type_names in the description's fields.
*
* NOTE(methylDragon): This method is pretty inefficient because it doesn't do checking and will
* re-copy all names.
*/
ROSIDL_GENERATOR_C_PUBLIC
rcutils_ret_t
rosidl_runtime_c_type_description_utils_repl_individual_type_description_type_names_in_place(
rosidl_runtime_c__type_description__IndividualTypeDescription * individual_type_description,
const char * from,
const char * to);


/// In-place replace substrings across all type names (and references to those names)
/**
* This means all `IndividualTypeDescription` type_names will get replaced, in the main description
* and referenced type descriptions, and also all references to those names (nested_type_name.)
*
* NOTE(methylDragon): This method is pretty inefficient because it doesn't do checking and will
* re-copy all names.
*/
ROSIDL_GENERATOR_C_PUBLIC
rcutils_ret_t
rosidl_runtime_c_type_description_utils_repl_all_type_description_type_names_in_place(
rosidl_runtime_c__type_description__TypeDescription * type_description,
const char * from,
const char * to);

// =================================================================================================
// DESCRIPTION PRINTING
Expand Down
108 changes: 106 additions & 2 deletions rosidl_runtime_c/src/type_description_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <string.h>

#include <rcutils/logging_macros.h>
#include <rcutils/repl_str.h>
#include <rcutils/qsort.h>
#include <rcutils/types/rcutils_ret.h>
#include <rcutils/types/hash_map.h>
Expand Down Expand Up @@ -1233,7 +1234,7 @@ rosidl_runtime_c_type_description_utils_append_referenced_type_description(
rcutils_ret_t
rosidl_runtime_c_type_description_utils_get_referenced_type_description_as_type_description(
const rosidl_runtime_c__type_description__IndividualTypeDescription__Sequence *
referenced_descriptions,
referenced_descriptions,
const rosidl_runtime_c__type_description__IndividualTypeDescription * referenced_description,
rosidl_runtime_c__type_description__TypeDescription ** output_description,
bool coerce_to_valid)
Expand Down Expand Up @@ -1272,7 +1273,7 @@ rosidl_runtime_c_type_description_utils_get_referenced_type_description_as_type_
if (coerce_to_valid) {
rcutils_ret_t ret =
rosidl_runtime_c_type_description_utils_coerce_to_valid_type_description_in_place(
*output_description);
*output_description);
if (ret != RCUTILS_RET_OK) {
RCUTILS_LOG_ERROR("Could not coerce output type description to valid");
rosidl_runtime_c__type_description__TypeDescription__destroy(*output_description);
Expand All @@ -1284,6 +1285,109 @@ rosidl_runtime_c_type_description_utils_get_referenced_type_description_as_type_
}


rcutils_ret_t
rosidl_runtime_c_type_description_utils_repl_individual_type_description_type_names_in_place(
rosidl_runtime_c__type_description__IndividualTypeDescription * individual_type_description,
const char * from,
const char * to)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(individual_type_description, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ARGUMENT_FOR_NULL(from, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ARGUMENT_FOR_NULL(to, RCUTILS_RET_INVALID_ARGUMENT);

rcutils_allocator_t allocator = rcutils_get_default_allocator();
bool ret = false;
char * repl = NULL;

// Replace type name
repl = rcutils_repl_str(
individual_type_description->type_name.data, from, to, &allocator);
if (repl == NULL) {
RCUTILS_LOG_ERROR("Could not replace individual type description type name");
return RCUTILS_RET_ERROR;
}

ret = rosidl_runtime_c__String__assign(&(individual_type_description->type_name), repl);
allocator.deallocate(repl, allocator.state);
if (!ret) {
RCUTILS_LOG_ERROR("Could not assign individual type description type name");
return RCUTILS_RET_ERROR;
}

// Replace field nested type names
rosidl_runtime_c__type_description__Field * field = NULL;
if (individual_type_description->fields.data) {
for (size_t i = 0; i < individual_type_description->fields.size; i++) {
field = &individual_type_description->fields.data[i];
if (!field->type.nested_type_name.size) {
continue;
}

repl = rcutils_repl_str(field->type.nested_type_name.data, from, to, &allocator);
if (repl == NULL) {
RCUTILS_LOG_ERROR(
"Could not replace individual type description field nested type name. Beware! "
"Partial in-place replacements might have already happened!");
return RCUTILS_RET_ERROR;
}

ret = rosidl_runtime_c__String__assign(&(field->type.nested_type_name), repl);
allocator.deallocate(repl, allocator.state);
if (!ret) {
RCUTILS_LOG_ERROR(
"Could not assign individual type description field nested type name. Beware! "
"Partial in-place replacements might have already happened!");
return RCUTILS_RET_ERROR;
}
}
}
return RCUTILS_RET_OK;
}


rcutils_ret_t
rosidl_runtime_c_type_description_utils_repl_all_type_description_type_names_in_place(
rosidl_runtime_c__type_description__TypeDescription * type_description,
const char * from,
const char * to)
{
RCUTILS_CHECK_ARGUMENT_FOR_NULL(type_description, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ARGUMENT_FOR_NULL(from, RCUTILS_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ARGUMENT_FOR_NULL(to, RCUTILS_RET_INVALID_ARGUMENT);

rcutils_ret_t end_ret = RCUTILS_RET_ERROR;

end_ret =
rosidl_runtime_c_type_description_utils_repl_individual_type_description_type_names_in_place(
&type_description->type_description, from, to);
if (end_ret != RCUTILS_RET_OK) {
RCUTILS_LOG_ERROR("Could not replace main type description type name");
return end_ret;
}

if (type_description->referenced_type_descriptions.data) {
for (size_t i = 0; i < type_description->referenced_type_descriptions.size; i++) {
rosidl_runtime_c__type_description__IndividualTypeDescription * individual_type_description =
&type_description->referenced_type_descriptions.data[i];

/* *INDENT-OFF* */ // Uncrustify will dislodge the NOLINT
end_ret =
rosidl_runtime_c_type_description_utils_repl_individual_type_description_type_names_in_place( // NOLINT
individual_type_description, from, to);
/* *INDENT-ON* */

if (end_ret != RCUTILS_RET_OK) {
RCUTILS_LOG_ERROR(
"Could not replace type names in referenced type. Beware! "
"Partial in-place replacements might have already happened!");
return end_ret;
}
}
}
return RCUTILS_RET_OK;
}


// =================================================================================================
// DESCRIPTION PRINTING
// =================================================================================================
Expand Down
19 changes: 13 additions & 6 deletions rosidl_runtime_c/test/test_type_description_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <rcutils/types/rcutils_ret.h>
#include <rcutils/types/hash_map.h>

#include "rosidl_runtime_c/type_description/field__functions.h"
#include "rosidl_runtime_c/type_description/field__struct.h"
#include "rosidl_runtime_c/type_description/individual_type_description__functions.h"
#include "rosidl_runtime_c/type_description/individual_type_description__struct.h"
#include "rosidl_runtime_c/type_description/type_description__functions.h"
#include "rosidl_runtime_c/type_description/type_description__struct.h"
#include "rosidl_runtime_c/type_description_utils.h"

#include <rcutils/types/rcutils_ret.h>
#include <rcutils/types/hash_map.h>
#include <rosidl_runtime_c/string_functions.h>

#include <stdlib.h>
Expand Down Expand Up @@ -127,7 +127,7 @@ TEST(TestUtils, test_basic_construction)
}


class TestUtilsFixture: public ::testing::Test
class TestUtilsFixture : public ::testing::Test
{
public:
void SetUp()
Expand Down Expand Up @@ -374,8 +374,15 @@ TEST_F(TestUtilsFixture, test_appends_and_advanced_construction)
EXPECT_TRUE(
rosidl_runtime_c__type_description__IndividualTypeDescription__are_equal(
&subset_desc_2->referenced_type_descriptions.data[0], empty_individual_desc));
// rosidl_runtime_c_type_description_utils_print_type_description(type_description_1);
// rosidl_runtime_c_type_description_utils_print_type_description(subset_desc_2);

// Test type name string replacements
ret = rosidl_runtime_c_type_description_utils_repl_all_type_description_type_names_in_place(
subset_desc_2, "mpty", "ligibility" // Expect eligibility
);
EXPECT_EQ(ret, RCUTILS_RET_OK);
EXPECT_FALSE(
rosidl_runtime_c__type_description__IndividualTypeDescription__are_equal(
&subset_desc_2->referenced_type_descriptions.data[0], empty_individual_desc));
rosidl_runtime_c__type_description__TypeDescription__destroy(subset_desc_2);
}

Expand Down

0 comments on commit 4155c36

Please sign in to comment.