rice 2.1.2 → 4.0.1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +121 -0
- data/CONTRIBUTORS.md +19 -0
- data/COPYING +2 -2
- data/Gemfile +3 -0
- data/README.md +45 -1028
- data/Rakefile +95 -12
- data/include/rice/rice.hpp +7766 -0
- data/lib/mkmf-rice.rb +127 -0
- data/lib/version.rb +3 -0
- data/rice/Address_Registration_Guard.ipp +75 -32
- data/rice/Address_Registration_Guard_defn.hpp +60 -56
- data/rice/Arg.hpp +80 -4
- data/rice/Arg.ipp +51 -0
- data/rice/Constructor.hpp +30 -376
- data/rice/Data_Object.ipp +234 -107
- data/rice/Data_Object_defn.hpp +77 -117
- data/rice/Data_Type.hpp +1 -2
- data/rice/Data_Type.ipp +251 -295
- data/rice/Data_Type_defn.hpp +175 -243
- data/rice/Director.hpp +14 -9
- data/rice/Enum.hpp +54 -104
- data/rice/Enum.ipp +104 -230
- data/rice/Exception.hpp +2 -8
- data/rice/Exception.ipp +65 -0
- data/rice/Exception_defn.hpp +46 -47
- data/rice/Identifier.hpp +28 -28
- data/rice/Identifier.ipp +23 -27
- data/rice/Return.hpp +39 -0
- data/rice/Return.ipp +33 -0
- data/rice/detail/Exception_Handler.ipp +22 -62
- data/rice/detail/Exception_Handler_defn.hpp +76 -91
- data/rice/detail/Iterator.hpp +18 -88
- data/rice/detail/Iterator.ipp +47 -0
- data/rice/detail/Jump_Tag.hpp +21 -0
- data/rice/detail/MethodInfo.hpp +44 -0
- data/rice/detail/MethodInfo.ipp +78 -0
- data/rice/detail/NativeAttribute.hpp +53 -0
- data/rice/detail/NativeAttribute.ipp +83 -0
- data/rice/detail/NativeFunction.hpp +69 -0
- data/rice/detail/NativeFunction.ipp +248 -0
- data/rice/detail/RubyFunction.hpp +39 -0
- data/rice/detail/RubyFunction.ipp +92 -0
- data/rice/detail/Type.hpp +29 -0
- data/rice/detail/Type.ipp +138 -0
- data/rice/detail/TypeRegistry.hpp +50 -0
- data/rice/detail/TypeRegistry.ipp +106 -0
- data/rice/detail/Wrapper.hpp +51 -0
- data/rice/detail/Wrapper.ipp +151 -0
- data/rice/detail/default_allocation_func.hpp +8 -19
- data/rice/detail/default_allocation_func.ipp +9 -8
- data/rice/detail/from_ruby.hpp +2 -37
- data/rice/detail/from_ruby.ipp +1020 -46
- data/rice/detail/from_ruby_defn.hpp +38 -0
- data/rice/detail/function_traits.hpp +124 -0
- data/rice/detail/method_data.hpp +23 -15
- data/rice/detail/method_data.ipp +53 -0
- data/rice/detail/rice_traits.hpp +116 -0
- data/rice/detail/ruby.hpp +9 -49
- data/rice/detail/to_ruby.hpp +3 -17
- data/rice/detail/to_ruby.ipp +409 -31
- data/rice/detail/to_ruby_defn.hpp +48 -0
- data/rice/forward_declares.ipp +82 -0
- data/rice/global_function.hpp +16 -20
- data/rice/global_function.ipp +8 -17
- data/rice/rice.hpp +59 -0
- data/rice/ruby_mark.hpp +5 -3
- data/rice/ruby_try_catch.hpp +4 -4
- data/rice/stl.hpp +11 -0
- data/sample/callbacks/extconf.rb +6 -0
- data/sample/callbacks/sample_callbacks.cpp +35 -0
- data/sample/callbacks/test.rb +28 -0
- data/sample/enum/extconf.rb +3 -0
- data/sample/enum/sample_enum.cpp +3 -17
- data/sample/enum/test.rb +2 -2
- data/sample/inheritance/animals.cpp +8 -24
- data/sample/inheritance/extconf.rb +3 -0
- data/sample/inheritance/test.rb +1 -1
- data/sample/map/extconf.rb +3 -0
- data/sample/map/map.cpp +10 -18
- data/sample/map/test.rb +1 -1
- data/test/embed_ruby.cpp +34 -0
- data/test/embed_ruby.hpp +4 -0
- data/test/ext/t1/extconf.rb +3 -0
- data/test/ext/t1/t1.cpp +1 -3
- data/test/ext/t2/extconf.rb +3 -0
- data/test/ext/t2/t2.cpp +1 -1
- data/test/extconf.rb +23 -0
- data/test/ruby/test_callbacks_sample.rb +28 -0
- data/test/ruby/test_multiple_extensions.rb +18 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
- data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
- data/test/test_Address_Registration_Guard.cpp +25 -11
- data/test/test_Array.cpp +131 -74
- data/test/test_Attribute.cpp +147 -0
- data/test/test_Builtin_Object.cpp +36 -15
- data/test/test_Class.cpp +151 -276
- data/test/test_Constructor.cpp +10 -9
- data/test/test_Data_Object.cpp +135 -193
- data/test/test_Data_Type.cpp +323 -252
- data/test/test_Director.cpp +56 -42
- data/test/test_Enum.cpp +230 -104
- data/test/test_Exception.cpp +7 -7
- data/test/test_Hash.cpp +33 -31
- data/test/test_Identifier.cpp +6 -6
- data/test/test_Inheritance.cpp +221 -0
- data/test/test_Iterator.cpp +161 -0
- data/test/test_Jump_Tag.cpp +1 -1
- data/test/test_Keep_Alive.cpp +161 -0
- data/test/test_Memory_Management.cpp +4 -5
- data/test/test_Module.cpp +169 -111
- data/test/test_Object.cpp +51 -19
- data/test/test_Ownership.cpp +275 -0
- data/test/test_Self.cpp +205 -0
- data/test/test_Stl_Optional.cpp +90 -0
- data/test/test_Stl_Pair.cpp +144 -0
- data/test/test_Stl_SmartPointer.cpp +200 -0
- data/test/test_Stl_String.cpp +74 -0
- data/test/test_Stl_Vector.cpp +652 -0
- data/test/test_String.cpp +3 -3
- data/test/test_Struct.cpp +31 -40
- data/test/test_Symbol.cpp +3 -3
- data/test/test_To_From_Ruby.cpp +283 -218
- data/test/test_global_functions.cpp +41 -20
- data/test/unittest.cpp +34 -8
- data/test/unittest.hpp +0 -4
- metadata +120 -136
- data/Doxyfile +0 -2268
- data/Makefile.am +0 -26
- data/Makefile.in +0 -920
- data/README.mingw +0 -8
- data/aclocal.m4 +0 -1088
- data/bootstrap +0 -8
- data/check_stdcxx_11.ac +0 -142
- data/config.guess +0 -1421
- data/config.sub +0 -1807
- data/configure +0 -7481
- data/configure.ac +0 -55
- data/depcomp +0 -791
- data/doxygen.ac +0 -314
- data/doxygen.am +0 -186
- data/extconf.rb +0 -69
- data/install-sh +0 -501
- data/missing +0 -215
- data/post-autoconf.rb +0 -22
- data/post-automake.rb +0 -28
- data/rice/Address_Registration_Guard.cpp +0 -22
- data/rice/Arg_impl.hpp +0 -129
- data/rice/Arg_operators.cpp +0 -21
- data/rice/Arg_operators.hpp +0 -19
- data/rice/Array.hpp +0 -214
- data/rice/Array.ipp +0 -256
- data/rice/Builtin_Object.hpp +0 -8
- data/rice/Builtin_Object.ipp +0 -50
- data/rice/Builtin_Object_defn.hpp +0 -50
- data/rice/Class.cpp +0 -57
- data/rice/Class.hpp +0 -8
- data/rice/Class.ipp +0 -6
- data/rice/Class_defn.hpp +0 -83
- data/rice/Data_Type.cpp +0 -54
- data/rice/Data_Type_fwd.hpp +0 -12
- data/rice/Director.cpp +0 -13
- data/rice/Exception.cpp +0 -59
- data/rice/Exception_Base.hpp +0 -8
- data/rice/Exception_Base.ipp +0 -13
- data/rice/Exception_Base_defn.hpp +0 -27
- data/rice/Hash.hpp +0 -227
- data/rice/Hash.ipp +0 -329
- data/rice/Identifier.cpp +0 -8
- data/rice/Jump_Tag.hpp +0 -24
- data/rice/Makefile.am +0 -124
- data/rice/Makefile.in +0 -839
- data/rice/Module.cpp +0 -84
- data/rice/Module.hpp +0 -8
- data/rice/Module.ipp +0 -6
- data/rice/Module_defn.hpp +0 -88
- data/rice/Module_impl.hpp +0 -281
- data/rice/Module_impl.ipp +0 -345
- data/rice/Object.cpp +0 -169
- data/rice/Object.hpp +0 -8
- data/rice/Object.ipp +0 -19
- data/rice/Object_defn.hpp +0 -191
- data/rice/Require_Guard.hpp +0 -21
- data/rice/String.cpp +0 -94
- data/rice/String.hpp +0 -91
- data/rice/Struct.cpp +0 -117
- data/rice/Struct.hpp +0 -162
- data/rice/Struct.ipp +0 -26
- data/rice/Symbol.cpp +0 -25
- data/rice/Symbol.hpp +0 -66
- data/rice/Symbol.ipp +0 -44
- data/rice/config.hpp +0 -47
- data/rice/config.hpp.in +0 -46
- data/rice/detail/Arguments.hpp +0 -118
- data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
- data/rice/detail/Auto_Function_Wrapper.ipp +0 -3694
- data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
- data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2774
- data/rice/detail/Caster.hpp +0 -103
- data/rice/detail/Not_Copyable.hpp +0 -25
- data/rice/detail/Wrapped_Function.hpp +0 -33
- data/rice/detail/cfp.hpp +0 -24
- data/rice/detail/cfp.ipp +0 -51
- data/rice/detail/check_ruby_type.cpp +0 -27
- data/rice/detail/check_ruby_type.hpp +0 -23
- data/rice/detail/creation_funcs.hpp +0 -37
- data/rice/detail/creation_funcs.ipp +0 -36
- data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
- data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
- data/rice/detail/demangle.cpp +0 -56
- data/rice/detail/demangle.hpp +0 -19
- data/rice/detail/env.hpp +0 -11
- data/rice/detail/method_data.cpp +0 -86
- data/rice/detail/node.hpp +0 -13
- data/rice/detail/object_call.hpp +0 -69
- data/rice/detail/object_call.ipp +0 -131
- data/rice/detail/protect.cpp +0 -29
- data/rice/detail/protect.hpp +0 -34
- data/rice/detail/ruby_version_code.hpp +0 -6
- data/rice/detail/ruby_version_code.hpp.in +0 -6
- data/rice/detail/st.hpp +0 -22
- data/rice/detail/traits.hpp +0 -43
- data/rice/detail/win32.hpp +0 -16
- data/rice/detail/wrap_function.hpp +0 -341
- data/rice/detail/wrap_function.ipp +0 -514
- data/rice/protect.hpp +0 -92
- data/rice/protect.ipp +0 -1134
- data/rice/rubypp.rb +0 -97
- data/rice/to_from_ruby.hpp +0 -8
- data/rice/to_from_ruby.ipp +0 -294
- data/rice/to_from_ruby_defn.hpp +0 -70
- data/ruby.ac +0 -135
- data/ruby/Makefile.am +0 -1
- data/ruby/Makefile.in +0 -625
- data/ruby/lib/Makefile.am +0 -3
- data/ruby/lib/Makefile.in +0 -503
- data/ruby/lib/mkmf-rice.rb.in +0 -217
- data/ruby/lib/version.rb +0 -3
- data/sample/Makefile.am +0 -47
- data/sample/Makefile.in +0 -486
- data/test/Makefile.am +0 -72
- data/test/Makefile.in +0 -1150
- data/test/ext/Makefile.am +0 -41
- data/test/ext/Makefile.in +0 -480
- data/test/test_rice.rb +0 -41
@@ -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
|
+
}
|