]> git.mxchange.org Git - simgear.git/blob - simgear/nasal/cppbind/from_nasal_detail.hxx
cppbind: Allow getter without from_nasal defined and setter without to_nasal.
[simgear.git] / simgear / nasal / cppbind / from_nasal_detail.hxx
1 ///@file
2 /// Conversion helpers used by from_nasal<T>(naContext, naRef)
3 ///
4 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Library General Public
8 // License as published by the Free Software Foundation; either
9 // version 2 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
19
20 #ifndef SG_FROM_NASAL_DETAIL_HXX_
21 #define SG_FROM_NASAL_DETAIL_HXX_
22
23 #include "nasal_traits.hxx"
24
25 #include <simgear/nasal/nasal.h>
26
27 #include <boost/utility/enable_if.hpp>
28 #include <boost/type_traits.hpp>
29
30 #include <string>
31 #include <typeinfo> // std::bad_cast
32 #include <vector>
33
34 class SGPath;
35
36 namespace nasal
37 {
38   class Hash;
39   class String;
40
41   /**
42    * Thrown when converting a type from/to Nasal has failed
43    */
44   class bad_nasal_cast:
45     public std::bad_cast
46   {
47     public:
48       /**
49        * Construct with generic error message
50        */
51       bad_nasal_cast();
52
53       /**
54        * Construct from an error message
55        *
56        * @param msg Error message/description
57        */
58       explicit bad_nasal_cast(const std::string& msg);
59
60       virtual ~bad_nasal_cast() throw();
61
62       /**
63        * Get a description of the cause of the failed cast.
64        */
65       virtual const char* what() const throw();
66
67     protected:
68       std::string _msg;
69   };
70
71   /**
72    * Simple pass through for unified handling also of naRef.
73    */
74   inline naRef from_nasal_helper(naContext, naRef ref, const naRef*)
75   { return ref; }
76
77   /**
78    * Convert Nasal string to std::string
79    */
80   std::string from_nasal_helper(naContext c, naRef ref, const std::string*);
81
82   /**
83    * Convert a Nasal string to an SGPath
84    */
85   SGPath from_nasal_helper(naContext c, naRef ref, const SGPath*);
86
87   /**
88    * Convert a Nasal hash to a nasal::Hash
89    */
90   Hash from_nasal_helper(naContext c, naRef ref, const Hash*);
91
92   /**
93    * Convert a Nasal string to a nasal::String
94    */
95   String from_nasal_helper(naContext c, naRef ref, const String*);
96
97   /**
98    * Convert a Nasal number to a C++ numeric type
99    */
100   template<class T>
101   typename boost::enable_if< boost::is_arithmetic<T>,
102                              T
103                            >::type
104   from_nasal_helper(naContext c, naRef ref, const T*)
105   {
106     naRef num = naNumValue(ref);
107     if( !naIsNum(num) )
108       throw bad_nasal_cast("Not a number");
109
110     return static_cast<T>(num.num);
111   }
112
113   /**
114    * Convert a Nasal vector to a std::vector
115    */
116   template<class T>
117   std::vector<T>
118   from_nasal_helper(naContext c, naRef ref, const std::vector<T>*)
119   {
120     if( !naIsVector(ref) )
121       throw bad_nasal_cast("Not a vector");
122
123     int size = naVec_size(ref);
124     std::vector<T> vec(size);
125
126     for(int i = 0; i < size; ++i)
127       vec[i] = from_nasal_helper(c, naVec_get(ref, i), static_cast<T*>(0));
128
129     return vec;
130   }
131
132   /**
133    * Convert a Nasal vector of 2 elements to a 2d vector
134    */
135   template<class Vec2>
136   typename boost::enable_if<is_vec2<Vec2>, Vec2>::type
137   from_nasal_helper(naContext c, naRef ref, const Vec2*)
138   {
139     std::vector<double> vec =
140       from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
141     if( vec.size() != 2 )
142       throw bad_nasal_cast("Expected vector with two elements");
143     return Vec2(vec[0], vec[1]);
144   }
145
146 } // namespace nasal
147
148 #endif /* SG_FROM_NASAL_DETAIL_HXX_ */