diff --git a/simgear/nasal/cppbind/detail/from_nasal_helper.hxx b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx index 436dcb3c..a582bfe6 100644 --- a/simgear/nasal/cppbind/detail/from_nasal_helper.hxx +++ b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx @@ -28,14 +28,13 @@ #include #include #include +#include #include #include -#include #include -#include -#include +#include #include #include @@ -143,9 +142,7 @@ namespace nasal * Convert a Nasal number to a C++ numeric type */ template - typename boost::enable_if< boost::is_arithmetic, - T - >::type + std::enable_if_t::value, T> from_nasal_helper(naContext c, naRef ref, const T*) { naRef num = naNumValue(ref); @@ -174,17 +171,39 @@ namespace nasal return vec; } + /** + * Convert a Nasal vector to a std::array + */ + template + std::array + from_nasal_helper(naContext c, naRef ref, const std::array*) + { + if( !naIsVector(ref) ) + throw bad_nasal_cast("Not a vector"); + + if( naVec_size(ref) != N ) + throw bad_nasal_cast( + "Expected vector with " + std::to_string(N) + " elements" + ); + + std::array arr; + + for(std::size_t i = 0; i < N; ++i) + arr[i] = from_nasal_helper(c, naVec_get(ref, i), static_cast(0)); + + return arr; + } + /** * Convert a Nasal vector of 2 elements to a 2d vector */ template - typename boost::enable_if, Vec2>::type + std::enable_if_t::value, Vec2> from_nasal_helper(naContext c, naRef ref, const Vec2*) { - std::vector vec = - from_nasal_helper(c, ref, static_cast*>(0)); - if( vec.size() != 2 ) - throw bad_nasal_cast("Expected vector with two elements"); + auto vec = + from_nasal_helper(c, ref, static_cast*>(0)); + return Vec2(vec[0], vec[1]); } @@ -194,10 +213,8 @@ namespace nasal template SGRect from_nasal_helper(naContext c, naRef ref, const SGRect*) { - std::vector vec = - from_nasal_helper(c, ref, static_cast*>(0)); - if( vec.size() != 4 ) - throw bad_nasal_cast("Expected vector with four elements"); + auto vec = + from_nasal_helper(c, ref, static_cast*>(0)); return SGRect(vec[0], vec[1], vec[2], vec[3]); } diff --git a/simgear/nasal/cppbind/detail/to_nasal_helper.hxx b/simgear/nasal/cppbind/detail/to_nasal_helper.hxx index 7d54fcb6..1098f08e 100644 --- a/simgear/nasal/cppbind/detail/to_nasal_helper.hxx +++ b/simgear/nasal/cppbind/detail/to_nasal_helper.hxx @@ -25,12 +25,13 @@ #include #include #include +#include #include -#include #include -#include +#include +#include #include #include #include @@ -75,11 +76,66 @@ namespace nasal naRef to_nasal_helper(naContext c, const free_function_t& func); + namespace detail + { + template + naRef array_to_nasal(naContext c, const T* arr, size_t size); + } + + /** + * Convert a fixed size array to a Nasal vector + */ + template + naRef to_nasal_helper(naContext c, const T(&array)[N]) + { + return detail::array_to_nasal(c, array, N); + } + + /** + * Convert a fixed size C++ array to a Nasal vector + */ + template + naRef to_nasal_helper(naContext c, const std::array& array) + { + return detail::array_to_nasal(c, array.data(), N); + } + + /** + * Convert a std::initializer_list to a Nasal vector + */ + template + naRef to_nasal_helper(naContext c, std::initializer_list list) + { + return detail::array_to_nasal(c, list.begin(), list.size()); + } + + /** + * Convert std::vector to a Nasal vector + */ + template< template class Vector, + class T, + class Alloc + > + std::enable_if_t< + std::is_same, std::vector>::value, + naRef + > + to_nasal_helper(naContext c, const Vector& vec) + { + return detail::array_to_nasal(c, vec.data(), vec.size()); + } + + /** + * Convert a std::map to a Nasal Hash + */ + template + naRef to_nasal_helper(naContext c, const std::map& map); + /** * Convert an enum value to the according numeric value */ template - typename boost::enable_if< boost::is_enum, naRef >::type + std::enable_if_t::value, naRef> to_nasal_helper(naContext c, T val) { return naNum(val); @@ -89,7 +145,7 @@ namespace nasal * Convert a numeric type to Nasal number */ template - typename boost::enable_if< boost::is_arithmetic, naRef >::type + std::enable_if_t::value, naRef> to_nasal_helper(naContext c, T num) { return naNum(num); @@ -99,67 +155,40 @@ namespace nasal * Convert a 2d vector to Nasal vector with 2 elements */ template - typename boost::enable_if, naRef>::type - to_nasal_helper(naContext c, const Vec2& vec); - - /** - * Convert a std::map to a Nasal Hash - */ - template - naRef to_nasal_helper(naContext c, const std::map& map); - - /** - * Convert a fixed size array to a Nasal vector - */ - template - naRef to_nasal_helper(naContext c, const T(&array)[N]); - - /** - * Convert std::vector to Nasal vector - */ - template< template class Vector, - class T, - class Alloc - > - typename boost::enable_if< boost::is_same< Vector, - std::vector - >, - naRef - >::type - to_nasal_helper(naContext c, const Vector& vec) - { - naRef ret = naNewVector(c); - naVec_setsize(c, ret, static_cast(vec.size())); - for(int i = 0; i < static_cast(vec.size()); ++i) - naVec_set(ret, i, to_nasal_helper(c, vec[i])); - return ret; - } - - //---------------------------------------------------------------------------- - template - typename boost::enable_if, naRef>::type + std::enable_if_t::value, naRef> to_nasal_helper(naContext c, const Vec2& vec) { - // We take just double because in Nasal every number is represented as - // double - double nasal_vec[2] = { + return to_nasal_helper(c, { + // We take just double because in Nasal every number is represented as + // double static_cast(vec[0]), static_cast(vec[1]) - }; - return to_nasal_helper(c, nasal_vec); + }); + } + + /** + * Convert a SGRect to a Nasal vector with position and size of the rect + */ + template + naRef to_nasal_helper(naContext c, const SGRect& rect) + { + return to_nasal_helper(c, { + static_cast(rect.x()), + static_cast(rect.y()), + static_cast(rect.width()), + static_cast(rect.height()) + }); } //---------------------------------------------------------------------------- template - naRef to_nasal_helper(naContext c, const SGRect& rect) + naRef detail::array_to_nasal(naContext c, const T* arr, size_t size) { - std::vector vec(4); - vec[0] = rect.x(); - vec[1] = rect.y(); - vec[2] = rect.width(); - vec[3] = rect.height(); - - return to_nasal_helper(c, vec); + naRef ret = naNewVector(c); + naVec_setsize(c, ret, static_cast(size)); + for(int i = 0; i < static_cast(size); ++i) + naVec_set(ret, i, to_nasal_helper(c, arr[i])); + return ret; } //---------------------------------------------------------------------------- @@ -182,17 +211,6 @@ namespace nasal return hash; } - //---------------------------------------------------------------------------- - template - naRef to_nasal_helper(naContext c, const T(&array)[N]) - { - naRef ret = naNewVector(c); - naVec_setsize(c, ret, static_cast(N)); - for(int i = 0; i < static_cast(N); ++i) - naVec_set(ret, i, to_nasal_helper(c, array[i])); - return ret; - } - } // namespace nasal #endif /* SG_TO_NASAL_HELPER_HXX_ */ diff --git a/simgear/nasal/cppbind/test/cppbind_test.cxx b/simgear/nasal/cppbind/test/cppbind_test.cxx index f2c704ef..8583a304 100644 --- a/simgear/nasal/cppbind/test/cppbind_test.cxx +++ b/simgear/nasal/cppbind/test/cppbind_test.cxx @@ -117,6 +117,51 @@ naRef f_derivedGetX(const Derived& d, naContext c) } naRef f_freeFunction(nasal::CallContext c) { return c.requireArg(0); } +namespace std +{ + template + ostream& operator<<(ostream& strm, const array& vec) + { + for(auto const& v: vec) + strm << "'" << v << "',"; + return strm; + } +} + +BOOST_AUTO_TEST_CASE( cppbind_arrays ) +{ + TestContext ctx; + + naRef na_vec = ctx.to_nasal({1., 2., 3.42}); + BOOST_REQUIRE( naIsVector(na_vec) ); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 0)), 1); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 1)), 2); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 2)), 3.42); + + na_vec = ctx.to_nasal(std::initializer_list({1., 2., 3.42})); + BOOST_REQUIRE( naIsVector(na_vec) ); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 0)), 1); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 1)), 2); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 2)), 3.42); + + using arr_d3_t = std::array; + arr_d3_t std_arr = {1., 2., 3.42}; + na_vec = ctx.to_nasal(std_arr); + BOOST_REQUIRE( naIsVector(na_vec) ); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 0)), 1); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 1)), 2); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 2)), 3.42); + + double d_arr[] = {1., 2., 3.42}; + na_vec = ctx.to_nasal(d_arr); + BOOST_REQUIRE( naIsVector(na_vec) ); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 0)), 1); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 1)), 2); + BOOST_CHECK_EQUAL(ctx.from_nasal(naVec_get(na_vec, 2)), 3.42); + + BOOST_CHECK_EQUAL(std_arr, ctx.from_nasal(na_vec)); +} + BOOST_AUTO_TEST_CASE( cppbind_misc_testing ) { TestContext c;