rice 4.3.3 → 4.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -26
- data/CMakeLists.txt +31 -0
- data/CMakePresets.json +75 -0
- data/COPYING +3 -2
- data/FindRuby.cmake +437 -0
- data/README.md +7 -2
- data/Rakefile +12 -5
- data/include/rice/rice.hpp +9522 -4426
- data/include/rice/stl.hpp +2831 -1198
- data/lib/make_rice_headers.rb +79 -0
- data/lib/mkmf-rice.rb +40 -94
- data/lib/rice/version.rb +3 -0
- data/lib/rice.rb +1 -0
- data/lib/rubygems/builder.rb +11 -0
- data/lib/rubygems/cmake_builder.rb +113 -0
- data/lib/rubygems_plugin.rb +9 -0
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +26 -6
- data/rice/Arg.ipp +35 -2
- data/rice/Buffer.hpp +123 -0
- data/rice/Buffer.ipp +599 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +73 -3
- data/rice/Data_Object.ipp +388 -96
- data/rice/Data_Type.hpp +214 -3
- data/rice/Data_Type.ipp +144 -67
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -7
- data/rice/Enum.ipp +102 -55
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/Init.hpp +8 -0
- data/rice/Init.ipp +8 -0
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +3 -0
- data/rice/Return.hpp +7 -27
- data/rice/Return.ipp +13 -13
- data/rice/cpp_api/Array.hpp +209 -0
- data/rice/cpp_api/Array.ipp +304 -0
- data/rice/cpp_api/Builtin_Object.hpp +31 -0
- data/rice/cpp_api/Builtin_Object.ipp +37 -0
- data/rice/cpp_api/Class.hpp +70 -0
- data/rice/cpp_api/Class.ipp +97 -0
- data/rice/cpp_api/Encoding.hpp +32 -0
- data/rice/cpp_api/Encoding.ipp +59 -0
- data/rice/cpp_api/Hash.hpp +194 -0
- data/rice/cpp_api/Hash.ipp +257 -0
- data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
- data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
- data/rice/cpp_api/Module.hpp +72 -0
- data/rice/cpp_api/Module.ipp +101 -0
- data/rice/cpp_api/Object.hpp +272 -0
- data/rice/cpp_api/Object.ipp +235 -0
- data/rice/cpp_api/String.hpp +74 -0
- data/rice/cpp_api/String.ipp +120 -0
- data/rice/cpp_api/Struct.hpp +113 -0
- data/rice/cpp_api/Struct.ipp +92 -0
- data/rice/cpp_api/Symbol.hpp +46 -0
- data/rice/cpp_api/Symbol.ipp +93 -0
- data/rice/cpp_api/shared_methods.hpp +134 -0
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +12 -10
- data/rice/detail/MethodInfo.ipp +26 -21
- data/rice/detail/Native.hpp +33 -0
- data/rice/detail/Native.ipp +157 -0
- data/rice/detail/NativeAttributeGet.hpp +52 -0
- data/rice/detail/NativeAttributeGet.ipp +57 -0
- data/rice/detail/NativeAttributeSet.hpp +44 -0
- data/rice/detail/NativeAttributeSet.ipp +88 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +33 -23
- data/rice/detail/NativeFunction.ipp +309 -70
- data/rice/detail/NativeIterator.hpp +9 -11
- data/rice/detail/NativeIterator.ipp +33 -31
- data/rice/detail/NativeRegistry.hpp +24 -15
- data/rice/detail/NativeRegistry.ipp +23 -48
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +16 -0
- data/rice/detail/RubyType.ipp +232 -0
- data/rice/detail/Type.hpp +7 -6
- data/rice/detail/Type.ipp +192 -45
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +68 -32
- data/rice/detail/Wrapper.ipp +121 -109
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +38 -3
- data/rice/detail/from_ruby.ipp +1321 -492
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +1424 -194
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +0 -1
- data/rice/libc/file.hpp +11 -0
- data/rice/libc/file.ipp +32 -0
- data/rice/rice.hpp +116 -26
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl/complex.hpp +6 -0
- data/rice/stl/complex.ipp +93 -0
- data/rice/stl/exception.hpp +11 -0
- data/rice/stl/exception.ipp +29 -0
- data/rice/stl/exception_ptr.hpp +6 -0
- data/rice/stl/exception_ptr.ipp +27 -0
- data/rice/stl/map.hpp +12 -0
- data/rice/stl/map.ipp +469 -0
- data/rice/stl/monostate.hpp +6 -0
- data/rice/stl/monostate.ipp +80 -0
- data/rice/stl/multimap.hpp +14 -0
- data/rice/stl/multimap.ipp +448 -0
- data/rice/stl/optional.hpp +6 -0
- data/rice/stl/optional.ipp +118 -0
- data/rice/stl/pair.hpp +13 -0
- data/rice/stl/pair.ipp +155 -0
- data/rice/stl/reference_wrapper.hpp +6 -0
- data/rice/stl/reference_wrapper.ipp +41 -0
- data/rice/stl/set.hpp +12 -0
- data/rice/stl/set.ipp +495 -0
- data/rice/stl/shared_ptr.hpp +28 -0
- data/rice/stl/shared_ptr.ipp +224 -0
- data/rice/stl/string.hpp +6 -0
- data/rice/stl/string.ipp +158 -0
- data/rice/stl/string_view.hpp +6 -0
- data/rice/stl/string_view.ipp +65 -0
- data/rice/stl/tuple.hpp +6 -0
- data/rice/stl/tuple.ipp +128 -0
- data/rice/stl/type_index.hpp +6 -0
- data/rice/stl/type_index.ipp +30 -0
- data/rice/stl/type_info.hpp +6 -0
- data/rice/stl/type_info.ipp +29 -0
- data/rice/stl/unique_ptr.hpp +22 -0
- data/rice/stl/unique_ptr.ipp +139 -0
- data/rice/stl/unordered_map.hpp +12 -0
- data/rice/stl/unordered_map.ipp +469 -0
- data/rice/stl/variant.hpp +6 -0
- data/rice/stl/variant.ipp +242 -0
- data/rice/stl/vector.hpp +12 -0
- data/rice/stl/vector.ipp +590 -0
- data/rice/stl.hpp +11 -3
- data/rice/traits/attribute_traits.hpp +26 -0
- data/rice/traits/function_traits.hpp +95 -0
- data/rice/traits/method_traits.hpp +47 -0
- data/rice/traits/rice_traits.hpp +160 -0
- data/rice.gemspec +85 -0
- data/test/embed_ruby.cpp +7 -1
- data/test/extconf.rb +2 -0
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +18 -4
- data/test/test_Attribute.cpp +136 -21
- data/test/test_Buffer.cpp +285 -0
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +230 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +97 -38
- data/test/test_Data_Type.cpp +470 -65
- data/test/test_Director.cpp +17 -8
- data/test/test_Enum.cpp +155 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +609 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +6 -1
- data/test/test_Jump_Exception.cpp +23 -0
- data/test/test_Keep_Alive.cpp +13 -19
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +128 -67
- data/test/test_Native_Registry.cpp +2 -34
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +806 -0
- data/test/test_Ownership.cpp +160 -54
- data/test/test_Proc.cpp +44 -0
- data/test/test_Self.cpp +9 -4
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +54 -42
- data/test/test_Stl_Multimap.cpp +693 -0
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +14 -9
- data/test/test_Stl_Reference_Wrapper.cpp +9 -2
- data/test/test_Stl_Set.cpp +790 -0
- data/test/test_Stl_SharedPtr.cpp +458 -0
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Tuple.cpp +116 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_UniquePtr.cpp +202 -0
- data/test/test_Stl_Unordered_Map.cpp +43 -38
- data/test/test_Stl_Variant.cpp +217 -84
- data/test/test_Stl_Vector.cpp +306 -58
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +524 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +171 -0
- data/test/test_global_functions.cpp +67 -7
- data/test/unittest.cpp +8 -0
- metadata +127 -26
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_Stl_SmartPointer.cpp +0 -283
- data/test/test_To_From_Ruby.cpp +0 -399
data/rice/stl/pair.ipp
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
#include <utility>
|
2
|
+
|
3
|
+
namespace Rice
|
4
|
+
{
|
5
|
+
namespace stl
|
6
|
+
{
|
7
|
+
template<typename T>
|
8
|
+
class PairHelper
|
9
|
+
{
|
10
|
+
public:
|
11
|
+
PairHelper(Data_Type<T> klass) : klass_(klass)
|
12
|
+
{
|
13
|
+
this->define_constructor();
|
14
|
+
this->define_copyable_methods();
|
15
|
+
this->define_access_methods();
|
16
|
+
this->define_modify_methods();
|
17
|
+
this->define_to_s();
|
18
|
+
}
|
19
|
+
|
20
|
+
private:
|
21
|
+
void define_constructor()
|
22
|
+
{
|
23
|
+
klass_.define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
|
24
|
+
}
|
25
|
+
|
26
|
+
void define_copyable_methods()
|
27
|
+
{
|
28
|
+
if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
|
29
|
+
{
|
30
|
+
klass_.define_method("copy", [](T& pair) -> T
|
31
|
+
{
|
32
|
+
return pair;
|
33
|
+
});
|
34
|
+
}
|
35
|
+
else
|
36
|
+
{
|
37
|
+
klass_.define_method("copy", [](T& pair) -> T
|
38
|
+
{
|
39
|
+
throw std::runtime_error("Cannot copy pair with non-copy constructible types");
|
40
|
+
return pair;
|
41
|
+
});
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
void define_access_methods()
|
46
|
+
{
|
47
|
+
// Access methods
|
48
|
+
klass_.define_method("first", [](T& pair) -> typename T::first_type&
|
49
|
+
{
|
50
|
+
return pair.first;
|
51
|
+
})
|
52
|
+
.define_method("second", [](T& pair) -> typename T::second_type&
|
53
|
+
{
|
54
|
+
return pair.second;
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
58
|
+
void define_modify_methods()
|
59
|
+
{
|
60
|
+
// Access methods
|
61
|
+
klass_.define_method("first=", [](T& pair, typename T::first_type& value) -> typename T::first_type&
|
62
|
+
{
|
63
|
+
if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
|
64
|
+
{
|
65
|
+
throw std::runtime_error("Cannot set pair.first since it is a constant");
|
66
|
+
}
|
67
|
+
else
|
68
|
+
{
|
69
|
+
pair.first = value;
|
70
|
+
return pair.first;
|
71
|
+
}
|
72
|
+
})
|
73
|
+
.define_method("second=", [](T& pair, typename T::second_type& value) -> typename T::second_type&
|
74
|
+
{
|
75
|
+
if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
|
76
|
+
{
|
77
|
+
throw std::runtime_error("Cannot set pair.second since it is a constant");
|
78
|
+
}
|
79
|
+
else
|
80
|
+
{
|
81
|
+
pair.second = value;
|
82
|
+
return pair.second;
|
83
|
+
}
|
84
|
+
});
|
85
|
+
}
|
86
|
+
|
87
|
+
void define_to_s()
|
88
|
+
{
|
89
|
+
if constexpr (detail::is_ostreamable_v<typename T::first_type> && detail::is_ostreamable_v<typename T::second_type>)
|
90
|
+
{
|
91
|
+
klass_.define_method("to_s", [](const T& pair)
|
92
|
+
{
|
93
|
+
std::stringstream stream;
|
94
|
+
stream << "[" << pair.first << ", " << pair.second << "]";
|
95
|
+
return stream.str();
|
96
|
+
});
|
97
|
+
}
|
98
|
+
else
|
99
|
+
{
|
100
|
+
klass_.define_method("to_s", [](const T& pair)
|
101
|
+
{
|
102
|
+
return "[Not printable]";
|
103
|
+
});
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
private:
|
108
|
+
Data_Type<T> klass_;
|
109
|
+
};
|
110
|
+
} // namespace
|
111
|
+
|
112
|
+
template<typename T1, typename T2>
|
113
|
+
Data_Type<std::pair<T1, T2>> define_pair(std::string klassName)
|
114
|
+
{
|
115
|
+
using Pair_T = std::pair<T1, T2>;
|
116
|
+
using Data_Type_T = Data_Type<Pair_T>;
|
117
|
+
|
118
|
+
if (klassName.empty())
|
119
|
+
{
|
120
|
+
std::string typeName = detail::typeName(typeid(Pair_T));
|
121
|
+
klassName = detail::rubyClassName(typeName);
|
122
|
+
}
|
123
|
+
|
124
|
+
Module rb_mStd = define_module("Std");
|
125
|
+
if (Data_Type_T::check_defined(klassName, rb_mStd))
|
126
|
+
{
|
127
|
+
return Data_Type_T();
|
128
|
+
}
|
129
|
+
|
130
|
+
Identifier id(klassName);
|
131
|
+
Data_Type_T result = define_class_under<detail::intrinsic_type<Pair_T>>(rb_mStd, id);
|
132
|
+
stl::PairHelper helper(result);
|
133
|
+
return result;
|
134
|
+
}
|
135
|
+
|
136
|
+
namespace detail
|
137
|
+
{
|
138
|
+
template<typename T1, typename T2>
|
139
|
+
struct Type<std::pair<T1, T2>>
|
140
|
+
{
|
141
|
+
static bool verify()
|
142
|
+
{
|
143
|
+
detail::verifyType<T1>();
|
144
|
+
detail::verifyType<T2>();
|
145
|
+
|
146
|
+
if (!Data_Type<std::pair<T1, T2>>::is_defined())
|
147
|
+
{
|
148
|
+
define_pair<T1, T2>();
|
149
|
+
}
|
150
|
+
|
151
|
+
return true;
|
152
|
+
}
|
153
|
+
};
|
154
|
+
}
|
155
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#include <functional>
|
2
|
+
|
3
|
+
namespace Rice::detail
|
4
|
+
{
|
5
|
+
template<typename T>
|
6
|
+
struct Type<std::reference_wrapper<T>>
|
7
|
+
{
|
8
|
+
constexpr static bool verify()
|
9
|
+
{
|
10
|
+
return Type<T>::verify();
|
11
|
+
}
|
12
|
+
};
|
13
|
+
|
14
|
+
template<typename T>
|
15
|
+
class To_Ruby<std::reference_wrapper<T>>
|
16
|
+
{
|
17
|
+
public:
|
18
|
+
VALUE convert(const std::reference_wrapper<T>& data, bool takeOwnership = false)
|
19
|
+
{
|
20
|
+
return To_Ruby<T&>().convert(data.get());
|
21
|
+
}
|
22
|
+
};
|
23
|
+
|
24
|
+
template<typename T>
|
25
|
+
class From_Ruby<std::reference_wrapper<T>>
|
26
|
+
{
|
27
|
+
public:
|
28
|
+
Convertible is_convertible(VALUE value)
|
29
|
+
{
|
30
|
+
return this->converter_.is_convertible(value);
|
31
|
+
}
|
32
|
+
|
33
|
+
std::reference_wrapper<T> convert(VALUE value)
|
34
|
+
{
|
35
|
+
return this->converter_.convert(value);
|
36
|
+
}
|
37
|
+
|
38
|
+
private:
|
39
|
+
From_Ruby<T&> converter_;
|
40
|
+
};
|
41
|
+
}
|
data/rice/stl/set.hpp
ADDED
data/rice/stl/set.ipp
ADDED
@@ -0,0 +1,495 @@
|
|
1
|
+
#include <set>
|
2
|
+
|
3
|
+
namespace Rice
|
4
|
+
{
|
5
|
+
namespace stl
|
6
|
+
{
|
7
|
+
template<typename T>
|
8
|
+
class SetHelper
|
9
|
+
{
|
10
|
+
// We do NOT use Reference_T and instead use Parameter_T to avoid the weirdness
|
11
|
+
// of std::set<bool>. Reference_T is actually a proxy class that we do not
|
12
|
+
// want to have to register with Rice nor do we want to pass it around.
|
13
|
+
using Key_T = typename T::key_type;
|
14
|
+
using Value_T = typename T::value_type;
|
15
|
+
using Size_T = typename T::size_type;
|
16
|
+
using Difference_T = typename T::difference_type;
|
17
|
+
// For To_Ruby_T however we do need to use reference type because this is what
|
18
|
+
// will be passed by an interator to To_Ruby#convert
|
19
|
+
using Reference_T = typename T::reference;
|
20
|
+
using Parameter_T = std::conditional_t<std::is_pointer_v<Value_T>, Value_T, Value_T&>;
|
21
|
+
using To_Ruby_T = detail::remove_cv_recursive_t<typename T::reference>;
|
22
|
+
|
23
|
+
public:
|
24
|
+
SetHelper(Data_Type<T> klass) : klass_(klass)
|
25
|
+
{
|
26
|
+
this->define_constructors();
|
27
|
+
this->define_capacity_methods();
|
28
|
+
this->define_comparable_methods();
|
29
|
+
this->define_modify_methods();
|
30
|
+
this->define_operators();
|
31
|
+
this->define_enumerable();
|
32
|
+
this->define_to_array();
|
33
|
+
this->define_to_s();
|
34
|
+
}
|
35
|
+
|
36
|
+
private:
|
37
|
+
|
38
|
+
void define_constructors()
|
39
|
+
{
|
40
|
+
klass_.define_constructor(Constructor<T>())
|
41
|
+
.define_constructor(Constructor<T, const T&>());
|
42
|
+
}
|
43
|
+
|
44
|
+
void define_capacity_methods()
|
45
|
+
{
|
46
|
+
klass_.define_method("empty?", &T::empty)
|
47
|
+
.define_method("max_size", &T::max_size)
|
48
|
+
.define_method("size", &T::size);
|
49
|
+
|
50
|
+
rb_define_alias(klass_, "count", "size");
|
51
|
+
rb_define_alias(klass_, "length", "size");
|
52
|
+
}
|
53
|
+
|
54
|
+
void define_comparable_methods()
|
55
|
+
{
|
56
|
+
klass_
|
57
|
+
.define_method("include?", [](T& self, const Key_T element) -> bool
|
58
|
+
{
|
59
|
+
auto iter = self.find(element);
|
60
|
+
return iter != self.end();
|
61
|
+
})
|
62
|
+
.define_method("count", [](T& self, const Key_T element) -> Size_T
|
63
|
+
{
|
64
|
+
return self.count(element);
|
65
|
+
});
|
66
|
+
}
|
67
|
+
|
68
|
+
void define_modify_methods()
|
69
|
+
{
|
70
|
+
klass_
|
71
|
+
.define_method("clear", &T::clear)
|
72
|
+
.define_method("delete", [](T& self, const Key_T key) -> T&
|
73
|
+
{
|
74
|
+
self.erase(key);
|
75
|
+
return self;
|
76
|
+
})
|
77
|
+
.define_method("insert", [](T& self, const Value_T value) -> T&
|
78
|
+
{
|
79
|
+
self.insert(value);
|
80
|
+
return self;
|
81
|
+
})
|
82
|
+
.define_method("merge", [](T& self, T& other) -> T&
|
83
|
+
{
|
84
|
+
self.merge(other);
|
85
|
+
return self;
|
86
|
+
});
|
87
|
+
|
88
|
+
rb_define_alias(klass_, "erase", "delete");
|
89
|
+
}
|
90
|
+
|
91
|
+
void define_operators()
|
92
|
+
{
|
93
|
+
klass_
|
94
|
+
.define_method("<<", [](T& self, const Value_T value) -> T&
|
95
|
+
{
|
96
|
+
self.insert(value);
|
97
|
+
return self;
|
98
|
+
})
|
99
|
+
.define_method("==", [](const T& self, const T& other) -> bool
|
100
|
+
{
|
101
|
+
if constexpr (detail::is_comparable_v<Value_T>)
|
102
|
+
{
|
103
|
+
return self == other;
|
104
|
+
}
|
105
|
+
else
|
106
|
+
{
|
107
|
+
return false;
|
108
|
+
}
|
109
|
+
})
|
110
|
+
.define_method("&", [](const T& self, const T& other) -> T
|
111
|
+
{
|
112
|
+
T result;
|
113
|
+
std::set_intersection(self.begin(), self.end(),
|
114
|
+
other.begin(), other.end(),
|
115
|
+
std::inserter(result, result.begin()));
|
116
|
+
|
117
|
+
return result;
|
118
|
+
})
|
119
|
+
.define_method("|", [](const T& self, const T& other) -> T
|
120
|
+
{
|
121
|
+
T result;
|
122
|
+
std::set_union(self.begin(), self.end(),
|
123
|
+
other.begin(), other.end(),
|
124
|
+
std::inserter(result, result.begin()));
|
125
|
+
|
126
|
+
return result;
|
127
|
+
})
|
128
|
+
.define_method("-", [](const T& self, const T& other) -> T
|
129
|
+
{
|
130
|
+
T result;
|
131
|
+
std::set_difference(self.begin(), self.end(),
|
132
|
+
other.begin(), other.end(),
|
133
|
+
std::inserter(result, result.begin()));
|
134
|
+
|
135
|
+
return result;
|
136
|
+
})
|
137
|
+
.define_method("^", [](const T& self, const T& other) -> T
|
138
|
+
{
|
139
|
+
T result;
|
140
|
+
std::set_symmetric_difference(self.begin(), self.end(),
|
141
|
+
other.begin(), other.end(),
|
142
|
+
std::inserter(result, result.begin()));
|
143
|
+
|
144
|
+
return result;
|
145
|
+
})
|
146
|
+
.define_method("<", [](const T& self, const T& other) -> bool
|
147
|
+
{
|
148
|
+
return std::includes(other.begin(), other.end(),
|
149
|
+
self.begin(), self.end());
|
150
|
+
})
|
151
|
+
.define_method(">", [](const T& self, const T& other) -> bool
|
152
|
+
{
|
153
|
+
return std::includes(self.begin(), self.end(),
|
154
|
+
other.begin(), other.end());
|
155
|
+
});
|
156
|
+
|
157
|
+
rb_define_alias(klass_, "eql?", "==");
|
158
|
+
rb_define_alias(klass_, "intersection", "&");
|
159
|
+
rb_define_alias(klass_, "union", "|");
|
160
|
+
rb_define_alias(klass_, "difference", "-");
|
161
|
+
rb_define_alias(klass_, "proper_subset?", "<");
|
162
|
+
rb_define_alias(klass_, "subset?", "<");
|
163
|
+
rb_define_alias(klass_, "proper_superset?", ">");
|
164
|
+
rb_define_alias(klass_, "superset?", ">");
|
165
|
+
}
|
166
|
+
|
167
|
+
void define_enumerable()
|
168
|
+
{
|
169
|
+
// Add enumerable support
|
170
|
+
klass_.template define_iterator<typename T::iterator(T::*)() const>(&T::begin, &T::end);
|
171
|
+
}
|
172
|
+
|
173
|
+
void define_to_array()
|
174
|
+
{
|
175
|
+
// Add enumerable support
|
176
|
+
klass_.define_method("to_a", [](T& self) -> VALUE
|
177
|
+
{
|
178
|
+
Array array;
|
179
|
+
for (const Value_T& element: self)
|
180
|
+
{
|
181
|
+
array.push(element);
|
182
|
+
}
|
183
|
+
|
184
|
+
return array.value();
|
185
|
+
}, Return().setValue());
|
186
|
+
}
|
187
|
+
|
188
|
+
void define_to_s()
|
189
|
+
{
|
190
|
+
if constexpr (detail::is_ostreamable_v<Value_T>)
|
191
|
+
{
|
192
|
+
klass_.define_method("to_s", [](const T& self)
|
193
|
+
{
|
194
|
+
auto iter = self.begin();
|
195
|
+
auto finish = self.end();
|
196
|
+
|
197
|
+
std::stringstream stream;
|
198
|
+
stream << "<" << detail::rubyClassName(detail::typeName(typeid(T))) << ":";
|
199
|
+
stream << "{";
|
200
|
+
|
201
|
+
for (; iter != finish; iter++)
|
202
|
+
{
|
203
|
+
if (iter == self.begin())
|
204
|
+
{
|
205
|
+
stream << *iter;
|
206
|
+
}
|
207
|
+
else
|
208
|
+
{
|
209
|
+
stream << ", " << *iter;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
stream << "}>";
|
214
|
+
return stream.str();
|
215
|
+
});
|
216
|
+
}
|
217
|
+
else
|
218
|
+
{
|
219
|
+
klass_.define_method("to_s", [](const T& self)
|
220
|
+
{
|
221
|
+
return "[Not printable]";
|
222
|
+
});
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
private:
|
227
|
+
Data_Type<T> klass_;
|
228
|
+
};
|
229
|
+
} // namespace
|
230
|
+
|
231
|
+
template<typename T>
|
232
|
+
Data_Type<std::set<T>> define_set(std::string klassName)
|
233
|
+
{
|
234
|
+
using Set_T = std::set<T>;
|
235
|
+
using Data_Type_T = Data_Type<Set_T>;
|
236
|
+
|
237
|
+
if (klassName.empty())
|
238
|
+
{
|
239
|
+
std::string typeName = detail::typeName(typeid(Set_T));
|
240
|
+
klassName = detail::rubyClassName(typeName);
|
241
|
+
}
|
242
|
+
|
243
|
+
Module rb_mStd = define_module("Std");
|
244
|
+
if (Data_Type_T::check_defined(klassName, rb_mStd))
|
245
|
+
{
|
246
|
+
return Data_Type_T();
|
247
|
+
}
|
248
|
+
|
249
|
+
Identifier id(klassName);
|
250
|
+
Data_Type_T result = define_class_under<detail::intrinsic_type<Set_T>>(rb_mStd, id);
|
251
|
+
stl::SetHelper helper(result);
|
252
|
+
return result;
|
253
|
+
}
|
254
|
+
|
255
|
+
namespace detail
|
256
|
+
{
|
257
|
+
// Helper method - maybe someday create a C++ Ruby set wrapper
|
258
|
+
template<typename T>
|
259
|
+
std::set<T> toSet(VALUE rubySet)
|
260
|
+
{
|
261
|
+
using Function_T = VALUE(*)(VALUE, ID, int, const VALUE*, rb_block_call_func_t, VALUE);
|
262
|
+
static Identifier identifier("each");
|
263
|
+
|
264
|
+
std::set<T> result;
|
265
|
+
auto block = [&result](const typename std::set<T>::value_type element) -> VALUE
|
266
|
+
{
|
267
|
+
result.insert(element);
|
268
|
+
return Qnil;
|
269
|
+
};
|
270
|
+
|
271
|
+
using NativeFunction_T = NativeFunction<void, decltype(block), false>;
|
272
|
+
|
273
|
+
// It is ok to use the address of native because it will remain valid while we iterate the set
|
274
|
+
NativeFunction_T native(block);
|
275
|
+
detail::protect<Function_T>(rb_block_call, rubySet, identifier.id(), 0, nullptr, NativeFunction_T::procEntry, (VALUE)&native);
|
276
|
+
|
277
|
+
return result;
|
278
|
+
}
|
279
|
+
|
280
|
+
template<typename T>
|
281
|
+
struct Type<std::set<T>>
|
282
|
+
{
|
283
|
+
static bool verify()
|
284
|
+
{
|
285
|
+
Type<intrinsic_type<T>>::verify();
|
286
|
+
|
287
|
+
if (!Data_Type<std::set<T>>::is_defined())
|
288
|
+
{
|
289
|
+
define_set<T>();
|
290
|
+
}
|
291
|
+
|
292
|
+
return true;
|
293
|
+
}
|
294
|
+
};
|
295
|
+
|
296
|
+
template<typename T>
|
297
|
+
class From_Ruby<std::set<T>>
|
298
|
+
{
|
299
|
+
private:
|
300
|
+
static inline std::string setName = "Set";
|
301
|
+
|
302
|
+
public:
|
303
|
+
From_Ruby() = default;
|
304
|
+
|
305
|
+
explicit From_Ruby(Arg * arg) : arg_(arg)
|
306
|
+
{
|
307
|
+
}
|
308
|
+
|
309
|
+
Convertible is_convertible(VALUE value)
|
310
|
+
{
|
311
|
+
switch (rb_type(value))
|
312
|
+
{
|
313
|
+
case RUBY_T_DATA:
|
314
|
+
return Data_Type<std::set<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
315
|
+
break;
|
316
|
+
case RUBY_T_OBJECT:
|
317
|
+
{
|
318
|
+
Object object(value);
|
319
|
+
if (object.class_name().str() == setName)
|
320
|
+
{
|
321
|
+
return Convertible::Cast;
|
322
|
+
}
|
323
|
+
}
|
324
|
+
default:
|
325
|
+
return Convertible::None;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
std::set<T> convert(VALUE value)
|
330
|
+
{
|
331
|
+
switch (rb_type(value))
|
332
|
+
{
|
333
|
+
case RUBY_T_DATA:
|
334
|
+
{
|
335
|
+
// This is a wrapped self (hopefully!)
|
336
|
+
return *detail::unwrap<std::set<T>>(value, Data_Type<std::set<T>>::ruby_data_type(), false);
|
337
|
+
}
|
338
|
+
case RUBY_T_OBJECT:
|
339
|
+
{
|
340
|
+
Object object(value);
|
341
|
+
if (object.class_name().str() == setName)
|
342
|
+
{
|
343
|
+
return toSet<T>(value);
|
344
|
+
}
|
345
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
346
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
347
|
+
}
|
348
|
+
default:
|
349
|
+
{
|
350
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
351
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
private:
|
357
|
+
Arg* arg_ = nullptr;
|
358
|
+
};
|
359
|
+
|
360
|
+
template<typename T>
|
361
|
+
class From_Ruby<std::set<T>&>
|
362
|
+
{
|
363
|
+
private:
|
364
|
+
static inline std::string setName = "Set";
|
365
|
+
|
366
|
+
public:
|
367
|
+
From_Ruby() = default;
|
368
|
+
|
369
|
+
explicit From_Ruby(Arg * arg) : arg_(arg)
|
370
|
+
{
|
371
|
+
}
|
372
|
+
|
373
|
+
Convertible is_convertible(VALUE value)
|
374
|
+
{
|
375
|
+
switch (rb_type(value))
|
376
|
+
{
|
377
|
+
case RUBY_T_DATA:
|
378
|
+
return Data_Type<std::set<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
379
|
+
break;
|
380
|
+
case RUBY_T_OBJECT:
|
381
|
+
{
|
382
|
+
Object object(value);
|
383
|
+
if (object.class_name().str() == setName)
|
384
|
+
{
|
385
|
+
return Convertible::Cast;
|
386
|
+
}
|
387
|
+
}
|
388
|
+
default:
|
389
|
+
return Convertible::None;
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
std::set<T>& convert(VALUE value)
|
394
|
+
{
|
395
|
+
switch (rb_type(value))
|
396
|
+
{
|
397
|
+
case RUBY_T_DATA:
|
398
|
+
{
|
399
|
+
// This is a wrapped self (hopefully!)
|
400
|
+
return *detail::unwrap<std::set<T>>(value, Data_Type<std::set<T>>::ruby_data_type(), false);
|
401
|
+
}
|
402
|
+
case RUBY_T_OBJECT:
|
403
|
+
{
|
404
|
+
Object object(value);
|
405
|
+
if (object.class_name().str() == setName)
|
406
|
+
{
|
407
|
+
// If this an Ruby array and the vector type is copyable
|
408
|
+
if constexpr (std::is_default_constructible_v<T>)
|
409
|
+
{
|
410
|
+
this->converted_ = toSet<T>(value);
|
411
|
+
return this->converted_;
|
412
|
+
}
|
413
|
+
}
|
414
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
415
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
416
|
+
}
|
417
|
+
default:
|
418
|
+
{
|
419
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
420
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
421
|
+
}
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
private:
|
426
|
+
Arg* arg_ = nullptr;
|
427
|
+
std::set<T> converted_;
|
428
|
+
};
|
429
|
+
|
430
|
+
template<typename T>
|
431
|
+
class From_Ruby<std::set<T>*>
|
432
|
+
{
|
433
|
+
private:
|
434
|
+
static inline std::string setName = "Set";
|
435
|
+
public:
|
436
|
+
Convertible is_convertible(VALUE value)
|
437
|
+
{
|
438
|
+
switch (rb_type(value))
|
439
|
+
{
|
440
|
+
case RUBY_T_DATA:
|
441
|
+
return Data_Type<std::set<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
442
|
+
break;
|
443
|
+
case RUBY_T_NIL:
|
444
|
+
return Convertible::Exact;
|
445
|
+
break;
|
446
|
+
case RUBY_T_OBJECT:
|
447
|
+
{
|
448
|
+
Object object(value);
|
449
|
+
if (object.class_name().str() == setName)
|
450
|
+
{
|
451
|
+
return Convertible::Cast;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
default:
|
455
|
+
return Convertible::None;
|
456
|
+
}
|
457
|
+
}
|
458
|
+
|
459
|
+
std::set<T>* convert(VALUE value)
|
460
|
+
{
|
461
|
+
switch (rb_type(value))
|
462
|
+
{
|
463
|
+
case RUBY_T_DATA:
|
464
|
+
{
|
465
|
+
// This is a wrapped self (hopefully!)
|
466
|
+
return detail::unwrap<std::set<T>>(value, Data_Type<std::set<T>>::ruby_data_type(), false);
|
467
|
+
}
|
468
|
+
case RUBY_T_OBJECT:
|
469
|
+
{
|
470
|
+
Object object(value);
|
471
|
+
if (object.class_name().str() == setName)
|
472
|
+
{
|
473
|
+
// If this an Ruby array and the vector type is copyable
|
474
|
+
if constexpr (std::is_default_constructible_v<T>)
|
475
|
+
{
|
476
|
+
this->converted_ = toSet<T>(value);
|
477
|
+
return &this->converted_;
|
478
|
+
}
|
479
|
+
}
|
480
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
481
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
482
|
+
}
|
483
|
+
default:
|
484
|
+
{
|
485
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
|
486
|
+
detail::protect(rb_obj_classname, value), "std::set");
|
487
|
+
}
|
488
|
+
}
|
489
|
+
}
|
490
|
+
|
491
|
+
private:
|
492
|
+
std::set<T> converted_;
|
493
|
+
};
|
494
|
+
}
|
495
|
+
}
|