rice 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -0
  3. data/CONTRIBUTORS.md +19 -0
  4. data/Gemfile +3 -0
  5. data/README.md +44 -1025
  6. data/Rakefile +95 -12
  7. data/include/rice/rice.hpp +7766 -0
  8. data/lib/mkmf-rice.rb +127 -0
  9. data/lib/version.rb +3 -0
  10. data/rice/Address_Registration_Guard.ipp +75 -32
  11. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  12. data/rice/Arg.hpp +80 -4
  13. data/rice/Arg.ipp +51 -0
  14. data/rice/Constructor.hpp +12 -14
  15. data/rice/Data_Object.ipp +234 -107
  16. data/rice/Data_Object_defn.hpp +77 -117
  17. data/rice/Data_Type.hpp +1 -2
  18. data/rice/Data_Type.ipp +251 -295
  19. data/rice/Data_Type_defn.hpp +175 -243
  20. data/rice/Director.hpp +11 -6
  21. data/rice/Enum.hpp +54 -104
  22. data/rice/Enum.ipp +104 -230
  23. data/rice/Exception.hpp +2 -8
  24. data/rice/Exception.ipp +65 -0
  25. data/rice/Exception_defn.hpp +46 -47
  26. data/rice/Identifier.hpp +28 -28
  27. data/rice/Identifier.ipp +23 -27
  28. data/rice/Return.hpp +39 -0
  29. data/rice/Return.ipp +33 -0
  30. data/rice/detail/Exception_Handler.ipp +22 -62
  31. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  32. data/rice/detail/Iterator.hpp +18 -88
  33. data/rice/detail/Iterator.ipp +47 -0
  34. data/rice/detail/Jump_Tag.hpp +21 -0
  35. data/rice/detail/MethodInfo.hpp +44 -0
  36. data/rice/detail/MethodInfo.ipp +78 -0
  37. data/rice/detail/NativeAttribute.hpp +53 -0
  38. data/rice/detail/NativeAttribute.ipp +83 -0
  39. data/rice/detail/NativeFunction.hpp +69 -0
  40. data/rice/detail/NativeFunction.ipp +248 -0
  41. data/rice/detail/RubyFunction.hpp +39 -0
  42. data/rice/detail/RubyFunction.ipp +92 -0
  43. data/rice/detail/Type.hpp +29 -0
  44. data/rice/detail/Type.ipp +138 -0
  45. data/rice/detail/TypeRegistry.hpp +50 -0
  46. data/rice/detail/TypeRegistry.ipp +106 -0
  47. data/rice/detail/Wrapper.hpp +51 -0
  48. data/rice/detail/Wrapper.ipp +151 -0
  49. data/rice/detail/default_allocation_func.hpp +8 -19
  50. data/rice/detail/default_allocation_func.ipp +9 -8
  51. data/rice/detail/from_ruby.hpp +2 -37
  52. data/rice/detail/from_ruby.ipp +1020 -46
  53. data/rice/detail/from_ruby_defn.hpp +38 -0
  54. data/rice/detail/function_traits.hpp +124 -0
  55. data/rice/detail/method_data.hpp +23 -15
  56. data/rice/detail/method_data.ipp +53 -0
  57. data/rice/detail/rice_traits.hpp +116 -0
  58. data/rice/detail/ruby.hpp +9 -46
  59. data/rice/detail/to_ruby.hpp +3 -17
  60. data/rice/detail/to_ruby.ipp +409 -31
  61. data/rice/detail/to_ruby_defn.hpp +48 -0
  62. data/rice/forward_declares.ipp +82 -0
  63. data/rice/global_function.hpp +16 -20
  64. data/rice/global_function.ipp +8 -17
  65. data/rice/rice.hpp +59 -0
  66. data/rice/ruby_mark.hpp +5 -3
  67. data/rice/ruby_try_catch.hpp +4 -4
  68. data/rice/stl.hpp +11 -0
  69. data/sample/callbacks/extconf.rb +3 -0
  70. data/sample/callbacks/sample_callbacks.cpp +10 -13
  71. data/sample/enum/extconf.rb +3 -0
  72. data/sample/enum/sample_enum.cpp +3 -17
  73. data/sample/enum/test.rb +2 -2
  74. data/sample/inheritance/animals.cpp +8 -24
  75. data/sample/inheritance/extconf.rb +3 -0
  76. data/sample/inheritance/test.rb +1 -1
  77. data/sample/map/extconf.rb +3 -0
  78. data/sample/map/map.cpp +10 -18
  79. data/sample/map/test.rb +1 -1
  80. data/test/embed_ruby.cpp +18 -5
  81. data/test/ext/t1/extconf.rb +3 -0
  82. data/test/ext/t1/t1.cpp +1 -3
  83. data/test/ext/t2/extconf.rb +3 -0
  84. data/test/ext/t2/t2.cpp +1 -1
  85. data/test/extconf.rb +23 -0
  86. data/test/ruby/test_callbacks_sample.rb +28 -0
  87. data/test/ruby/test_multiple_extensions.rb +18 -0
  88. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  89. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  90. data/test/test_Address_Registration_Guard.cpp +23 -10
  91. data/test/test_Array.cpp +129 -73
  92. data/test/test_Attribute.cpp +147 -0
  93. data/test/test_Builtin_Object.cpp +34 -14
  94. data/test/test_Class.cpp +149 -275
  95. data/test/test_Constructor.cpp +10 -9
  96. data/test/test_Data_Object.cpp +133 -192
  97. data/test/test_Data_Type.cpp +322 -252
  98. data/test/test_Director.cpp +54 -41
  99. data/test/test_Enum.cpp +228 -103
  100. data/test/test_Exception.cpp +5 -6
  101. data/test/test_Hash.cpp +31 -30
  102. data/test/test_Identifier.cpp +4 -5
  103. data/test/test_Inheritance.cpp +221 -0
  104. data/test/test_Iterator.cpp +161 -0
  105. data/test/test_Jump_Tag.cpp +1 -1
  106. data/test/test_Keep_Alive.cpp +161 -0
  107. data/test/test_Memory_Management.cpp +2 -4
  108. data/test/test_Module.cpp +167 -110
  109. data/test/test_Object.cpp +41 -21
  110. data/test/test_Ownership.cpp +275 -0
  111. data/test/test_Self.cpp +205 -0
  112. data/test/test_Stl_Optional.cpp +90 -0
  113. data/test/test_Stl_Pair.cpp +144 -0
  114. data/test/test_Stl_SmartPointer.cpp +200 -0
  115. data/test/test_Stl_String.cpp +74 -0
  116. data/test/test_Stl_Vector.cpp +652 -0
  117. data/test/test_String.cpp +1 -2
  118. data/test/test_Struct.cpp +29 -39
  119. data/test/test_Symbol.cpp +1 -2
  120. data/test/test_To_From_Ruby.cpp +249 -285
  121. data/test/test_global_functions.cpp +39 -19
  122. data/test/unittest.hpp +0 -4
  123. metadata +63 -139
  124. data/Doxyfile +0 -2268
  125. data/Makefile.am +0 -26
  126. data/Makefile.in +0 -931
  127. data/README.mingw +0 -8
  128. data/aclocal.m4 +0 -1085
  129. data/ax_cxx_compile_stdcxx.m4 +0 -951
  130. data/bootstrap +0 -8
  131. data/config.guess +0 -1421
  132. data/config.sub +0 -1807
  133. data/configure +0 -7792
  134. data/configure.ac +0 -55
  135. data/depcomp +0 -791
  136. data/doxygen.ac +0 -314
  137. data/doxygen.am +0 -186
  138. data/extconf.rb +0 -70
  139. data/install-sh +0 -501
  140. data/missing +0 -215
  141. data/post-autoconf.rb +0 -22
  142. data/post-automake.rb +0 -28
  143. data/rice/Address_Registration_Guard.cpp +0 -22
  144. data/rice/Arg_impl.hpp +0 -129
  145. data/rice/Arg_operators.cpp +0 -21
  146. data/rice/Arg_operators.hpp +0 -19
  147. data/rice/Array.hpp +0 -214
  148. data/rice/Array.ipp +0 -256
  149. data/rice/Builtin_Object.hpp +0 -8
  150. data/rice/Builtin_Object.ipp +0 -50
  151. data/rice/Builtin_Object_defn.hpp +0 -50
  152. data/rice/Class.cpp +0 -57
  153. data/rice/Class.hpp +0 -8
  154. data/rice/Class.ipp +0 -6
  155. data/rice/Class_defn.hpp +0 -84
  156. data/rice/Data_Type.cpp +0 -54
  157. data/rice/Data_Type_fwd.hpp +0 -12
  158. data/rice/Director.cpp +0 -13
  159. data/rice/Exception.cpp +0 -54
  160. data/rice/Exception_Base.hpp +0 -8
  161. data/rice/Exception_Base.ipp +0 -13
  162. data/rice/Exception_Base_defn.hpp +0 -27
  163. data/rice/Hash.hpp +0 -230
  164. data/rice/Hash.ipp +0 -329
  165. data/rice/Identifier.cpp +0 -8
  166. data/rice/Jump_Tag.hpp +0 -24
  167. data/rice/Makefile.am +0 -121
  168. data/rice/Makefile.in +0 -884
  169. data/rice/Module.cpp +0 -84
  170. data/rice/Module.hpp +0 -8
  171. data/rice/Module.ipp +0 -6
  172. data/rice/Module_defn.hpp +0 -88
  173. data/rice/Module_impl.hpp +0 -281
  174. data/rice/Module_impl.ipp +0 -345
  175. data/rice/Object.cpp +0 -169
  176. data/rice/Object.hpp +0 -8
  177. data/rice/Object.ipp +0 -33
  178. data/rice/Object_defn.hpp +0 -214
  179. data/rice/Require_Guard.hpp +0 -21
  180. data/rice/String.cpp +0 -89
  181. data/rice/String.hpp +0 -91
  182. data/rice/Struct.cpp +0 -117
  183. data/rice/Struct.hpp +0 -162
  184. data/rice/Struct.ipp +0 -26
  185. data/rice/Symbol.cpp +0 -25
  186. data/rice/Symbol.hpp +0 -66
  187. data/rice/Symbol.ipp +0 -44
  188. data/rice/config.hpp +0 -47
  189. data/rice/config.hpp.in +0 -46
  190. data/rice/detail/Arguments.hpp +0 -118
  191. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  192. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3181
  193. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  194. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2501
  195. data/rice/detail/Caster.hpp +0 -103
  196. data/rice/detail/Not_Copyable.hpp +0 -25
  197. data/rice/detail/Wrapped_Function.hpp +0 -33
  198. data/rice/detail/cfp.hpp +0 -24
  199. data/rice/detail/cfp.ipp +0 -51
  200. data/rice/detail/check_ruby_type.cpp +0 -27
  201. data/rice/detail/check_ruby_type.hpp +0 -23
  202. data/rice/detail/creation_funcs.hpp +0 -37
  203. data/rice/detail/creation_funcs.ipp +0 -36
  204. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  205. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  206. data/rice/detail/demangle.cpp +0 -56
  207. data/rice/detail/demangle.hpp +0 -19
  208. data/rice/detail/env.hpp +0 -11
  209. data/rice/detail/method_data.cpp +0 -92
  210. data/rice/detail/node.hpp +0 -13
  211. data/rice/detail/protect.cpp +0 -29
  212. data/rice/detail/protect.hpp +0 -34
  213. data/rice/detail/ruby_version_code.hpp +0 -6
  214. data/rice/detail/ruby_version_code.hpp.in +0 -6
  215. data/rice/detail/st.hpp +0 -22
  216. data/rice/detail/win32.hpp +0 -16
  217. data/rice/detail/wrap_function.hpp +0 -66
  218. data/rice/protect.hpp +0 -38
  219. data/rice/protect.ipp +0 -1134
  220. data/rice/rubypp.rb +0 -97
  221. data/rice/to_from_ruby.hpp +0 -8
  222. data/rice/to_from_ruby.ipp +0 -418
  223. data/rice/to_from_ruby_defn.hpp +0 -70
  224. data/ruby.ac +0 -135
  225. data/ruby/Makefile.am +0 -1
  226. data/ruby/Makefile.in +0 -628
  227. data/ruby/lib/Makefile.am +0 -3
  228. data/ruby/lib/Makefile.in +0 -506
  229. data/ruby/lib/mkmf-rice.rb.in +0 -217
  230. data/ruby/lib/version.rb +0 -3
  231. data/sample/Makefile.am +0 -53
  232. data/sample/Makefile.in +0 -495
  233. data/test/Makefile.am +0 -73
  234. data/test/Makefile.in +0 -1219
  235. data/test/ext/Makefile.am +0 -41
  236. data/test/ext/Makefile.in +0 -483
  237. data/test/test_rice.rb +0 -45
