diff --git a/dynmsg/CMakeLists.txt b/dynmsg/CMakeLists.txt index aa2075d..bb4b994 100644 --- a/dynmsg/CMakeLists.txt +++ b/dynmsg/CMakeLists.txt @@ -38,7 +38,6 @@ add_library(dynmsg STATIC src/message_reading_c.cpp src/message_reading_cpp.cpp src/typesupport.cpp - src/vector_utils.cpp src/string_utils.cpp src/yaml_utils.cpp ) @@ -89,9 +88,6 @@ if(BUILD_TESTING) ament_add_gtest(wide_strings test/test_wide_strings.cpp) target_link_libraries(wide_strings dynmsg) - ament_add_gtest(test_vector_utils test/test_vector_utils.cpp) - target_link_libraries(test_vector_utils dynmsg) - ament_add_gtest(test_typesupport test/test_typesupport.cpp) target_link_libraries(test_typesupport dynmsg) ament_target_dependencies(test_typesupport std_msgs) diff --git a/dynmsg/include/dynmsg/vector_utils.hpp b/dynmsg/include/dynmsg/vector_utils.hpp deleted file mode 100644 index 023250f..0000000 --- a/dynmsg/include/dynmsg/vector_utils.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Christophe Bedard -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef DYNMSG__VECTOR_UTILS_HPP_ -#define DYNMSG__VECTOR_UTILS_HPP_ - -#include -#include - -namespace dynmsg -{ - -/// Get the number of elements in/size of a vector given a pointer to it and its element size. -/** - * This uses some knowledge/assumption about the std::vector implementation. - * See the `get_vector_size` implementation for more info on how it works. - * - * Note that std::vector is a special optimized std::vector - * specialization and the "trick" used in get_vector_size() does not work. - */ -size_t get_vector_size(const uint8_t * vector, size_t element_size); - -} // namespace dynmsg - -#endif // DYNMSG__VECTOR_UTILS_HPP_ diff --git a/dynmsg/src/message_reading_c.cpp b/dynmsg/src/message_reading_c.cpp index a6bd289..1a3ae54 100644 --- a/dynmsg/src/message_reading_c.cpp +++ b/dynmsg/src/message_reading_c.cpp @@ -491,20 +491,12 @@ dynamic_array_to_yaml( array_node); break; case rosidl_typesupport_introspection_c__ROS_TYPE_MESSAGE: - // We do not know the specific type of the sequence because the type is not available at - // compile-time, but they all follow the same structure pattern, where a pointer to the data - // is first, followed by the element count, followed by the capacity RosMessage nested_member; nested_member.type_info = reinterpret_cast(member_info.members_->data); - uint8_t * element_data; - memcpy(&element_data, member_data, sizeof(void *)); - size_t element_size; - element_size = nested_member.type_info->size_of_; - size_t element_count; - element_count = static_cast(member_data[sizeof(void *)]); - for (size_t ii = 0; ii < element_count; ++ii) { - nested_member.data = element_data + ii * element_size; + for (size_t i = 0; i < member_info.size_function(member_data); i++) { // Recursively read the nested type into the array element in the YAML representation + nested_member.data = reinterpret_cast( + member_info.get_function(const_cast(member_data), i)); array_node.push_back(dynmsg::c::message_to_yaml(nested_member)); } break; diff --git a/dynmsg/src/message_reading_cpp.cpp b/dynmsg/src/message_reading_cpp.cpp index 072819c..ada9b3a 100644 --- a/dynmsg/src/message_reading_cpp.cpp +++ b/dynmsg/src/message_reading_cpp.cpp @@ -25,7 +25,6 @@ #include "dynmsg/message_reading.hpp" #include "dynmsg/string_utils.hpp" #include "dynmsg/typesupport.hpp" -#include "dynmsg/vector_utils.hpp" namespace dynmsg { @@ -516,21 +515,12 @@ dynamic_array_to_yaml( array_node); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE: - // We do not know the specific type of the sequence because the type is not available at - // compile-time, but we know it's a vector and we know the size of the contained type. RosMessage_Cpp nested_member; nested_member.type_info = reinterpret_cast(member_info.members_->data); - uint8_t * element_data; - memcpy(&element_data, member_data, sizeof(void *)); - size_t element_size; - element_size = nested_member.type_info->size_of_; - size_t element_count; - element_count = dynmsg::get_vector_size(member_data, element_size); - DYNMSG_DEBUG(std::cout << "\telement_size=" << element_size << std::endl); - DYNMSG_DEBUG(std::cout << "\telement_count=" << element_count << std::endl); - for (size_t ii = 0; ii < element_count; ++ii) { - nested_member.data = element_data + ii * element_size; + for (size_t i = 0; i < member_info.size_function(member_data); i++) { // Recursively read the nested type into the array element in the YAML representation + nested_member.data = reinterpret_cast( + member_info.get_function(const_cast(member_data), i)); array_node.push_back(message_to_yaml(nested_member)); } break; diff --git a/dynmsg/src/vector_utils.cpp b/dynmsg/src/vector_utils.cpp deleted file mode 100644 index f5b0312..0000000 --- a/dynmsg/src/vector_utils.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2021 Christophe Bedard -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include "dynmsg/vector_utils.hpp" - -/// Memory layout of an std::vector. -/** - * https://en.cppreference.com/w/cpp/container/vector - * https://stackoverflow.com/a/52337100 - */ -struct fake_vector -{ - void * begin; - void * end; - void * end_capacity; -}; - -union vector_union { - // The here doesn't matter because the memory - // layout (see fake_vector) is always the same. - std::vector * std; - fake_vector * fake; -}; - -namespace dynmsg -{ - -/** - * This uses the fact that std::vector is a contiguous container, therefore - * vector_size = (end - begin) / element_size - * - * This doesn't work for std::vector because that specialization - * is space-optimized and doesn't store its elements in a contiguous array, - * so that above gives a wildly invalid result. - */ -size_t get_vector_size(const uint8_t * vector, size_t element_size) -{ - // Should not get an element size of 0, but we want to avoid errors - if (0ul == element_size) { - return 0ul; - } - vector_union v = {reinterpret_cast *>(const_cast(vector))}; - return ( - reinterpret_cast(v.fake->end) - reinterpret_cast(v.fake->begin) - ) / element_size; -} - -} // namespace dynmsg diff --git a/dynmsg/test/test_vector_utils.cpp b/dynmsg/test/test_vector_utils.cpp deleted file mode 100644 index d2e44fa..0000000 --- a/dynmsg/test/test_vector_utils.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2021 Christophe Bedard -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include -#include - -#include "dynmsg/vector_utils.hpp" - -struct some_custom_object -{ - std::string str; - int i; - double d; - float f; -}; - -template -size_t _get_vector_size(std::vector & vector) -{ - return dynmsg::get_vector_size(reinterpret_cast(&vector), sizeof(T)); -} - -TEST(TestVectorUtils, get_vector_size) -{ - std::vector vector_string; - vector_string.push_back("abcdef"); - vector_string.push_back("hijklmnop"); - vector_string.push_back("qrstuv"); - vector_string.push_back("xyz"); - vector_string.push_back("1234567890"); - vector_string.push_back("09876543211234567890"); - EXPECT_EQ(6ul, _get_vector_size(vector_string)); - - std::vector vector_int; - vector_int.push_back(-4); - vector_int.push_back(20); - vector_int.push_back(6); - vector_int.push_back(9); - EXPECT_EQ(4ul, _get_vector_size(vector_int)); - - std::vector vector_custom; - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - vector_custom.push_back({}); - EXPECT_EQ(9ul, _get_vector_size(vector_custom)); - - // Special case, but it shouldn't happen - std::vector vector_void; - EXPECT_EQ(0ul, _get_vector_size(vector_void)); -}