Virtual Testbed
Ship dynamics simulator for extreme conditions
wrapper.hh
1 #ifndef VTESTBED_GUILE_WRAPPER_HH
2 #define VTESTBED_GUILE_WRAPPER_HH
3 
4 #include <libguile.h>
5 
6 #include <any>
7 #include <memory>
8 #include <typeinfo>
9 
10 #include <vtestbed/guile/base.hh>
11 
12 namespace vtb {
13 
14  namespace guile {
15 
16  template <class T> class Aspect;
17  template <class T> class Traits;
18  template <class T> class Wrapper;
19 
33  template <class T>
34  class Aspect: public T {
35 
36  private:
37  using base_type = T;
38  using wrapper_type = Wrapper<T>;
39 
40  private:
41  wrapper_type* _wrapper;
42 
43  public:
44  using base_type::base_type;
45 
46  inline Aspect(const T& rhs): T(rhs) {}
47  inline Aspect(T&& rhs): T(std::move(rhs)) {}
48  inline ~Aspect() { this->_wrapper->clear(); this->_wrapper = nullptr; }
49 
50  inline void wrapper(wrapper_type* rhs) { this->_wrapper = rhs; }
51  inline wrapper_type* wrapper() { return this->_wrapper; }
52  inline const wrapper_type* wrapper() const { return this->_wrapper; }
53 
54  };
55 
60  template <class T>
61  class Wrapper {
62 
63  public:
64  using value_type = Aspect<T>;
65 
66  private:
67  value_type* _ptr = nullptr;
68 
69  public:
70  inline value_type* ptr() { return this->_ptr; }
71  inline T* get() { return this->_ptr; }
72  inline const T* get() const { return this->_ptr; }
73  inline void set(value_type* rhs) { this->_ptr = rhs; }
74  inline void release() { delete this->_ptr; this->_ptr = nullptr; }
75  inline void clear() { this->_ptr = nullptr; }
76  inline value_type* copy() { return new value_type(*this->_ptr); }
77 
78  };
79 
80  template <class T>
81  class Wrapper<std::unique_ptr<T>> {
82 
83  public:
84  using value_type = std::unique_ptr<T>;
85 
86  private:
87  value_type _ptr;
88 
89  public:
90  inline value_type& get() { return this->_ptr; }
91  inline const T& get() const { return this->_ptr; }
92  inline void set(value_type&& rhs) { this->_ptr = std::move(rhs); }
93  inline void release() { this->_ptr.reset(); }
94  inline void clear() { this->_ptr.reset(); }
95 
96  };
97 
98  template <>
99  class Wrapper<std::any> {
100 
101  public:
102  using value_type = std::any;
103 
104  private:
105  value_type _any;
106 
107  public:
108  inline value_type& get() { return this->_any; }
109  inline const value_type& get() const { return this->_any; }
110  inline void set(value_type&& rhs) { this->_any = std::move(rhs); }
111  inline void set(const value_type& rhs) { this->_any = rhs; }
112  inline void release() { this->_any.reset(); }
113  inline void clear() { this->_any.reset(); }
114 
115  };
116 
117  template <class T> inline Wrapper<T>*
118  to_wrapper(SCM object) {
119  return reinterpret_cast<Wrapper<T>*>(scm_foreign_object_ref(object, 0));
120  }
121 
122  template <class T> inline void
123  finalize(SCM object) {
124  to_wrapper<T>(object)->release();
125  }
126 
127  template <class T> inline SCM
128  make_type(const char* name) {
129  return scm_make_foreign_object_type(scm_from_utf8_symbol(name),
130  scm_list_1(scm_from_utf8_symbol("pointer")),
131  finalize<T>);
132  }
133 
134  template <class T> inline SCM
135  define_type(const char* name) {
136  SCM type = make_type<T>(name);
137  scm_c_define(name, type);
138  return type;
139  }
140 
141  template <class T> inline Wrapper<T>*
142  make_wrapper(Aspect<T>* ptr) {
143  auto* wrapper = allocate<Wrapper<T>>(typeid(T).name());
144  ptr->wrapper(wrapper);
145  wrapper->set(ptr);
146  return wrapper;
147  }
148 
149  template <class T> inline Wrapper<std::unique_ptr<T>>*
150  make_wrapper(std::unique_ptr<T>&& ptr) {
151  auto* wrapper = allocate<Wrapper<std::unique_ptr<T>>>(typeid(T).name());
152  wrapper->set(std::move(ptr));
153  return wrapper;
154  }
155 
156  inline Wrapper<std::any>*
157  make_wrapper(std::any&& any) {
158  auto* wrapper = allocate<Wrapper<std::any>>(any.type().name());
159  wrapper->set(std::move(any));
160  return wrapper;
161  }
162 
163  inline Wrapper<std::any>*
164  make_wrapper(const std::any& any) {
165  auto* wrapper = allocate<Wrapper<std::any>>(any.type().name());
166  wrapper->set(any);
167  return wrapper;
168  }
169 
170  template <class T> inline Wrapper<T>*
171  make_wrapper() {
172  return make_wrapper<T>(new Aspect<T>);
173  }
174 
175  template <class T> inline SCM
176  make_object(SCM type, Wrapper<T>* wrapper) {
177  return scm_make_foreign_object_1(type, wrapper);
178  }
179 
180  template <class T> inline SCM
181  make_object(SCM type, Aspect<T>* ptr) {
182  return make_object<T>(type, make_wrapper<T>(ptr));
183  }
184 
185  template <class T> inline SCM
186  make_object(SCM type, std::unique_ptr<T>&& ptr) {
187  return make_object<std::unique_ptr<T>>(type, make_wrapper<T>(std::move(ptr)));
188  }
189 
190  inline SCM
191  make_object(SCM type, std::any&& any) {
192  return make_object<std::any>(type, make_wrapper(std::move(any)));
193  }
194 
195  inline SCM
196  make_object(SCM type, const std::any& any) {
197  return make_object<std::any>(type, make_wrapper(any));
198  }
199 
200  template <class T> inline SCM
201  make_object(SCM type) {
202  return make_object<T>(type, make_wrapper<T>());
203  }
204 
205  }
206 
207 }
208 
209 #endif // vim:filetype=cpp
Aspect that extends Guile-unaware classes and provides a pointer to the corresponding wrapper object.
Definition: wrapper.hh:16
Foreign object wrapper.
Definition: wrapper.hh:18
Main namespace.
Definition: convert.hh:9