@@ -0,0 +1,39 @@
1
+ #ifndef Rice__detail__ruby_function__hpp_
2
+ #define Rice__detail__ruby_function__hpp_
3
+
4
+ #include "ruby.hpp"
5
+
6
+ namespace Rice::detail
7
+ {
8
+ /* This is functor class that wraps calls to a Ruby C API method. It is needed because
9
+ rb_protect only supports calling methods that take one argument. Thus
10
+ we invoke rb_protect telling it to invoke Ruby_Function::call with an
11
+ instance of a Ruby_Function. That instance then in turn calls the original
12
+ Ruby method passing along its required arguments. */
13
+
14
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
15
+ class RubyFunction
16
+ {
17
+ public:
18
+ RubyFunction(Function_T func, const Arg_Ts&... args);
19
+ Return_T operator()();
20
+
21
+ private:
22
+ Function_T func_;
23
+ std::tuple<Arg_Ts...> args_;
24
+ };
25
+
26
+ template<typename Return_T, typename ...Arg_Ts>
27
+ Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args);
28
+ }
29
+
30
+ namespace Rice
31
+ {
32
+ template<typename Return_T, typename ...Arg_Ts>
33
+ [[deprecated("Please use detail::protect")]]
34
+ Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args);
35
+ }
36
+
37
+ #include "RubyFunction.ipp"
38
+
39
+ #endif // Rice__detail__ruby_function__hpp_
@@ -0,0 +1,92 @@
1
+ #include "Jump_Tag.hpp"
2
+ #include "../Exception_defn.hpp"
3
+
4
+ #include <any>
5
+
6
+ namespace Rice::detail
7
+ {
8
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
9
+ inline RubyFunction<Function_T, Return_T, Arg_Ts...>::RubyFunction(Function_T func, const Arg_Ts&... args)
10
+ : func_(func), args_(std::forward_as_tuple(args...))
11
+ {
12
+ }
13
+
14
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
15
+ inline Return_T RubyFunction<Function_T, Return_T, Arg_Ts...>::operator()()
16
+ {
17
+ const int TAG_RAISE = 0x6; // From Ruby header files
18
+ int state = 0;
19
+
20
+ // Setup a thread local variable to capture the result of the Ruby function call.
21
+ // We use thread_local because the lambda has to be captureless so it can
22
+ // be converted to a function pointer callable by C.
23
+ // The thread local variable avoids having to cast the result to VALUE and then
24
+ // back again to Return_T. The problem with that is the translation is not lossless
25
+ // in some cases - for example a double with value of -1.0 does not roundrip.
26
+ //
27
+ thread_local std::any result;
28
+
29
+ // Callback that will invoke the Ruby function
30
+ using Functor_T = RubyFunction<Function_T, Return_T, Arg_Ts...>;
31
+ auto callback = [](VALUE value)
32
+ {
33
+ Functor_T* functor = (Functor_T*)value;
34
+
35
+ if constexpr (std::is_same_v<Return_T, void>)
36
+ {
37
+ std::apply(functor->func_, functor->args_);
38
+ }
39
+ else
40
+ {
41
+ result = std::apply(functor->func_, functor->args_);
42
+ }
43
+
44
+ return Qnil;
45
+ };
46
+
47
+ // Now call rb_protect which will invoke the callback lambda above
48
+ rb_protect(callback, (VALUE)this, &state);
49
+
50
+ // Did anything go wrong?
51
+ if (state == 0)
52
+ {
53
+ if constexpr (!std::is_same_v<Return_T, void>)
54
+ {
55
+ return std::any_cast<Return_T>(result);
56
+ }
57
+ }
58
+ else
59
+ {
60
+ VALUE err = rb_errinfo();
61
+ if (state == TAG_RAISE && RTEST(err))
62
+ {
63
+ rb_set_errinfo(Qnil);
64
+ throw Rice::Exception(err);
65
+ }
66
+ else
67
+ {
68
+ throw Jump_Tag(state);
69
+ }
70
+ }
71
+ }
72
+
73
+ // Create a functor for calling a Ruby function and define some aliases for readability.
74
+ template<typename Return_T, typename ...Arg_Ts>
75
+ inline Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args)
76
+ {
77
+ using Function_T = Return_T(*)(Arg_Ts...);
78
+ auto rubyFunction = RubyFunction<Function_T, Return_T, Arg_Ts...>(func, args...);
79
+ return rubyFunction();
80
+ }
81
+ }
82
+
83
+ namespace Rice
84
+ {
85
+ template<typename Return_T, typename ...Arg_Ts>
86
+ inline Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args)
87
+ {
88
+ using Function_T = Return_T(*)(Arg_Ts...);
89
+ auto rubyFunction = detail::RubyFunction<Function_T, Return_T, Arg_Ts...>(func, args...);
90
+ return rubyFunction();
91
+ }
92
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef Rice__Type__hpp_
2
+ #define Rice__Type__hpp_
3
+
4
+ #include <string>
5
+ #include <typeinfo>
6
+ #include "rice_traits.hpp"
7
+
8
+ namespace Rice::detail
9
+ {
10
+ template<typename T>
11
+ struct Type
12
+ {
13
+ static bool verify();
14
+ };
15
+
16
+ // Return the name of a type
17
+ std::string typeName(const std::type_info& typeInfo);
18
+ std::string makeClassName(const std::type_info& typeInfo);
19
+
20
+ template<typename T>
21
+ void verifyType();
22
+
23
+ template<typename Tuple_T>
24
+ void verifyTypes();
25
+ }
26
+
27
+ #include "Type.ipp"
28
+
29
+ #endif // Rice__Type__hpp_
@@ -0,0 +1,138 @@
1
+ #include "rice_traits.hpp"
2
+
3
+ #include <iosfwd>
4
+ #include <numeric>
5
+ #include <regex>
6
+ #include <sstream>
7
+ #include <tuple>
8
+
9
+ #ifdef __GNUC__
10
+ #include <cxxabi.h>
11
+ #include <cstdlib>
12
+ #include <cstring>
13
+ #endif
14
+
15
+ namespace Rice::detail
16
+ {
17
+ template<>
18
+ struct Type<void>
19
+ {
20
+ static bool verify()
21
+ {
22
+ return true;
23
+ }
24
+ };
25
+
26
+ template<typename T>
27
+ void verifyType()
28
+ {
29
+ Type<intrinsic_type<T>>::verify();
30
+ }
31
+
32
+ template<typename Tuple_T, size_t...Is>
33
+ void verifyTypesImpl()
34
+ {
35
+ (Type<intrinsic_type<typename std::tuple_element<Is, Tuple_T>::type>>::verify(), ...);
36
+ }
37
+
38
+ template<typename Tuple_T>
39
+ void verifyTypes()
40
+ {
41
+ if constexpr (std::tuple_size<Tuple_T>::value > 0)
42
+ {
43
+ verifyTypesImpl<Tuple_T, std::tuple_size<Tuple_T>::value - 1>();
44
+ }
45
+ }
46
+
47
+ inline std::string demangle(char const* mangled_name)
48
+ {
49
+ #ifdef __GNUC__
50
+ struct Helper
51
+ {
52
+ Helper(
53
+ char const* mangled_name)
54
+ : name_(0)
55
+ {
56
+ int status = 0;
57
+ name_ = abi::__cxa_demangle(mangled_name, 0, 0, &status);
58
+ }
59
+
60
+ ~Helper()
61
+ {
62
+ std::free(name_);
63
+ }
64
+
65
+ char* name_;
66
+
67
+ private:
68
+ Helper(Helper const&);
69
+ void operator=(Helper const&);
70
+ };
71
+
72
+ Helper helper(mangled_name);
73
+ if (helper.name_)
74
+ {
75
+ return helper.name_;
76
+ }
77
+ else
78
+ {
79
+ return mangled_name;
80
+ }
81
+ #else
82
+ return mangled_name;
83
+ #endif
84
+ }
85
+
86
+ inline std::string typeName(const std::type_info& typeInfo)
87
+ {
88
+ return demangle(typeInfo.name());
89
+ }
90
+
91
+ inline std::string makeClassName(const std::type_info& typeInfo)
92
+ {
93
+ std::string base = demangle(typeInfo.name());
94
+
95
+ // Remove class keyword
96
+ auto classRegex = std::regex("class +");
97
+ base = std::regex_replace(base, classRegex, "");
98
+
99
+ // Remove struct keyword
100
+ auto structRegex = std::regex("struct +");
101
+ base = std::regex_replace(base, structRegex, "");
102
+
103
+ // Remove std::__[^:]*::
104
+ auto stdClangRegex = std::regex("std::__[^:]+::");
105
+ base = std::regex_replace(base, stdClangRegex, "");
106
+
107
+ // Remove std::
108
+ auto stdRegex = std::regex("std::");
109
+ base = std::regex_replace(base, stdRegex, "");
110
+
111
+ // Replace > >
112
+ auto trailingAngleBracketSpaceRegex = std::regex(" >");
113
+ base = std::regex_replace(base, trailingAngleBracketSpaceRegex, ">");
114
+
115
+ // Replace < and >
116
+ auto angleBracketRegex = std::regex("<|>");
117
+ base = std::regex_replace(base, angleBracketRegex, "__");
118
+
119
+ // Replace ,
120
+ auto commaRegex = std::regex(", *");
121
+ base = std::regex_replace(base, commaRegex, "_");
122
+
123
+ // Now create a vector of strings split on whitespace
124
+ std::istringstream stream(base);
125
+ std::vector<std::string> words{ std::istream_iterator<std::string>{stream},
126
+ std::istream_iterator<std::string>{} };
127
+
128
+ std::string result = std::accumulate(words.begin(), words.end(), std::string(),
129
+ [](const std::string& memo, const std::string& word) -> std::string
130
+ {
131
+ std::string capitalized = word;
132
+ capitalized[0] = toupper(capitalized[0]);
133
+ return memo + capitalized;
134
+ });
135
+
136
+ return result;
137
+ }
138
+ }
@@ -0,0 +1,50 @@
1
+ #ifndef Rice__TypeRegistry__hpp_
2
+ #define Rice__TypeRegistry__hpp_
3
+
4
+ #include <optional>
5
+ #include <string>
6
+ #include <typeindex>
7
+ #include <typeinfo>
8
+ #include <unordered_map>
9
+
10
+ #include "ruby.hpp"
11
+
12
+ /* The type registery keeps track of all C++ types wrapped by Rice. When a native function returns
13
+ an instance of a class/struct we look up its type to verity that it has been registered.
14
+
15
+ We have to do this to support C++ inheritance. If a C++ function returns a pointer/reference
16
+ to an Abstract class, the actual returned object will be a Child class. However, all we know
17
+ from the C++ method signature is that it is an Absract class - thus the need for a registry.*/
18
+
19
+ namespace Rice::detail
20
+ {
21
+ class TypeRegistry
22
+ {
23
+ public:
24
+ template <typename T>
25
+ static void add();
26
+
27
+ template <typename T>
28
+ static void add(VALUE klass, rb_data_type_t* rbType);
29
+
30
+ template <typename T>
31
+ static void remove();
32
+
33
+ template <typename T>
34
+ static bool isDefined();
35
+
36
+ template <typename T>
37
+ static void verifyDefined();
38
+
39
+ template <typename T>
40
+ static std::pair<VALUE, rb_data_type_t*> figureType(const T& object);
41
+
42
+ private:
43
+ static std::optional<std::pair<VALUE, rb_data_type_t*>> lookup(const std::type_info& typeInfo);
44
+ static inline std::unordered_map<std::type_index, std::pair<VALUE, rb_data_type_t*>> registry_{};
45
+ };
46
+ }
47
+
48
+ #include "TypeRegistry.ipp"
49
+
50
+ #endif // Rice__TypeRegistry__hpp_
@@ -0,0 +1,106 @@
1
+ #include <stdexcept>
2
+
3
+ #include "ruby.hpp"
4
+ #include "rice_traits.hpp"
5
+ #include "Type.hpp"
6
+
7
+ namespace Rice::detail
8
+ {
9
+ template <typename T>
10
+ inline void TypeRegistry::add()
11
+ {
12
+ std::type_index key(typeid(T));
13
+ registry_[key] = std::pair(Qnil, nullptr);
14
+ }
15
+
16
+ template <typename T>
17
+ inline void TypeRegistry::add(VALUE klass, rb_data_type_t* rbType)
18
+ {
19
+ std::type_index key(typeid(T));
20
+ registry_[key] = std::pair(klass, rbType);
21
+ }
22
+
23
+ template <typename T>
24
+ inline void TypeRegistry::remove()
25
+ {
26
+ std::type_index key(typeid(T));
27
+ registry_.erase(key);
28
+ }
29
+
30
+ template <typename T>
31
+ inline bool TypeRegistry::isDefined()
32
+ {
33
+ std::type_index key(typeid(T));
34
+ auto iter = registry_.find(key);
35
+ return iter != registry_.end();
36
+ }
37
+
38
+ template <typename T>
39
+ inline void TypeRegistry::verifyDefined()
40
+ {
41
+ if (!isDefined<T>())
42
+ {
43
+ std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T));
44
+ throw std::invalid_argument(message);
45
+ }
46
+ }
47
+
48
+ inline std::optional<std::pair<VALUE, rb_data_type_t*>> TypeRegistry::lookup(const std::type_info& typeInfo)
49
+ {
50
+ std::type_index key(typeInfo);
51
+ auto iter = registry_.find(key);
52
+
53
+ if (iter == registry_.end())
54
+ {
55
+ return std::nullopt;
56
+ }
57
+ else
58
+ {
59
+ return iter->second;
60
+ }
61
+ }
62
+
63
+ template <typename T>
64
+ inline std::pair<VALUE, rb_data_type_t*> TypeRegistry::figureType(const T& object)
65
+ {
66
+ // First check and see if the actual type of the object is registered
67
+ std::optional<std::pair<VALUE, rb_data_type_t*>> result = lookup(typeid(object));
68
+
69
+ if (result)
70
+ {
71
+ return result.value();
72
+ }
73
+
74
+ // If not, then we are willing to accept an ancestor class specified by T. This is needed
75
+ // to support Directors. Classes inherited from Directors are never actually registered
76
+ // with Rice - and what we really want it to return the C++ class they inherit from.
77
+ result = lookup(typeid(T));
78
+ if (result)
79
+ {
80
+ return result.value();
81
+ }
82
+
83
+ // Give up!
84
+ std::string message = "Type " + typeName(typeid(object)) + " is not registered";
85
+ throw std::runtime_error(message.c_str());
86
+ }
87
+
88
+ // TODO - hacky to put this here but there is a circular dependency between Type and TypeRegistry
89
+ template<typename T>
90
+ bool Type<T>::verify()
91
+ {
92
+ // Use intrinsic_type so that we don't have to define specializations
93
+ // for pointers, references, const, etc.
94
+ using Intrinsic_T = intrinsic_type<T>;
95
+
96
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
97
+ {
98
+ return true;
99
+ }
100
+ else
101
+ {
102
+ TypeRegistry::verifyDefined<Intrinsic_T>();
103
+ return true;
104
+ }
105
+ }
106
+ }