diff --git a/include/zenoh/api/interop.hxx b/include/zenoh/api/interop.hxx index 24d18d68..5ccc78c6 100644 --- a/include/zenoh/api/interop.hxx +++ b/include/zenoh/api/interop.hxx @@ -13,7 +13,9 @@ #pragma once #include +#include #include +#include #include "base.hxx" @@ -179,6 +181,23 @@ OwnedType move_to_c_obj(Owned&& owned_cpp_obj) { } namespace detail { +// Copy the strings into a vector and consume the C array, including on exceptions. +inline std::vector string_array_to_vector(::z_owned_string_array_t& array) { + struct DropGuard { + ::z_owned_string_array_t& array; + ~DropGuard() { ::z_drop(::z_move(array)); } + } guard{array}; + const auto* loaned = ::z_loan(guard.array); + const size_t count = ::z_string_array_len(loaned); + std::vector result; + result.reserve(count); + for (size_t i = 0; i < count; ++i) { + const auto* value = ::z_string_array_get(loaned, i); + result.emplace_back(::z_string_data(value), ::z_string_len(value)); + } + return result; +} + template bool check(const Owned& owned_cpp_obj) { return ::z_internal_check(*as_owned_c_ptr(owned_cpp_obj)); diff --git a/include/zenoh/api/link.hxx b/include/zenoh/api/link.hxx index 8cfd858d..41ab1fd6 100644 --- a/include/zenoh/api/link.hxx +++ b/include/zenoh/api/link.hxx @@ -93,15 +93,7 @@ class Link : public Owned<::z_owned_link_t> { std::vector get_interfaces() const { ::z_owned_string_array_t interfaces_out; ::z_link_interfaces(interop::as_loaned_c_ptr(*this), &interfaces_out); - auto loaned = ::z_loan(interfaces_out); - std::vector result; - result.reserve(::z_string_array_len(loaned)); - for (size_t i = 0; i < ::z_string_array_len(loaned); i++) { - auto s = ::z_string_array_get(loaned, i); - result.emplace_back(::z_string_data(s), ::z_string_len(s)); - } - ::z_drop(::z_move(interfaces_out)); - return result; + return interop::detail::string_array_to_vector(interfaces_out); } /// @brief Get the priority range supported by this link. diff --git a/tests/universal/details.cxx b/tests/universal/details.cxx index 34a65f1c..1fa4fe5d 100644 --- a/tests/universal/details.cxx +++ b/tests/universal/details.cxx @@ -14,6 +14,9 @@ #include "zenoh.hxx" +#undef NDEBUG +#include + using namespace zenoh; static_assert(detail::is_take_from_loaned_available_v<::z_owned_session_t> == false); @@ -22,4 +25,25 @@ static_assert(detail::is_take_from_loaned_available_v<::z_owned_sample_t>); static_assert(detail::is_take_from_loaned_available_v<::z_owned_reply_t>); static_assert(detail::is_take_from_loaned_available_v<::z_owned_query_t>); -int main() { return 0; } \ No newline at end of file +static void test_string_array_to_vector() { + ::z_owned_string_array_t array; + ::z_string_array_new(&array); + assert(interop::detail::string_array_to_vector(array).empty()); + assert(!::z_internal_string_array_check(&array)); + + ::z_string_array_new(&array); + const std::vector expected{"eth0", "", std::string("a\0b", 3), "lo"}; + for (const auto& text : expected) { + ::z_view_string_t view; + assert(::z_view_string_from_substr(&view, text.data(), text.size()) == Z_OK); + ::z_string_array_push_by_copy(::z_loan_mut(array), ::z_loan(view)); + } + const auto result = interop::detail::string_array_to_vector(array); + assert(!::z_internal_string_array_check(&array)); + assert(result == expected); +} + +int main() { + test_string_array_to_vector(); + return 0; +}