From 5d3461cf416150c36a530524846bac2784947150 Mon Sep 17 00:00:00 2001 From: Alexander Sherikov Date: Tue, 4 Jun 2024 23:19:54 +0400 Subject: [PATCH] ros2param WIP --- .github/workflows/head_2.yml | 37 +- .github/workflows/tag.yml | 4 +- CMakeLists.txt | 2 +- Makefile | 5 + cmake/cmakeut_compiler_flags.cmake | 2 + cmake/options_deb_packages_bionic.cmake | 1 + cmake/options_deb_packages_focal.cmake | 1 + cmake/options_deb_packages_jammy.cmake | 1 + cmake/options_deb_packages_xenial.cmake | 1 + cmake/options_default.cmake | 2 +- cmake/options_noros.cmake | 3 +- cmake/options_noros_tidy.cmake | 3 +- cmake/options_noros_xenial.cmake | 3 +- cmake/options_ros.cmake | 3 +- cmake/options_ros2.cmake | 7 + cmake/options_ros2_tidy.cmake | 8 + cmake/options_ros_tidy.cmake | 3 +- extra_visitors/msgpack/src/reader.cpp | 2 +- extra_visitors/msgpack/src/reader_compact.cpp | 4 +- .../ariles2/visitors/namevalue/writer.h | 2 +- extra_visitors/octave/src/writer.cpp | 4 +- extra_visitors/pugixml/src/reader.cpp | 2 +- extra_visitors/pugixml/src/writer.cpp | 2 +- extra_visitors/rapidjson/src/reader.cpp | 2 +- extra_visitors/rapidjson/src/writer.cpp | 2 +- extra_visitors/ros2param/CMakeLists.txt | 21 + .../ros2param/ariles2/visitors/ros2param.h | 43 ++ .../ariles2/visitors/ros2param/reader.h | 65 +++ .../ariles2/visitors/ros2param/writer.h | 53 +++ extra_visitors/ros2param/src/reader.cpp | 437 ++++++++++++++++++ extra_visitors/ros2param/src/writer.cpp | 299 ++++++++++++ extra_visitors/rosparam/src/reader.cpp | 2 +- extra_visitors/rosparam/src/writer.cpp | 2 +- extra_visitors/yaml_cpp/src/reader.cpp | 2 +- include/ariles2/internal/helpers.h | 11 +- include/ariles2/types.h | 6 +- include/ariles2/visitors/common.h | 119 +---- include/ariles2/visitors/serialization.h | 4 +- qa/scspell.dict | 2 + tests/CMakeLists.txt | 2 +- tests/api_v2/all_enabled_visitors.h | 4 + tests/api_v2/fixtures/initializers.h | 61 +++ tests/api_v2/instantiate.h | 4 + tests/api_v2/regression_test_210.cpp | 1 + tests/api_v2/regression_test_215.cpp | 1 + tests/api_v2/regression_test_223.cpp | 1 + tests/api_v2/regression_test_224.cpp | 1 + 47 files changed, 1112 insertions(+), 135 deletions(-) create mode 100644 cmake/options_ros2.cmake create mode 100644 cmake/options_ros2_tidy.cmake create mode 100644 extra_visitors/ros2param/CMakeLists.txt create mode 100644 extra_visitors/ros2param/ariles2/visitors/ros2param.h create mode 100644 extra_visitors/ros2param/ariles2/visitors/ros2param/reader.h create mode 100644 extra_visitors/ros2param/ariles2/visitors/ros2param/writer.h create mode 100644 extra_visitors/ros2param/src/reader.cpp create mode 100644 extra_visitors/ros2param/src/writer.cpp diff --git a/.github/workflows/head_2.yml b/.github/workflows/head_2.yml index 345dc106..52ef8b2f 100644 --- a/.github/workflows/head_2.yml +++ b/.github/workflows/head_2.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-deps - run: $APT fakeroot devscripts build-essential - run: | @@ -30,7 +30,7 @@ jobs: ROS_CI_DESKTOP: focal steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP - run: rosdep update - run: sudo make install-deps @@ -45,7 +45,7 @@ jobs: clang_noros: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt update - run: sudo make install-deps - run: make build-tests TYPE=Debug OPTIONS=noros TARGETS="all" TC=clang ARGS=-V @@ -54,16 +54,33 @@ jobs: jammy_gcc_noros: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt update - run: sudo make install-deps - run: make build-tests TYPE=Debug OPTIONS=noros TARGETS="all" TC=gcc ARGS=-V + jammy_gcc_ros: + runs-on: ubuntu-22.04 + + env: + ROS_DISTRO: humble + ROS_HOSTNAME: localhost + ROS_CI_DESKTOP: jammy + + steps: + - uses: actions/checkout@v4 + - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP + - run: rosdep update + - run: sudo make install-deps + - run: | + source /opt/ros/$ROS_DISTRO/setup.bash + make build-tests TYPE=Debug OPTIONS=ros2 TARGETS="all" TC=gcc ARGS=-V + focal_gcc_noros: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt update - run: sudo make install-deps - run: make build-tests TYPE=Debug OPTIONS=noros TARGETS="all" TC=gcc ARGS=-V @@ -78,7 +95,7 @@ jobs: ROS_CI_DESKTOP: focal steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP - run: rosdep update - run: sudo make install-deps @@ -96,7 +113,7 @@ jobs: ROS_CI_DESKTOP: focal steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP - run: rosdep update - run: sudo make install-deps @@ -109,7 +126,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt update - run: $APT cppcheck - run: $APT python3-pip python3-setuptools @@ -127,7 +144,7 @@ jobs: ROS_CI_DESKTOP: focal steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP - run: rosdep update - run: sudo make install-deps @@ -141,7 +158,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt update - run: sudo make install-deps - run: $APT clang-tools-14 clang-tidy-14 diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index fcda4aa7..abf5f46f 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -18,7 +18,7 @@ jobs: DEB_TARGET: jammy steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-deps - run: $APT fakeroot devscripts build-essential - run: make deb-build DEB_TARGET=$DEB_TARGET @@ -36,7 +36,7 @@ jobs: DEB_TARGET: focal steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo make install-ros ROS_DISTRO=$ROS_DISTRO UBUNTU_DISTRO=$ROS_CI_DESKTOP - run: rosdep update - run: sudo make install-deps diff --git a/CMakeLists.txt b/CMakeLists.txt index 49ab86e8..3ad4332a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ option (ARILES_VERBOSE "Verbose build" ON) option (ARILES_BUILD_REGRESSION_TESTS "Build regression tests." ON) option (ARILES_CCACHE "Enable ccache if available" ON) set (ARILES_DEB_TARGETS "" CACHE STRING "Enable debian package generation.") -set (ARILES_CPP_STANDARD "11" CACHE STRING "14 is required for boost >= 1.82, 11 is still ok for ariles") +set (ARILES_CPP_STANDARD "17" CACHE STRING "must not be older than 17") # install parameters set (ARILES_PKGCONFIG_INSTALL_PATH "" CACHE STRING "pkg-config pc-file install path, not installed if empty") diff --git a/Makefile b/Makefile index e67cf3b8..ff2a68db 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,11 @@ test-ros: clean ${MAKE} build-tests TC=${TC} TYPE=Debug OPTIONS=ros TARGETS="${TARGETS}" EXTRA_CMAKE_PARAM="${EXTRA_CMAKE_PARAM}" +test-ros2: clean + #${MAKE} build-tests TC=${TC} TYPE=Debug OPTIONS=default TARGETS="${TARGETS}" EXTRA_CMAKE_PARAM="${EXTRA_CMAKE_PARAM}" + ${MAKE} build-tests TC=${TC} TYPE=Debug OPTIONS=ros2 TARGETS="${TARGETS}" EXTRA_CMAKE_PARAM="${EXTRA_CMAKE_PARAM}" + + test-noros: clean ${MAKE} build-tests TC=${TC} TYPE=Debug OPTIONS=noros TARGETS="${TARGETS}" EXTRA_CMAKE_PARAM="${EXTRA_CMAKE_PARAM}" ${MAKE} clangcheck SCANBUILD=scan-build15 OPTIONS=noros_tidy diff --git a/cmake/cmakeut_compiler_flags.cmake b/cmake/cmakeut_compiler_flags.cmake index 6d9e5195..1da76184 100644 --- a/cmake/cmakeut_compiler_flags.cmake +++ b/cmake/cmakeut_compiler_flags.cmake @@ -91,6 +91,8 @@ function(cmakeut_compiler_flags STANDARD) set(CMAKE_CXX_CLANG_TIDY "${CMAKE_CXX_CLANG_TIDY},-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay") # long functions are ok set(CMAKE_CXX_CLANG_TIDY "${CMAKE_CXX_CLANG_TIDY},-google-readability-function-size,-readability-function-size,-hicpp-function-size") + # do not enforce nested namespace concatenation + set(CMAKE_CXX_CLANG_TIDY "${CMAKE_CXX_CLANG_TIDY},-modernize-concat-nested-namespaces") # overly restrictive fuchsia stuff diff --git a/cmake/options_deb_packages_bionic.cmake b/cmake/options_deb_packages_bionic.cmake index e4152a5e..36d64ae0 100644 --- a/cmake/options_deb_packages_bionic.cmake +++ b/cmake/options_deb_packages_bionic.cmake @@ -5,3 +5,4 @@ set(ARILES_BUILD_REGRESSION_TESTS "OFF" CACHE STRING "") set(ARILES_VISITORS_DEFAULT_MODE "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "$ENV{ROS_DISTRO}" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_deb_packages_focal.cmake b/cmake/options_deb_packages_focal.cmake index 9b43f264..9be67f94 100644 --- a/cmake/options_deb_packages_focal.cmake +++ b/cmake/options_deb_packages_focal.cmake @@ -6,3 +6,4 @@ set(ARILES_BUILD_REGRESSION_TESTS "OFF" CACHE STRING "") set(ARILES_VISITORS_DEFAULT_MODE "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "$ENV{ROS_DISTRO}" CACHE STRING "") set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_deb_packages_jammy.cmake b/cmake/options_deb_packages_jammy.cmake index 280aca58..5a4ca904 100644 --- a/cmake/options_deb_packages_jammy.cmake +++ b/cmake/options_deb_packages_jammy.cmake @@ -5,3 +5,4 @@ set(ARILES_BUILD_REGRESSION_TESTS "OFF" CACHE STRING "") set(ARILES_VISITORS_DEFAULT_MODE "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "$ENV{ROS_DISTRO}" CACHE STRING "") diff --git a/cmake/options_deb_packages_xenial.cmake b/cmake/options_deb_packages_xenial.cmake index 45ea3d67..09b8983a 100644 --- a/cmake/options_deb_packages_xenial.cmake +++ b/cmake/options_deb_packages_xenial.cmake @@ -6,3 +6,4 @@ set(ARILES_VISITORS_DEFAULT_MODE "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "$ENV{ROS_DISTRO}" CACHE STRING "") set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_default.cmake b/cmake/options_default.cmake index f9483459..344c225a 100644 --- a/cmake/options_default.cmake +++ b/cmake/options_default.cmake @@ -1 +1 @@ -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") diff --git a/cmake/options_noros.cmake b/cmake/options_noros.cmake index 024a3db0..10feaa62 100644 --- a/cmake/options_noros.cmake +++ b/cmake/options_noros.cmake @@ -1,4 +1,4 @@ -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") set(ARILES_VISITOR_graphviz "ON" CACHE STRING "") set(ARILES_VISITOR_pugixml "ON" CACHE STRING "") @@ -7,3 +7,4 @@ set(ARILES_VISITOR_jsonnet "ON" CACHE STRING "") set(ARILES_VISITOR_msgpack "ON" CACHE STRING "") set(ARILES_VISITOR_yaml_cpp "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_noros_tidy.cmake b/cmake/options_noros_tidy.cmake index 0d036799..3a2492b8 100644 --- a/cmake/options_noros_tidy.cmake +++ b/cmake/options_noros_tidy.cmake @@ -1,4 +1,4 @@ -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") set(ARILES_CPP_CLANG_TIDY "ON" CACHE STRING "") set(ARILES_VISITOR_graphviz "ON" CACHE STRING "") @@ -8,3 +8,4 @@ set(ARILES_VISITOR_jsonnet "ON" CACHE STRING "") set(ARILES_VISITOR_msgpack "ON" CACHE STRING "") set(ARILES_VISITOR_yaml_cpp "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_noros_xenial.cmake b/cmake/options_noros_xenial.cmake index e735c7b6..58e279e0 100644 --- a/cmake/options_noros_xenial.cmake +++ b/cmake/options_noros_xenial.cmake @@ -1,7 +1,7 @@ #- rapidjson-dev # not found #- libmsgpack-dev # version is too old -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") set(ARILES_VISITOR_graphviz "ON" CACHE STRING "") set(ARILES_VISITOR_pugixml "ON" CACHE STRING "") @@ -10,3 +10,4 @@ set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") set(ARILES_VISITOR_yaml_cpp "ON" CACHE STRING "") set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_ros.cmake b/cmake/options_ros.cmake index f7489f45..a68315aa 100644 --- a/cmake/options_ros.cmake +++ b/cmake/options_ros.cmake @@ -1,6 +1,7 @@ -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") set(ARILES_VISITOR_pugixml "OFF" CACHE STRING "") set(ARILES_VISITOR_rapidjson "OFF" CACHE STRING "") set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/cmake/options_ros2.cmake b/cmake/options_ros2.cmake new file mode 100644 index 00000000..5fb46b7a --- /dev/null +++ b/cmake/options_ros2.cmake @@ -0,0 +1,7 @@ +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") + +set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") +set(ARILES_VISITOR_pugixml "OFF" CACHE STRING "") +set(ARILES_VISITOR_rapidjson "OFF" CACHE STRING "") +set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") +set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") diff --git a/cmake/options_ros2_tidy.cmake b/cmake/options_ros2_tidy.cmake new file mode 100644 index 00000000..b0fb455d --- /dev/null +++ b/cmake/options_ros2_tidy.cmake @@ -0,0 +1,8 @@ +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +set(ARILES_CPP_CLANG_TIDY "ON" CACHE STRING "") + +set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") +set(ARILES_VISITOR_pugixml "OFF" CACHE STRING "") +set(ARILES_VISITOR_rapidjson "OFF" CACHE STRING "") +set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") +set(ARILES_VISITOR_rosparam "OFF" CACHE STRING "") diff --git a/cmake/options_ros_tidy.cmake b/cmake/options_ros_tidy.cmake index f007d4ed..c4a017fa 100644 --- a/cmake/options_ros_tidy.cmake +++ b/cmake/options_ros_tidy.cmake @@ -1,7 +1,8 @@ -set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") +#set(ARILES_CPP_SANITIZERS "ON" CACHE STRING "") set(ARILES_CPP_CLANG_TIDY "ON" CACHE STRING "") set(ARILES_VISITOR_msgpack "OFF" CACHE STRING "") set(ARILES_VISITOR_pugixml "OFF" CACHE STRING "") set(ARILES_VISITOR_rapidjson "OFF" CACHE STRING "") set(ARILES_VISITOR_jsonnet "OFF" CACHE STRING "") +set(ARILES_VISITOR_ros2param "OFF" CACHE STRING "") diff --git a/extra_visitors/msgpack/src/reader.cpp b/extra_visitors/msgpack/src/reader.cpp index d985f750..c20b3c03 100644 --- a/extra_visitors/msgpack/src/reader.cpp +++ b/extra_visitors/msgpack/src/reader.cpp @@ -202,7 +202,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } diff --git a/extra_visitors/msgpack/src/reader_compact.cpp b/extra_visitors/msgpack/src/reader_compact.cpp index bbf41bc3..0687decd 100644 --- a/extra_visitors/msgpack/src/reader_compact.cpp +++ b/extra_visitors/msgpack/src/reader_compact.cpp @@ -141,7 +141,7 @@ namespace ariles2 void Reader::endMap() { ARILES2_ASSERT( - impl_->node_stack_.back().isAllParsed(), + impl_->node_stack_.back().isCompleted(), "Some entries were not parsed, which is not allowed by this visitor."); impl_->node_stack_.pop_back(); } @@ -166,7 +166,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } diff --git a/extra_visitors/namevalue/ariles2/visitors/namevalue/writer.h b/extra_visitors/namevalue/ariles2/visitors/namevalue/writer.h index 6cdc184b..2c0963c8 100644 --- a/extra_visitors/namevalue/ariles2/visitors/namevalue/writer.h +++ b/extra_visitors/namevalue/ariles2/visitors/namevalue/writer.h @@ -153,7 +153,7 @@ namespace ariles2 std::string node; if (node_stack_.back().isArray()) { - node.reserve(node_stack_.back().node_.size() + map_name.size() + 15); + node.reserve(node_stack_.back().node_.size() + map_name.size() + num_chars_for_index_reserve + 3); node = node_stack_.back().node_; node += "{"; diff --git a/extra_visitors/octave/src/writer.cpp b/extra_visitors/octave/src/writer.cpp index 8d6f7ba4..914416f0 100644 --- a/extra_visitors/octave/src/writer.cpp +++ b/extra_visitors/octave/src/writer.cpp @@ -124,7 +124,7 @@ namespace ariles2 std::string node; if (impl_->node_stack_.back().isArray()) { - node.reserve(impl_->node_stack_.back().node_.size() + map_name.size() + 15); + node.reserve(impl_->node_stack_.back().node_.size() + map_name.size() + num_chars_for_index_reserve + 3); node = impl_->node_stack_.back().node_; node += "{"; @@ -153,7 +153,7 @@ namespace ariles2 if (impl_->node_stack_.back().isArray()) { std::string node; - node.reserve(impl_->node_stack_.back().node_.size() + 15); + node.reserve(impl_->node_stack_.back().node_.size() + num_chars_for_index_reserve + 2); node = impl_->node_stack_.back().node_; node += "{"; node += boost::lexical_cast(impl_->node_stack_.back().index_ + 1); diff --git a/extra_visitors/pugixml/src/reader.cpp b/extra_visitors/pugixml/src/reader.cpp index 49fc98a4..abc31798 100644 --- a/extra_visitors/pugixml/src/reader.cpp +++ b/extra_visitors/pugixml/src/reader.cpp @@ -166,7 +166,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } diff --git a/extra_visitors/pugixml/src/writer.cpp b/extra_visitors/pugixml/src/writer.cpp index 6048f3ba..9b6c46a4 100644 --- a/extra_visitors/pugixml/src/writer.cpp +++ b/extra_visitors/pugixml/src/writer.cpp @@ -107,7 +107,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); impl_->node_stack_.emplace_back(impl_->getRawNode().append_child("item")); } diff --git a/extra_visitors/rapidjson/src/reader.cpp b/extra_visitors/rapidjson/src/reader.cpp index e66b433f..4ac86f9c 100644 --- a/extra_visitors/rapidjson/src/reader.cpp +++ b/extra_visitors/rapidjson/src/reader.cpp @@ -149,7 +149,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } diff --git a/extra_visitors/rapidjson/src/writer.cpp b/extra_visitors/rapidjson/src/writer.cpp index c3c14d96..3dba2934 100644 --- a/extra_visitors/rapidjson/src/writer.cpp +++ b/extra_visitors/rapidjson/src/writer.cpp @@ -122,7 +122,7 @@ namespace ariles2 ARILES2_TRACE_FUNCTION; ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } void Writer::endArrayElement() diff --git a/extra_visitors/ros2param/CMakeLists.txt b/extra_visitors/ros2param/CMakeLists.txt new file mode 100644 index 00000000..0fdfbcff --- /dev/null +++ b/extra_visitors/ros2param/CMakeLists.txt @@ -0,0 +1,21 @@ +set (TGT_ARILES_VISITOR_LIB "${PROJECT_NAME}_visitor_${ARILES_VISITOR}") + +if(NOT ARILES_DEB_TARGETS) + cmake_policy(SET CMP0057 NEW) # Support new ``if()`` IN_LIST operator. + find_package(rclcpp REQUIRED) +endif() + +add_library(${TGT_ARILES_VISITOR_LIB} + ${ARILES_VISITOR_${ARILES_VISITOR}_DIR}/src/reader.cpp + ${ARILES_VISITOR_${ARILES_VISITOR}_DIR}/src/writer.cpp +) + +if(NOT ARILES_DEB_TARGETS) + target_link_libraries(${TGT_ARILES_VISITOR_LIB} PUBLIC + rclcpp::rclcpp + ) +endif() + +include(ariles_install_component) +set(ARILES_ROS_DISTRO "${ARILES_VISITOR_ros2param}") +set(DEB_${ARILES_COMPONENT}_DEPENDS "ros-${ARILES_ROS_DISTRO}-rclcpp") diff --git a/extra_visitors/ros2param/ariles2/visitors/ros2param.h b/extra_visitors/ros2param/ariles2/visitors/ros2param.h new file mode 100644 index 00000000..d8359f9d --- /dev/null +++ b/extra_visitors/ros2param/ariles2/visitors/ros2param.h @@ -0,0 +1,43 @@ +/** + @file + @author Alexander Sherikov + + @copyright 2018-2020 Alexander Sherikov, Licensed under the Apache License, Version 2.0. + (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0) + + @brief +*/ + +/** +@defgroup ros2param ROS +@ingroup config + +@brief ROS parameter server serialization. +*/ + + +#pragma once + +#define ARILES2_VISITOR_INCLUDED_ros2param + +#include +#include + +#include + + +#include "./ros2param/reader.h" +#include "./ros2param/writer.h" + +namespace ariles2 +{ + /** + * @brief ROS parameter server visitor. + * @ingroup ros2param + */ + struct ARILES2_VISIBILITY_ATTRIBUTE ros2param + { + using Reader = ariles2::cfgread::Visitor; + using Writer = ariles2::cfgwrite::Visitor; + }; +} // namespace ariles2 diff --git a/extra_visitors/ros2param/ariles2/visitors/ros2param/reader.h b/extra_visitors/ros2param/ariles2/visitors/ros2param/reader.h new file mode 100644 index 00000000..2c216755 --- /dev/null +++ b/extra_visitors/ros2param/ariles2/visitors/ros2param/reader.h @@ -0,0 +1,65 @@ +/** + @file + @author Alexander Sherikov + + @copyright 2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0. + (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0) + + @brief +*/ + +#pragma once + + +namespace ariles2 +{ + namespace ns_ros2param + { + namespace impl + { + class ARILES2_VISIBILITY_ATTRIBUTE Reader; + } + + + + /** + * @brief Configuration reader class + */ + class ARILES2_VISIBILITY_ATTRIBUTE Reader : public serialization::PIMPLVisitor + { + public: + /** + * @brief Constructor + * + * @param[in] nh NodeHandle + */ + explicit Reader(const ::rclcpp::Node *nh); + + + bool startMapEntry(const std::string &child_name); + void endMapEntry(); + + + bool startIteratedMap( + const SizeLimitEnforcementType /*limit_type*/ = SIZE_LIMIT_NONE, + const std::size_t /*min*/ = 0, + const std::size_t /*max*/ = 0); + bool startIteratedMapElement(std::string &entry_name); + void endIteratedMapElement(); + void endIteratedMap(); + + + std::size_t startArray(); + void startArrayElement(); + void endArrayElement(); + void endArray(); + + +#define ARILES2_BASIC_TYPE(type) void readElement(type &element); + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + }; + } // namespace ns_ros2param +} // namespace ariles2 diff --git a/extra_visitors/ros2param/ariles2/visitors/ros2param/writer.h b/extra_visitors/ros2param/ariles2/visitors/ros2param/writer.h new file mode 100644 index 00000000..0708b5bd --- /dev/null +++ b/extra_visitors/ros2param/ariles2/visitors/ros2param/writer.h @@ -0,0 +1,53 @@ +/** + @file + @author Alexander Sherikov + + @copyright 2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0. + (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0) + + @brief +*/ + +#pragma once + + +namespace ariles2 +{ + namespace ns_ros2param + { + namespace impl + { + class ARILES2_VISIBILITY_ATTRIBUTE Writer; + } + + + + /** + * @brief Configuration writer class + */ + class ARILES2_VISIBILITY_ATTRIBUTE Writer : public serialization::PIMPLVisitor + { + public: + explicit Writer(::rclcpp::Node *nh); + + + void flush(); + + + void startMapEntry(const std::string &child_name); + void endMapEntry(); + + void startArray(const std::size_t size, const bool /*compact*/ = false); + void startArrayElement(); + void endArrayElement(); + void endArray(); + + +#define ARILES2_BASIC_TYPE(type) void writeElement(const type &element, const Parameters ¶m); + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + }; + } // namespace ns_ros2param +} // namespace ariles2 diff --git a/extra_visitors/ros2param/src/reader.cpp b/extra_visitors/ros2param/src/reader.cpp new file mode 100644 index 00000000..f2b50b82 --- /dev/null +++ b/extra_visitors/ros2param/src/reader.cpp @@ -0,0 +1,437 @@ +/** + @file + @author Alexander Sherikov + + @copyright 2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0. + (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0) + + @brief +*/ + +#include + +#include + + +namespace ariles2 +{ + namespace ns_ros2param + { + class ReaderNodeWrapper : public serialization::Node + { + protected: + using Parent = serialization::Node; + + protected: + std::vector childs_; + const rclcpp::Parameter parameter_; + const bool is_builtin_array_ = false; + + public: + using Parent::Parent; + + ReaderNodeWrapper(const std::string &name, const std::vector &&childs) + : Parent(name, Parent::ITERATED_MAP), childs_(childs) + { + size_ = childs_.size(); + } + + const std::string &getChildName() const + { + ARILES2_ASSERT(index_ < childs_.size(), "End of iterated map has not been reached."); + return (childs_[index_]); + } + + ReaderNodeWrapper(const rclcpp::Parameter &¶meter) + : Parent(Parent::ARRAY), parameter_(parameter), is_builtin_array_(true) + { + switch (parameter_.get_type()) + { + case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY: + size_ = parameter_.as_byte_array().size(); + return; + case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY: + size_ = parameter_.as_bool_array().size(); + return; + case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY: + size_ = parameter_.as_integer_array().size(); + return; + case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY: + size_ = parameter_.as_double_array().size(); + return; + case rclcpp::ParameterType::PARAMETER_STRING_ARRAY: + size_ = parameter_.as_string_array().size(); + return; + default: + ARILES2_THROW("Unexpected value type"); + } + } + + bool isBuiltinArray() const + { + return (is_builtin_array_); + } + + bool tryReadArray(int64_t &value) + { + if (isBuiltinArray()) + { + switch (parameter_.get_type()) + { + case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY: + value = parameter_.as_byte_array()[index_]; + return (true); + case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY: + value = parameter_.as_integer_array()[index_]; + return (true); + default: + ARILES2_THROW("Unexpected array value type"); + } + } + return (false); + } + + bool tryReadArray(double &value) + { + if (isBuiltinArray()) + { + switch (parameter_.get_type()) + { + case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY: + value = parameter_.as_double_array()[index_]; + return (true); + default: + ARILES2_THROW("Unexpected array value type"); + } + } + return (false); + } + + bool tryReadArray(std::string &value) + { + if (isBuiltinArray()) + { + switch (parameter_.get_type()) + { + case rclcpp::ParameterType::PARAMETER_STRING_ARRAY: + value = parameter_.as_string_array()[index_]; + return (true); + default: + ARILES2_THROW("Unexpected array value type"); + } + } + return (false); + } + + bool tryReadArray(bool &value) + { + if (isBuiltinArray()) + { + switch (parameter_.get_type()) + { + case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY: + value = parameter_.as_bool_array()[index_]; + return (true); + default: + ARILES2_THROW("Unexpected array value type"); + } + } + return (false); + } + + bool isNonBuiltinArray() const + { + return (not is_builtin_array_ and isArray()); + } + }; + + namespace impl + { + class ARILES2_VISIBILITY_ATTRIBUTE Reader + { + public: + /// Stack of nodes. + std::vector node_stack_; + + // https://docs.ros2.org/latest/api/rclcpp/classrclcpp_1_1Node.html + const rclcpp::Node *nh_; + + public: + explicit Reader(const ::rclcpp::Node *nh) + { + nh_ = nh; + } + + ReaderNodeWrapper &back() + { + return (node_stack_.back()); + } + + const ReaderNodeWrapper &back() const + { + return (node_stack_.back()); + } + + bool getParameter(rclcpp::Parameter ¶meter) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(back().node_); + return (nh_->get_parameter(back().node_, parameter)); + } + + rcl_interfaces::msg::ListParametersResult listParameters() const + { + return (nh_->list_parameters({ node_stack_.size() == 0 ? "" : back().node_ }, /*depth=*/1)); + } + }; + } // namespace impl + } // namespace ns_ros2param +} // namespace ariles2 + + +namespace ariles2 +{ + namespace ns_ros2param + { + Reader::Reader(const ::rclcpp::Node *nh) + { + makeImplPtr(nh); + } + + + bool Reader::startMapEntry(const std::string &child_name) + { + ARILES2_TRACE_FUNCTION; + if (0 == impl_->node_stack_.size()) + { + impl_->node_stack_.emplace_back(child_name); + } + else + { + ARILES2_ASSERT(not impl_->back().isBuiltinArray(), "Unexpected parent type (builtin array)."); + + std::string node; + node.reserve(impl_->back().node_.size() + child_name.size() + 1); + node = impl_->back().node_; + node += "."; + node += child_name; + impl_->node_stack_.emplace_back(std::move(node)); + } + + return (true); + } + + void Reader::endMapEntry() + { + ARILES2_TRACE_FUNCTION; + impl_->node_stack_.pop_back(); + } + + + + bool Reader::startIteratedMap( + const SizeLimitEnforcementType limit_type, + const std::size_t min, + const std::size_t max) + { + ARILES2_TRACE_FUNCTION; + + const rcl_interfaces::msg::ListParametersResult name_list = impl_->listParameters(); + + checkSize(limit_type, name_list.names.size(), min, max); + + impl_->node_stack_.emplace_back(impl_->back().node_, std::move(name_list.names)); + return (true); + } + + bool Reader::startIteratedMapElement(std::string &entry_name) + { + ARILES2_TRACE_FUNCTION; + const std::string &child_name = impl_->back().getChildName(); + + std::string node; + node.reserve(impl_->back().node_.size() + child_name.size() + 1); + node = impl_->back().node_; + node += "."; + node += child_name; + impl_->node_stack_.emplace_back(std::move(node)); + + entry_name = child_name; + + return (true); + } + + void Reader::endIteratedMapElement() + { + impl_->node_stack_.pop_back(); + ++(impl_->back().index_); + } + + void Reader::endIteratedMap() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(impl_->back().isCompleted(), "End of iterated map has not been reached."); + impl_->node_stack_.pop_back(); + } + + + std::size_t Reader::startArray() + { + ARILES2_TRACE_FUNCTION; + + rclcpp::Parameter values; + if (impl_->node_stack_.size() > 0 and impl_->getParameter(values)) + { + impl_->node_stack_.emplace_back(std::move(values)); + } + else + { + const rcl_interfaces::msg::ListParametersResult name_list = impl_->listParameters(); + impl_->node_stack_.emplace_back(0, name_list.names.size()); + } + + return (impl_->back().size_); + } + + void Reader::startArrayElement() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(not impl_->back().isCompleted(), "Internal error: array has more elements than expected."); + + if (impl_->back().isNonBuiltinArray()) + { + std::string node; + node.reserve(impl_->back().node_.size() + num_chars_for_index_reserve + 1); + node = impl_->back().node_; + node += "."; + node += boost::lexical_cast(impl_->back().index_); + + impl_->node_stack_.emplace_back(std::move(node)); + } + } + + void Reader::endArrayElement() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(impl_->back().isArray(), "Internal error: expected array."); + if (impl_->back().isNonBuiltinArray()) + { + impl_->node_stack_.pop_back(); + } + ++(impl_->back().index_); + } + + void Reader::endArray() + { + ARILES2_TRACE_FUNCTION; + impl_->node_stack_.pop_back(); + } + + + +#define ARILES2_BASIC_TYPE(type) \ + void Reader::readElement(type &element) \ + { \ + int64_t tmp_value; \ + if (not impl_->back().tryReadArray(tmp_value)) \ + { \ + ARILES2_TRACE_FUNCTION; \ + rclcpp::Parameter parameter; \ + ARILES2_ASSERT( \ + impl_->getParameter(parameter), std::string("Cannot read parameter: ") + impl_->back().node_); \ + ARILES2_ASSERT( \ + rclcpp::ParameterType::PARAMETER_INTEGER == parameter.get_type(), \ + "Unexpected parameter type while reading signed integer."); \ + tmp_value = parameter.as_int(); \ + } \ + ARILES2_ASSERT( \ + tmp_value <= std::numeric_limits::max() && tmp_value >= std::numeric_limits::min(), \ + "Value is out of range."); \ + element = static_cast(tmp_value); \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + + +#define ARILES2_BASIC_TYPE(type) \ + void Reader::readElement(type &element) \ + { \ + ARILES2_TRACE_FUNCTION; \ + int64_t tmp_value; \ + if (not impl_->back().tryReadArray(tmp_value)) \ + { \ + rclcpp::Parameter parameter; \ + ARILES2_ASSERT( \ + impl_->getParameter(parameter), std::string("Cannot read parameter: ") + impl_->back().node_); \ + ARILES2_ASSERT( \ + rclcpp::ParameterType::PARAMETER_INTEGER == parameter.get_type(), \ + "Unexpected parameter type while reading signed integer."); \ + tmp_value = parameter.as_int(); \ + } \ + ARILES2_ASSERT(tmp_value >= 0, "Expected positive value."); \ + ARILES2_ASSERT(static_cast(tmp_value) <= std::numeric_limits::max(), "Value is too large."); \ + element = static_cast(tmp_value); \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + + +#define ARILES2_BASIC_TYPE(type) \ + void Reader::readElement(type &element) \ + { \ + ARILES2_TRACE_FUNCTION; \ + double tmp_value; \ + if (not impl_->back().tryReadArray(tmp_value)) \ + { \ + rclcpp::Parameter parameter; \ + ARILES2_ASSERT( \ + impl_->getParameter(parameter), std::string("Cannot read parameter: ") + impl_->back().node_); \ + ARILES2_ASSERT( \ + rclcpp::ParameterType::PARAMETER_DOUBLE == parameter.get_type(), \ + "Unexpected parameter type while reading signed integer."); \ + tmp_value = parameter.as_double(); \ + } \ + element = static_cast(tmp_value); \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_REAL_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + + + void Reader::readElement(std::string &element) + { + ARILES2_TRACE_FUNCTION; + if (not impl_->back().tryReadArray(element)) + { + rclcpp::Parameter parameter; + ARILES2_ASSERT( + impl_->getParameter(parameter), std::string("Cannot read parameter: ") + impl_->back().node_); + ARILES2_ASSERT( + rclcpp::ParameterType::PARAMETER_STRING == parameter.get_type(), + "Unexpected parameter type while reading signed integer."); + element = parameter.as_string(); + } + } + + + void Reader::readElement(bool &element) + { + ARILES2_TRACE_FUNCTION; + if (not impl_->back().tryReadArray(element)) + { + rclcpp::Parameter parameter; + ARILES2_ASSERT( + impl_->getParameter(parameter), std::string("Cannot read parameter: ") + impl_->back().node_); + ARILES2_ASSERT( + rclcpp::ParameterType::PARAMETER_BOOL == parameter.get_type(), + "Unexpected parameter type while reading signed integer."); + element = parameter.as_bool(); + } + } + } // namespace ns_ros2param +} // namespace ariles2 diff --git a/extra_visitors/ros2param/src/writer.cpp b/extra_visitors/ros2param/src/writer.cpp new file mode 100644 index 00000000..59e9888e --- /dev/null +++ b/extra_visitors/ros2param/src/writer.cpp @@ -0,0 +1,299 @@ +/** + @file + @author Alexander Sherikov + + @copyright 2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0. + (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0) + + @brief +*/ + + +#include +#include + +#include + + +namespace ariles2 +{ + namespace ns_ros2param + { + class WriterNodeWrapper : public serialization::Node + { + protected: + using Parent = serialization::Node; + + public: + std::variant< + std::vector, + std::vector, + std::vector, + std::vector, + std::vector, + std::vector> + array_values_; + bool array_values_ok_ = false; + + public: + using Parent::Parent; + + + template + bool tryPushArray(const t_Value value) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(node_); + ARILES2_TRACE_TYPE(t_Value); + if (isArray()) + { + if (not array_values_ok_) + { + array_values_.emplace>(); + std::get>(array_values_).reserve(size_); + array_values_ok_ = true; + } + std::get>(array_values_).push_back(value); + return (true); + } + return (false); + } + + bool tryPushArray(const std::string &value) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(node_); + if (isArray()) + { + if (not array_values_ok_) + { + array_values_.emplace>(); + std::get>(array_values_).reserve(size_); + array_values_ok_ = true; + } + std::get>(array_values_).push_back(value); + return (true); + } + return (false); + } + }; + + namespace impl + { + class ARILES2_VISIBILITY_ATTRIBUTE Writer + { + public: + /// Stack of nodes. + std::vector node_stack_; + + // https://docs.ros2.org/latest/api/rclcpp/classrclcpp_1_1Node.html + rclcpp::Node *nh_; + + std::vector parameters_; + + public: + explicit Writer(::rclcpp::Node *nh) + { + nh_ = nh; + } + + WriterNodeWrapper &back() + { + return (node_stack_.back()); + } + + const WriterNodeWrapper &back() const + { + return (node_stack_.back()); + } + + bool publishParameters() + { + return (nh_->set_parameters_atomically(parameters_).successful); + } + + template + void setParameter(const t_Element element) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(back().node_); + ARILES2_TRACE_TYPE(t_Element); + + parameters_.emplace_back(back().node_, element); + } + + void setParameter(const std::string &element) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(back().node_); + parameters_.emplace_back(back().node_, element); + } + + void setParameter() + { + ARILES2_TRACE_FUNCTION; + if (back().array_values_ok_) + { + std::visit([this](auto &&arg) { setParameter(arg); }, back().array_values_); + } + } + }; + } // namespace impl + } // namespace ns_ros2param +} // namespace ariles2 + + +namespace ariles2 +{ + namespace ns_ros2param + { + Writer::Writer(::rclcpp::Node *nh) + { + makeImplPtr(nh); + } + + + void Writer::flush() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(impl_->publishParameters(), "Failed to set parameters."); + } + + + void Writer::startMapEntry(const std::string &child_name) + { + ARILES2_TRACE_FUNCTION; + ARILES2_TRACE_VALUE(child_name); + if (0 == impl_->node_stack_.size()) + { + impl_->node_stack_.emplace_back(child_name); + } + else + { + std::string node; + if (impl_->back().isArray()) + { + node.reserve(impl_->back().node_.size() + child_name.size() + num_chars_for_index_reserve + 3); + node = impl_->back().node_; + node += "."; + node += boost::lexical_cast(impl_->back().index_); + } + else + { + node.reserve(impl_->back().node_.size() + child_name.size() + 1); + node = impl_->back().node_; + } + node += "."; + node += child_name; + impl_->node_stack_.emplace_back(std::move(node)); + } + } + + void Writer::endMapEntry() + { + ARILES2_TRACE_FUNCTION; + impl_->node_stack_.pop_back(); + } + + + void Writer::startArray(const std::size_t size, const bool /*compact*/) + { + ARILES2_TRACE_FUNCTION; + impl_->node_stack_.emplace_back(impl_->back().node_, /*index=*/0, size); + } + + void Writer::startArrayElement() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(not impl_->back().isCompleted(), "Internal error: array has more elements than expected."); + } + + void Writer::endArrayElement() + { + ARILES2_TRACE_FUNCTION; + ARILES2_ASSERT(impl_->back().isArray(), "Internal error: expected array."); + ++impl_->back().index_; + } + + void Writer::endArray() + { + ARILES2_TRACE_FUNCTION; + impl_->setParameter(); + impl_->node_stack_.pop_back(); + } + + + void Writer::writeElement(const unsigned char &element, const Parameters &) + { + ARILES2_TRACE_FUNCTION; + if (not impl_->back().tryPushArray(element)) + { + impl_->setParameter(static_cast(element)); + } + } + + + void Writer::writeElement(const float &element, const Parameters &) + { + ARILES2_TRACE_FUNCTION; + if (not impl_->back().tryPushArray(element)) + { + impl_->setParameter(static_cast(element)); + } + } + + +#define ARILES2_ROS2PARAM_NATIVE_TYPES_LIST \ + ARILES2_BASIC_TYPE(bool) \ + ARILES2_BASIC_TYPE(double) \ + ARILES2_BASIC_TYPE(std::string) + + +#define ARILES2_BASIC_TYPE(type) \ + void Writer::writeElement(const type &element, const Parameters &) \ + { \ + ARILES2_TRACE_FUNCTION; \ + if (not impl_->back().tryPushArray(element)) \ + { \ + impl_->setParameter(element); \ + } \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_ROS2PARAM_NATIVE_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + + +#define ARILES2_BASIC_TYPE(type) \ + void Writer::writeElement(const type &element, const Parameters &) \ + { \ + ARILES2_TRACE_FUNCTION; \ + if (not impl_->back().tryPushArray(element)) \ + { \ + impl_->setParameter(static_cast(element)); \ + } \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST) + +#undef ARILES2_BASIC_TYPE + + +#define ARILES2_BASIC_TYPE(type) \ + void Writer::writeElement(const type &element, const Parameters &) \ + { \ + ARILES2_TRACE_FUNCTION; \ + ARILES2_ASSERT( \ + static_cast(element) <= static_cast(std::numeric_limits::max()), \ + "Value is too large."); \ + if (not impl_->back().tryPushArray(element)) \ + { \ + impl_->setParameter(static_cast(element)); \ + } \ + } + + ARILES2_MACRO_SUBSTITUTE(ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST_WITHOUT_BYTE) + +#undef ARILES2_BASIC_TYPE + } // namespace ns_ros2param +} // namespace ariles2 diff --git a/extra_visitors/rosparam/src/reader.cpp b/extra_visitors/rosparam/src/reader.cpp index 95f97720..80fc7b96 100644 --- a/extra_visitors/rosparam/src/reader.cpp +++ b/extra_visitors/rosparam/src/reader.cpp @@ -142,7 +142,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } void Reader::endArrayElement() diff --git a/extra_visitors/rosparam/src/writer.cpp b/extra_visitors/rosparam/src/writer.cpp index d2e12199..9f0c51f3 100644 --- a/extra_visitors/rosparam/src/writer.cpp +++ b/extra_visitors/rosparam/src/writer.cpp @@ -82,7 +82,7 @@ namespace ariles2 { ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } void Writer::endArrayElement() diff --git a/extra_visitors/yaml_cpp/src/reader.cpp b/extra_visitors/yaml_cpp/src/reader.cpp index d7d42bf2..a4f0b5ad 100644 --- a/extra_visitors/yaml_cpp/src/reader.cpp +++ b/extra_visitors/yaml_cpp/src/reader.cpp @@ -168,7 +168,7 @@ namespace ariles2 ARILES2_TRACE_FUNCTION; ARILES2_ASSERT( impl_->node_stack_.back().index_ < impl_->node_stack_.back().size_, - "Internal error: namevalue.has more elements than expected."); + "Internal error: array has more elements than expected."); } diff --git a/include/ariles2/internal/helpers.h b/include/ariles2/internal/helpers.h index 9f711f97..d3256a48 100644 --- a/include/ariles2/internal/helpers.h +++ b/include/ariles2/internal/helpers.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -57,11 +58,14 @@ ARILES2_BASIC_TYPE(long long) \ ARILES2_BASIC_TYPE(char) -#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST \ +#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST_WITHOUT_BYTE \ ARILES2_BASIC_TYPE(unsigned int) \ ARILES2_BASIC_TYPE(unsigned short) \ ARILES2_BASIC_TYPE(unsigned long) \ - ARILES2_BASIC_TYPE(unsigned long long) \ + ARILES2_BASIC_TYPE(unsigned long long) + +#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST \ + ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST_WITHOUT_BYTE \ ARILES2_BASIC_TYPE(unsigned char) @@ -99,6 +103,9 @@ namespace ariles2 { + // 20 + const uint8_t num_chars_for_index_reserve = std::numeric_limits::digits10 + 1; + // intentionally not defined template class ARILES2_VISIBILITY_ATTRIBUTE PointerHandler; diff --git a/include/ariles2/types.h b/include/ariles2/types.h index e98c6201..44198618 100644 --- a/include/ariles2/types.h +++ b/include/ariles2/types.h @@ -317,7 +317,11 @@ namespace ariles2 ARILES2_TRACE_FUNCTION; if (value_.get() != other.value_.get()) { - value_->arilesVisit(visitor, *other.value_, param); + if (nullptr != value_ and nullptr != other.value_) + { + value_->arilesVisit(visitor, *other.value_, param); + } + visitor.equal_ = false; } } #endif diff --git a/include/ariles2/visitors/common.h b/include/ariles2/visitors/common.h index 9013c01c..25ffc8a4 100644 --- a/include/ariles2/visitors/common.h +++ b/include/ariles2/visitors/common.h @@ -10,6 +10,7 @@ #pragma once +#include #include #include "../internal/helpers.h" @@ -200,6 +201,7 @@ namespace ariles2 template typename t_Visitor::ReturnType apply( t_Ariles &ariles_class, + ARILES2_IS_BASE_ENABLER(ariles2::Ariles, t_Ariles), ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) { ARILES2_TRACE_FUNCTION; @@ -211,118 +213,41 @@ namespace ariles2 // ----- - template - typename t_Visitor::ReturnType apply( - t_Arg &arg, - t_Ariles &ariles_class, - ARILES2_IS_BASE_DISABLER(ariles2::Ariles, t_Arg), - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) + template < + class t_Visitor, + typename t_Arg, + typename... t_Args, + typename = std::enable_if_t::value>, + typename = std::enable_if_t::value>, + typename = std::enable_if_t>::value>> + typename t_Visitor::ReturnType apply(t_Arg &arg, t_Args &&...args) { ARILES2_TRACE_FUNCTION; t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class)); + return (ariles2::apply(visitor, std::forward(args)...)); } - template - typename t_Visitor::ReturnType apply( - t_Arg &arg, - t_Ariles &ariles_class, - const char *name, - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) + template < + class t_Visitor, + typename t_Arg, + typename... t_Args, + typename = std::enable_if_t::value>, + typename = std::enable_if_t>::value>> + typename t_Visitor::ReturnType apply(t_Arg *arg, t_Args &&...args) { ARILES2_TRACE_FUNCTION; t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, name)); + return (ariles2::apply(visitor, std::forward(args)...)); } - template - typename t_Visitor::ReturnType apply( - const t_Arg &arg, - t_Ariles &ariles_class, - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) - { - ARILES2_TRACE_FUNCTION; - t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class)); - } - - - template - typename t_Visitor::ReturnType apply( - t_Arg &arg, - t_Ariles &ariles_class, - const typename t_Visitor::Parameters ¶m, - ARILES2_IS_BASE_DISABLER(std::string, t_Arg), - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) - { - ARILES2_TRACE_FUNCTION; - t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, param)); - } - - - template - typename t_Visitor::ReturnType apply( - t_Arg &arg, - t_Ariles &ariles_class, - const t_Subtree &subtree, - ARILES2_IS_ANY_OF(t_Subtree, const std::string, const std::vector), - ARILES2_IS_BASE_DISABLER(std::string, t_Arg), - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) - { - ARILES2_TRACE_FUNCTION; - t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, subtree)); - } - - - template - typename t_Visitor::ReturnType apply( - t_Arg &arg, - t_Ariles &ariles_class, - const char *name, - const typename t_Visitor::Parameters ¶m, - ARILES2_IS_BASE_DISABLER(std::string, t_Arg), - ARILES2_IS_BASE_DISABLER(ariles2::visitor::Visitor, t_Arg), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) - { - ARILES2_TRACE_FUNCTION; - t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, name, param)); - } - - - template - typename t_Visitor::ReturnType apply( - const std::string &arg, - t_Ariles &ariles_class, - const typename t_Visitor::Parameters ¶m, - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) - { - ARILES2_TRACE_FUNCTION; - t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, param)); - } - - - template - typename t_Visitor::ReturnType apply( - const std::string &arg, - t_Ariles &ariles_class, - const t_Subtree &subtree, - ARILES2_IS_ANY_OF(t_Subtree, const std::string, const std::vector), - ARILES2_IS_BASE_ENABLER(ariles2::visitor::Visitor, t_Visitor)) + template + typename t_Visitor::ReturnType apply(const std::string &arg, t_Args &&...args) { ARILES2_TRACE_FUNCTION; t_Visitor visitor(arg); - return (ariles2::apply(visitor, ariles_class, subtree)); + return (ariles2::apply(visitor, std::forward(args)...)); } // ----- diff --git a/include/ariles2/visitors/serialization.h b/include/ariles2/visitors/serialization.h index 15c909ea..eb805bec 100644 --- a/include/ariles2/visitors/serialization.h +++ b/include/ariles2/visitors/serialization.h @@ -112,9 +112,9 @@ namespace ariles2 return (ARRAY == type_); } - bool isAllParsed() const + bool isCompleted() const { - return (index_ == size_); + return (index_ >= size_); } }; diff --git a/qa/scspell.dict b/qa/scspell.dict index cb0b9d09..6ffbb8b7 100644 --- a/qa/scspell.dict +++ b/qa/scspell.dict @@ -9,6 +9,7 @@ auxillary backtrace cfgread cfgwrite +classrclcpp cmakeut constexpr copyfrom @@ -99,6 +100,7 @@ putback quaterniond rankdir rapidjson +rclcpp rdbuf reinitializes remappings diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7481d19a..1319685a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,6 @@ include(ariles_define_test) include(ariles_parse_test_dependencies) set(ARILES_TEST_FILE_VISITORS "yaml_cpp;msgpack;rapidjson;jsonnet;pugixml") -set(ARILES_TEST_ALL_VISITORS "${ARILES_TEST_FILE_VISITORS};rosparam") +set(ARILES_TEST_ALL_VISITORS "${ARILES_TEST_FILE_VISITORS};rosparam;ros2param") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/api_v2") diff --git a/tests/api_v2/all_enabled_visitors.h b/tests/api_v2/all_enabled_visitors.h index 207635b9..63024bc3 100644 --- a/tests/api_v2/all_enabled_visitors.h +++ b/tests/api_v2/all_enabled_visitors.h @@ -34,6 +34,10 @@ # include #endif +#ifdef ARILES_VISITOR_ros2param +# include +#endif + // Do not have Reader and therefore are excluded from most of the tests // // #ifdef ARILES_VISITOR_octave diff --git a/tests/api_v2/fixtures/initializers.h b/tests/api_v2/fixtures/initializers.h index 3a2d6546..3c8f2a2d 100644 --- a/tests/api_v2/fixtures/initializers.h +++ b/tests/api_v2/fixtures/initializers.h @@ -190,5 +190,66 @@ namespace ariles_tests } }; #endif + + +#ifdef ARILES2_VISITOR_INCLUDED_ros2param +# include + + + class ROS2Initializer + { + private: + inline static std::atomic counter_{ 0 }; + + ROS2Initializer(const ROS2Initializer &); + void operator=(const ROS2Initializer &); + + + public: + rclcpp::Node::SharedPtr nh_; + + + public: + ROS2Initializer() + { + nh_ = nullptr; + + if (not rclcpp::ok()) + { + rclcpp::init(/*argn=*/0, /*argv=*/nullptr); + } + + nh_ = rclcpp::Node::make_shared( + std::string("FixtureBase") + boost::lexical_cast(counter_++), + rclcpp::NodeOptions() + .allow_undeclared_parameters(true) + .automatically_declare_parameters_from_overrides(true)); + } + + ~ROS2Initializer() + { + /* + rcl_interfaces::msg::ListParametersResult parameters = nh_->list_parameters({""}, 100); + std::cout << ">>>>>>>>> " << std::endl; + for (const std::string & name : parameters.names) + { + std::cout << name << std::endl; + } + std::cout << ">>>>>>>>> " << std::endl; + */ + rclcpp::shutdown(); + } + + const rclcpp::Node *getReaderInitializer(const std::string & /*string_id*/) + { + return (nh_.get()); + } + + rclcpp::Node *getWriterInitializer(const std::string & /*string_id*/) + { + return (nh_.get()); + } + }; +#endif } // namespace initializers } // namespace ariles_tests diff --git a/tests/api_v2/instantiate.h b/tests/api_v2/instantiate.h index 86ca45eb..1572348f 100644 --- a/tests/api_v2/instantiate.h +++ b/tests/api_v2/instantiate.h @@ -41,6 +41,10 @@ ARILES_TESTS(rapidjson_jsonnet, jsonnet, StreamInitializer) ARILES_TESTS_SHORTCUT(rosparam, ROSInitializer) #endif +#ifdef ARILES2_VISITOR_INCLUDED_ros2param +ARILES_TESTS_SHORTCUT(ros2param, ROS2Initializer) +#endif + #ifdef ARILES2_VISITOR_INCLUDED_octave ARILES_TESTS_SHORTCUT(octave, FilenameInitializer) #endif diff --git a/tests/api_v2/regression_test_210.cpp b/tests/api_v2/regression_test_210.cpp index 473448f6..45b053b2 100644 --- a/tests/api_v2/regression_test_210.cpp +++ b/tests/api_v2/regression_test_210.cpp @@ -29,6 +29,7 @@ // =============================================================== #undef ARILES_VISITOR_rosparam +#undef ARILES_VISITOR_ros2param #include "fixtures/initializers.h" #include "fixtures/009_read.h" diff --git a/tests/api_v2/regression_test_215.cpp b/tests/api_v2/regression_test_215.cpp index f9a09267..9bf28c49 100644 --- a/tests/api_v2/regression_test_215.cpp +++ b/tests/api_v2/regression_test_215.cpp @@ -27,6 +27,7 @@ // =============================================================== #undef ARILES_VISITOR_rosparam +#undef ARILES_VISITOR_ros2param #include "fixtures/initializers.h" #include "fixtures/009_read.h" diff --git a/tests/api_v2/regression_test_223.cpp b/tests/api_v2/regression_test_223.cpp index 19fca43b..7a71117c 100644 --- a/tests/api_v2/regression_test_223.cpp +++ b/tests/api_v2/regression_test_223.cpp @@ -26,6 +26,7 @@ // =============================================================== #undef ARILES_VISITOR_rosparam +#undef ARILES_VISITOR_ros2param #include "fixtures/initializers.h" #include "fixtures/015_read_compare.h" diff --git a/tests/api_v2/regression_test_224.cpp b/tests/api_v2/regression_test_224.cpp index 2cbdaa54..30bc3340 100644 --- a/tests/api_v2/regression_test_224.cpp +++ b/tests/api_v2/regression_test_224.cpp @@ -58,6 +58,7 @@ namespace ariles_tests // =============================================================== #undef ARILES_VISITOR_rosparam +#undef ARILES_VISITOR_ros2param #include "fixtures/initializers.h" #include "fixtures/009_read.h"