From 0fef94cfdbd51a0bbe3ab48d574f5aecc2323a3f Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sat, 10 Nov 2012 14:18:27 +0100 Subject: [PATCH] Add from_nasal helper and fix to_nasal for std::vector. --- simgear/nasal/cppbind/CMakeLists.txt | 3 + simgear/nasal/cppbind/cppbind_test.cxx | 21 +++- simgear/nasal/cppbind/from_nasal.cxx | 65 +++++++++++++ simgear/nasal/cppbind/from_nasal.hxx | 43 +++++++++ simgear/nasal/cppbind/from_nasal_detail.hxx | 101 ++++++++++++++++++++ simgear/nasal/cppbind/to_nasal.hxx | 14 ++- 6 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 simgear/nasal/cppbind/from_nasal.cxx create mode 100644 simgear/nasal/cppbind/from_nasal.hxx create mode 100644 simgear/nasal/cppbind/from_nasal_detail.hxx diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt index d77731a9..fecfb8ea 100644 --- a/simgear/nasal/cppbind/CMakeLists.txt +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -2,11 +2,14 @@ include (SimGearComponent) set(HEADERS NasalHash.hxx + from_nasal_detail.hxx + from_nasal.hxx to_nasal.hxx ) set(SOURCES NasalHash.cxx + from_nasal.cxx to_nasal.cxx ) diff --git a/simgear/nasal/cppbind/cppbind_test.cxx b/simgear/nasal/cppbind/cppbind_test.cxx index 48269a8e..6bf768a4 100644 --- a/simgear/nasal/cppbind/cppbind_test.cxx +++ b/simgear/nasal/cppbind/cppbind_test.cxx @@ -1,4 +1,6 @@ #include "NasalHash.hxx" +#include "from_nasal.hxx" +#include "to_nasal.hxx" #include #include @@ -19,19 +21,34 @@ int main(int argc, char* argv[]) r = to_nasal(c, "Test"); VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + VERIFY( from_nasal(c, r) == "Test" ); r = to_nasal(c, std::string("Test")); VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + VERIFY( from_nasal(c, r) == "Test" ); r = to_nasal(c, 42); VERIFY( naNumValue(r).num == 42 ); + VERIFY( from_nasal(c, r) == 42 ); - r = to_nasal(c, 4.2); - VERIFY( naNumValue(r).num == 4.2 ); + r = to_nasal(c, 4.2f); + VERIFY( naNumValue(r).num == 4.2f ); + VERIFY( from_nasal(c, r) == 4.2f ); std::vector vec; r = to_nasal(c, vec); + r = to_nasal(c, "string"); + try + { + from_nasal(c, r); + + std::cerr << "failed: Expected bad_nasal_cast to be thrown" << std::endl; + return 1; + } + catch(nasal::bad_nasal_cast&) + {} + Hash hash(c); hash.set("vec", r); hash.set("vec2", vec); diff --git a/simgear/nasal/cppbind/from_nasal.cxx b/simgear/nasal/cppbind/from_nasal.cxx new file mode 100644 index 00000000..03c4dc2e --- /dev/null +++ b/simgear/nasal/cppbind/from_nasal.cxx @@ -0,0 +1,65 @@ +// Conversion functions to convert Nasal types to C++ types +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "from_nasal_detail.hxx" +#include "NasalHash.hxx" + +namespace nasal +{ + //---------------------------------------------------------------------------- + bad_nasal_cast::bad_nasal_cast() + { + + } + + //---------------------------------------------------------------------------- + bad_nasal_cast::bad_nasal_cast(const std::string& msg): + _msg( msg ) + { + + } + + //---------------------------------------------------------------------------- + bad_nasal_cast::~bad_nasal_cast() throw() + { + + } + + //---------------------------------------------------------------------------- + const char* bad_nasal_cast::what() const throw() + { + return _msg.empty() ? bad_cast::what() : _msg.c_str(); + } + + //---------------------------------------------------------------------------- + std::string from_nasal(naContext c, naRef ref, std::string*) + { + naRef na_str = naStringValue(c, ref); + return std::string(naStr_data(na_str), naStr_len(na_str)); + } + + //---------------------------------------------------------------------------- + Hash from_nasal(naContext c, naRef ref, Hash*) + { + if( !naIsHash(ref) ) + throw bad_nasal_cast("Not a hash"); + + return Hash(ref, c); + } + +} // namespace nasal diff --git a/simgear/nasal/cppbind/from_nasal.hxx b/simgear/nasal/cppbind/from_nasal.hxx new file mode 100644 index 00000000..e9991cb6 --- /dev/null +++ b/simgear/nasal/cppbind/from_nasal.hxx @@ -0,0 +1,43 @@ +// Conversion functions to convert Nasal types to C++ types +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_FROM_NASAL_HXX_ +#define SG_FROM_NASAL_HXX_ + +#include "from_nasal_detail.hxx" + +namespace nasal +{ + + /** + * Convert a Nasal type to any supported C++ type. + * + * @note Every type which should be supported needs a function with the + * following signature declared: + * + * Type from_nasal(naContext, naRef, Type*) + */ + template + T from_nasal(naContext c, naRef ref) + { + return from_nasal(c, ref, static_cast(0)); + } + +} // namespace nasal + +#endif /* SG_FROM_NASAL_HXX_ */ diff --git a/simgear/nasal/cppbind/from_nasal_detail.hxx b/simgear/nasal/cppbind/from_nasal_detail.hxx new file mode 100644 index 00000000..d5db8cbd --- /dev/null +++ b/simgear/nasal/cppbind/from_nasal_detail.hxx @@ -0,0 +1,101 @@ +// Conversion helpers used by from_nasal(naContext, naRef) +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_FROM_NASAL_DETAIL_HXX_ +#define SG_FROM_NASAL_DETAIL_HXX_ + +#include + +#include +#include + +#include +#include // std::bad_cast +#include + +namespace nasal +{ + class Hash; + + /** + * Thrown when converting a type from/to Nasal has failed + */ + class bad_nasal_cast: + public std::bad_cast + { + public: + bad_nasal_cast(); + explicit bad_nasal_cast(const std::string& msg); + + virtual ~bad_nasal_cast() throw(); + virtual const char* what() const throw(); + + protected: + std::string _msg; + }; + + /** + * Convert Nasal string to std::string + */ + std::string from_nasal(naContext c, naRef ref, std::string*); + + /** + * Convert a Nasal hash to a nasal::Hash + */ + Hash from_nasal(naContext c, naRef ref, Hash*); + + /** + * Convert a Nasal number to a C++ numeric type + */ + template + typename boost::enable_if< boost::is_arithmetic, + T + >::type + from_nasal(naContext c, naRef ref, T*) + { + naRef num = naNumValue(ref); + if( !naIsNum(num) ) + throw bad_nasal_cast("Not a number"); + + return static_cast(num.num); + } + + /** + * Convert a Nasal vector to a std::vector + */ + template + typename boost::enable_if< boost::is_same >, + Vector + >::type + from_nasal(naContext c, naRef ref, Vector*) + { + if( !naIsVector(ref) ) + throw bad_nasal_cast("Not a vector"); + + int size = naVec_size(ref); + Vector vec(size); + + for(int i = 0; i < size; ++i) + vec[i] = from_nasal(c, naVec_get(ref, i)); + + return vec; + } + +} // namespace nasal + +#endif /* SG_FROM_NASAL_DETAIL_HXX_ */ diff --git a/simgear/nasal/cppbind/to_nasal.hxx b/simgear/nasal/cppbind/to_nasal.hxx index 1166a4f4..0fd230a0 100644 --- a/simgear/nasal/cppbind/to_nasal.hxx +++ b/simgear/nasal/cppbind/to_nasal.hxx @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -64,8 +64,16 @@ namespace nasal /** * Convert std::vector to Nasal vector */ - template - naRef to_nasal(naContext c, const std::vector& vec) + template< template class Vector, + class T, + class Alloc + > + typename boost::enable_if< boost::is_same< Vector, + std::vector + >, + naRef + >::type + to_nasal(naContext c, const Vector& vec) { naRef ret = naNewVector(c); naVec_setsize(c, ret, vec.size()); -- 2.39.5