rice 4.5.0 → 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.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/Rakefile +5 -4
  8. data/include/rice/rice.hpp +5436 -3201
  9. data/include/rice/stl.hpp +2355 -1269
  10. data/lib/make_rice_headers.rb +79 -0
  11. data/lib/mkmf-rice.rb +4 -0
  12. data/lib/rice/version.rb +3 -0
  13. data/lib/rice.rb +1 -0
  14. data/lib/rubygems/builder.rb +11 -0
  15. data/lib/rubygems/cmake_builder.rb +113 -0
  16. data/lib/rubygems_plugin.rb +9 -0
  17. data/rice/Arg.hpp +7 -1
  18. data/rice/Arg.ipp +11 -2
  19. data/rice/Buffer.hpp +123 -0
  20. data/rice/Buffer.ipp +599 -0
  21. data/rice/Constructor.ipp +3 -3
  22. data/rice/Data_Object.hpp +2 -3
  23. data/rice/Data_Object.ipp +188 -188
  24. data/rice/Data_Type.hpp +4 -5
  25. data/rice/Data_Type.ipp +42 -26
  26. data/rice/Enum.hpp +0 -1
  27. data/rice/Enum.ipp +26 -23
  28. data/rice/Init.hpp +8 -0
  29. data/rice/Init.ipp +8 -0
  30. data/rice/MemoryView.ipp +1 -41
  31. data/rice/Return.hpp +1 -1
  32. data/rice/Return.ipp +6 -0
  33. data/rice/cpp_api/Array.hpp +209 -0
  34. data/rice/cpp_api/Array.ipp +304 -0
  35. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  36. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  37. data/rice/cpp_api/Class.hpp +70 -0
  38. data/rice/cpp_api/Class.ipp +97 -0
  39. data/rice/cpp_api/Encoding.hpp +32 -0
  40. data/rice/cpp_api/Encoding.ipp +59 -0
  41. data/rice/cpp_api/Hash.hpp +194 -0
  42. data/rice/cpp_api/Hash.ipp +257 -0
  43. data/rice/cpp_api/Identifier.hpp +46 -0
  44. data/rice/cpp_api/Identifier.ipp +31 -0
  45. data/rice/cpp_api/Module.hpp +72 -0
  46. data/rice/cpp_api/Module.ipp +101 -0
  47. data/rice/cpp_api/Object.hpp +272 -0
  48. data/rice/cpp_api/Object.ipp +235 -0
  49. data/rice/cpp_api/String.hpp +74 -0
  50. data/rice/cpp_api/String.ipp +120 -0
  51. data/rice/cpp_api/Struct.hpp +113 -0
  52. data/rice/cpp_api/Struct.ipp +92 -0
  53. data/rice/cpp_api/Symbol.hpp +46 -0
  54. data/rice/cpp_api/Symbol.ipp +93 -0
  55. data/rice/cpp_api/shared_methods.hpp +134 -0
  56. data/rice/detail/MethodInfo.hpp +1 -9
  57. data/rice/detail/MethodInfo.ipp +5 -72
  58. data/rice/detail/Native.hpp +3 -2
  59. data/rice/detail/Native.ipp +32 -4
  60. data/rice/detail/NativeAttributeGet.hpp +3 -2
  61. data/rice/detail/NativeAttributeGet.ipp +8 -2
  62. data/rice/detail/NativeAttributeSet.hpp +3 -2
  63. data/rice/detail/NativeAttributeSet.ipp +8 -2
  64. data/rice/detail/NativeCallbackFFI.ipp +1 -1
  65. data/rice/detail/NativeFunction.hpp +17 -6
  66. data/rice/detail/NativeFunction.ipp +168 -64
  67. data/rice/detail/NativeIterator.hpp +3 -2
  68. data/rice/detail/NativeIterator.ipp +8 -2
  69. data/rice/detail/RubyType.hpp +2 -5
  70. data/rice/detail/RubyType.ipp +50 -5
  71. data/rice/detail/Type.hpp +3 -1
  72. data/rice/detail/Type.ipp +61 -31
  73. data/rice/detail/Wrapper.hpp +68 -33
  74. data/rice/detail/Wrapper.ipp +103 -113
  75. data/rice/detail/from_ruby.hpp +5 -4
  76. data/rice/detail/from_ruby.ipp +737 -365
  77. data/rice/detail/to_ruby.ipp +1092 -186
  78. data/rice/global_function.ipp +1 -1
  79. data/rice/libc/file.hpp +11 -0
  80. data/rice/libc/file.ipp +32 -0
  81. data/rice/rice.hpp +23 -16
  82. data/rice/stl/complex.hpp +6 -0
  83. data/rice/stl/complex.ipp +93 -0
  84. data/rice/stl/exception.hpp +11 -0
  85. data/rice/stl/exception.ipp +29 -0
  86. data/rice/stl/exception_ptr.hpp +6 -0
  87. data/rice/stl/exception_ptr.ipp +27 -0
  88. data/rice/stl/map.hpp +12 -0
  89. data/rice/stl/map.ipp +469 -0
  90. data/rice/stl/monostate.hpp +6 -0
  91. data/rice/stl/monostate.ipp +80 -0
  92. data/rice/stl/multimap.hpp +14 -0
  93. data/rice/stl/multimap.ipp +448 -0
  94. data/rice/stl/optional.hpp +6 -0
  95. data/rice/stl/optional.ipp +118 -0
  96. data/rice/stl/pair.hpp +13 -0
  97. data/rice/stl/pair.ipp +155 -0
  98. data/rice/stl/reference_wrapper.hpp +6 -0
  99. data/rice/stl/reference_wrapper.ipp +41 -0
  100. data/rice/stl/set.hpp +12 -0
  101. data/rice/stl/set.ipp +495 -0
  102. data/rice/stl/shared_ptr.hpp +28 -0
  103. data/rice/stl/shared_ptr.ipp +224 -0
  104. data/rice/stl/string.hpp +6 -0
  105. data/rice/stl/string.ipp +158 -0
  106. data/rice/stl/string_view.hpp +6 -0
  107. data/rice/stl/string_view.ipp +65 -0
  108. data/rice/stl/tuple.hpp +6 -0
  109. data/rice/stl/tuple.ipp +128 -0
  110. data/rice/stl/type_index.hpp +6 -0
  111. data/rice/stl/type_index.ipp +30 -0
  112. data/rice/stl/type_info.hpp +6 -0
  113. data/rice/stl/type_info.ipp +29 -0
  114. data/rice/stl/unique_ptr.hpp +22 -0
  115. data/rice/stl/unique_ptr.ipp +139 -0
  116. data/rice/stl/unordered_map.hpp +12 -0
  117. data/rice/stl/unordered_map.ipp +469 -0
  118. data/rice/stl/variant.hpp +6 -0
  119. data/rice/stl/variant.ipp +242 -0
  120. data/rice/stl/vector.hpp +12 -0
  121. data/rice/stl/vector.ipp +590 -0
  122. data/rice/stl.hpp +7 -3
  123. data/rice/traits/attribute_traits.hpp +26 -0
  124. data/rice/traits/function_traits.hpp +95 -0
  125. data/rice/traits/method_traits.hpp +47 -0
  126. data/rice/traits/rice_traits.hpp +160 -0
  127. data/rice.gemspec +85 -0
  128. data/test/embed_ruby.cpp +3 -0
  129. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  130. data/test/test_Array.cpp +6 -3
  131. data/test/test_Attribute.cpp +34 -1
  132. data/test/test_Buffer.cpp +285 -0
  133. data/test/test_Callback.cpp +2 -3
  134. data/test/test_Data_Object.cpp +88 -34
  135. data/test/test_Data_Type.cpp +106 -65
  136. data/test/test_Director.cpp +7 -3
  137. data/test/test_Enum.cpp +5 -2
  138. data/test/test_File.cpp +1 -1
  139. data/test/test_From_Ruby.cpp +181 -114
  140. data/test/test_Iterator.cpp +1 -1
  141. data/test/{test_JumpException.cpp → test_Jump_Exception.cpp} +1 -0
  142. data/test/test_Keep_Alive.cpp +7 -18
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +0 -1
  144. data/test/test_Module.cpp +13 -6
  145. data/test/test_Native_Registry.cpp +0 -1
  146. data/test/test_Overloads.cpp +180 -5
  147. data/test/test_Ownership.cpp +100 -57
  148. data/test/test_Proc.cpp +0 -1
  149. data/test/test_Self.cpp +4 -4
  150. data/test/test_Stl_Map.cpp +37 -39
  151. data/test/test_Stl_Multimap.cpp +693 -0
  152. data/test/test_Stl_Pair.cpp +8 -8
  153. data/test/test_Stl_Reference_Wrapper.cpp +4 -2
  154. data/test/test_Stl_Set.cpp +790 -0
  155. data/test/{test_Stl_SmartPointer.cpp → test_Stl_SharedPtr.cpp} +97 -127
  156. data/test/test_Stl_Tuple.cpp +116 -0
  157. data/test/test_Stl_Type.cpp +1 -1
  158. data/test/test_Stl_UniquePtr.cpp +202 -0
  159. data/test/test_Stl_Unordered_Map.cpp +28 -34
  160. data/test/test_Stl_Variant.cpp +217 -89
  161. data/test/test_Stl_Vector.cpp +209 -83
  162. data/test/test_To_Ruby.cpp +373 -1
  163. data/test/test_Type.cpp +85 -14
  164. data/test/test_global_functions.cpp +17 -4
  165. metadata +94 -10
  166. data/rice/detail/TupleIterator.hpp +0 -14
@@ -0,0 +1,272 @@
1
+ #ifndef Rice__Object__hpp_
2
+ #define Rice__Object__hpp_
3
+
4
+ /*! \file Object.hpp
5
+ */
6
+
7
+ #include <iosfwd>
8
+
9
+ namespace Rice
10
+ {
11
+ class Class;
12
+ class String;
13
+ class Array;
14
+
15
+ //! The base class for all Objects
16
+ /*! Perhaps the name "Object" is a misnomer, because this class really
17
+ * holds an object reference, not an object.
18
+ */
19
+ class Object
20
+ {
21
+ public:
22
+ //! Encapsulate an existing ruby object.
23
+ Object(VALUE value = Qnil) : value_(value) {}
24
+
25
+ //! Destructor
26
+ virtual ~Object();
27
+
28
+ // Enable copying
29
+ Object(const Object& other) = default;
30
+ Object& operator=(const Object& other) = default;
31
+
32
+ // Enable moving
33
+ Object(Object&& other);
34
+ Object& operator=(Object&& other);
35
+
36
+ //! Returns false if the object is nil or false; returns true
37
+ //! otherwise.
38
+ // Having this conversion also prevents accidental conversion to
39
+ // undesired integral types (e.g. long or int) by making the
40
+ // conversion ambiguous.
41
+ bool test() const { return RTEST(value_); }
42
+
43
+ //! Returns false if the object is nil or false; returns true
44
+ //! otherwise.
45
+ operator bool() const { return test(); }
46
+
47
+ //! Returns true if the object is nil, false otherwise.
48
+ bool is_nil() const { return NIL_P(value_); }
49
+
50
+ //! Implicit conversion to VALUE.
51
+ operator VALUE() const { return value_; }
52
+
53
+ //! Explicitly get the encapsulated VALUE.
54
+ // Returns a const ref so that Address_Registration_Guard can access
55
+ // the address where the VALUE is stored
56
+ VALUE const volatile& value() const { return value_; }
57
+
58
+ //! Get the class of an object.
59
+ /*! \return the object's Class.
60
+ */
61
+ Class class_of() const;
62
+
63
+ //! Compare this object to another object.
64
+ /*! Gets the result of self <=> other and returns the result. The
65
+ * result will be less than zero if self < other, greater than zero
66
+ * if self > other, and equal to zero if self == other.
67
+ */
68
+ int compare(Object const& other) const;
69
+
70
+ //! Return a string representation of an object.
71
+ /*! \return the result of calling to_s on the object. A String is not
72
+ * returned, because it is not possible to return an instance of a
73
+ * derived class.
74
+ */
75
+ String to_s() const;
76
+
77
+ //! Return the name of an object's class.
78
+ String class_name() const;
79
+
80
+ //! Inspect the object.
81
+ /*! \return the result of calling inspect on the object. A String is
82
+ * not returned, because it is not possible to return an instance of
83
+ * a derived class.
84
+ */
85
+ String inspect() const;
86
+
87
+ //! Freeze the object.
88
+ void freeze();
89
+
90
+ //! Determine if the object is frozen.
91
+ /*! \return true if the object is frozen, false otherwise.
92
+ */
93
+ bool is_frozen() const;
94
+
95
+ //! Evaluate the given string in the context of the object.
96
+ /*! This is equivalant to calling obj.instance_eval(s) from inside the
97
+ * interpreter.
98
+ * \return the result of the expression.
99
+ */
100
+ Object instance_eval(String const& s);
101
+
102
+ //! Return the type of the underlying C object.
103
+ /*! This is equivalent to calling rb_type(obj).
104
+ * \return the type of the underlying C object (e.g. T_DATA, T_ARRAY,
105
+ * etc.).
106
+ */
107
+ int rb_type() const;
108
+
109
+ //! Return the object's id
110
+ VALUE object_id() const;
111
+
112
+ //! Determine whether the object is an instance of a class/module.
113
+ /*! \param klass a class or module.
114
+ * \return true if the object is an instance of the given
115
+ * class/module or one of its descendants.
116
+ */
117
+ bool is_a(Object klass) const;
118
+
119
+ //! Determine if the objects responds to a method.
120
+ /*! \param id the name of the method
121
+ * \return true if the objects responds to the method, false
122
+ * otherwise.
123
+ */
124
+ bool respond_to(Identifier id) const;
125
+
126
+ //! Determine whether class is the object's class.
127
+ /*! \param klass a class.
128
+ * \return true if the object is an instance of the given class.
129
+ */
130
+ bool is_instance_of(Object klass) const;
131
+
132
+ //! Determine whether the Ruby VALUEs wrapped by this
133
+ //! object are the same object. Maps to Object::equal?
134
+ /*! \param other a Object.
135
+ */
136
+ bool is_equal(const Object& other) const;
137
+
138
+ //! Determine whether the Ruby VALUEs wrapped by this
139
+ //! object are equivalent. Maps to Object::eql?
140
+ /*! \param other a Object.
141
+ */
142
+ bool is_eql(const Object& other) const;
143
+
144
+ //! Set an instance variable.
145
+ /*! \param name the name of the instance variable to set (including
146
+ * the leading @ sign)
147
+ * \param value the value of the variable, which will be converted to
148
+ * a Ruby type if necessary.
149
+ */
150
+ template<typename T>
151
+ void iv_set(Identifier name, T const& value);
152
+
153
+ //! Get the value of an instance variable.
154
+ /*! \param name the name of the instance variable to get
155
+ * \return the value of the instance variable
156
+ */
157
+ Object iv_get(Identifier name) const;
158
+
159
+ //! Get the value of an instance variable, but don't warn if it is
160
+ //unset.
161
+ /*! \param name the name of the instance variable to get
162
+ * \return the value of the instance variable
163
+ */
164
+ Object attr_get(Identifier name) const;
165
+
166
+ //! Call the Ruby method specified by 'id' on object 'obj'.
167
+ /*! Pass in arguments (arg1, arg2, ...). The arguments will be converted to
168
+ * Ruby objects with to_ruby<>. To call methods expecting keyword arguments,
169
+ * use call_kw.
170
+ *
171
+ * E.g.:
172
+ * \code
173
+ * Rice::Object obj = x.call("foo", "one", 2);
174
+ * \endcode
175
+ *
176
+ * If a return type is specified, the return value will automatically be
177
+ * converted to that type as long as 'from_ruby' exists for that type.
178
+ *
179
+ * E.g.:
180
+ * \code
181
+ * float ret = x.call<float>("foo", z, 42);
182
+ * \endcode
183
+ */
184
+ template<typename ...Arg_Ts>
185
+ Object call(Identifier id, Arg_Ts... args) const;
186
+
187
+ //! Call the Ruby method specified by 'id' on object 'obj'.
188
+ /*! Pass in arguments (arg1, arg2, ...). The arguments will be converted to
189
+ * Ruby objects with to_ruby<>. The final argument must be a Hash and will be treated
190
+ * as keyword arguments to the function.
191
+ *
192
+ * E.g.:
193
+ * \code
194
+ * Rice::Hash kw;
195
+ * kw[":argument"] = String("one")
196
+ * Rice::Object obj = x.call_kw("foo", kw);
197
+ * \endcode
198
+ *
199
+ * If a return type is specified, the return value will automatically be
200
+ * converted to that type as long as 'from_ruby' exists for that type.
201
+ *
202
+ * E.g.:
203
+ * \code
204
+ * float ret = x.call_kw<float>("foo", kw);
205
+ * \endcode
206
+ */
207
+ template<typename ...Arg_Ts>
208
+ Object call_kw(Identifier id, Arg_Ts... args) const;
209
+
210
+ //! Vectorized call.
211
+ /*! Calls the method identified by id with the list of arguments
212
+ * identified by args.
213
+ * \param id the name of the method to call
214
+ * \param args the arguments to the method
215
+ * \return the return value of the method call
216
+ */
217
+ Object vcall(Identifier id, Array args);
218
+
219
+ //! Get a constant.
220
+ /*! \param name the name of the constant to get.
221
+ * \return the value of the constant.
222
+ */
223
+ Object const_get(Identifier name) const;
224
+
225
+ //! Determine whether a constant is defined.
226
+ /*! \param name the name of the constant to check.
227
+ * \return true if the constant is defined in this module or false
228
+ * otherwise.
229
+ */
230
+ bool const_defined(Identifier name) const;
231
+
232
+ //! Set a constant.
233
+ /*! \param name the name of the constant to set.
234
+ * \param value the value of the constant.
235
+ * \return *this
236
+ */
237
+ inline Object const_set(Identifier name, Object value);
238
+
239
+ //! Set a constant if it not already set.
240
+ /*! \param name the name of the constant to set.
241
+ * \param value the value of the constant.
242
+ * \return *this
243
+ */
244
+ inline Object const_set_maybe(Identifier name, Object value);
245
+
246
+ //! Remove a constant.
247
+ /*! \param name the name of the constant to remove.
248
+ */
249
+ void remove_const(Identifier name);
250
+
251
+ protected:
252
+ //! Set the encapsulated value.
253
+ void set_value(VALUE v);
254
+
255
+ private:
256
+ volatile VALUE value_;
257
+ };
258
+
259
+ std::ostream& operator<<(std::ostream& out, Object const& obj);
260
+
261
+ bool operator==(Object const& lhs, Object const& rhs);
262
+ bool operator!=(Object const& lhs, Object const& rhs);
263
+ bool operator<(Object const& lhs, Object const& rhs);
264
+ bool operator>(Object const& lhs, Object const& rhs);
265
+
266
+ extern Object const Nil;
267
+ extern Object const True;
268
+ extern Object const False;
269
+ extern Object const Undef;
270
+ } // namespace Rice
271
+
272
+ #endif // Rice__Object__hpp_
@@ -0,0 +1,235 @@
1
+ namespace Rice
2
+ {
3
+ inline const Object Nil(Qnil);
4
+ inline const Object True(Qtrue);
5
+ inline const Object False(Qfalse);
6
+ inline const Object Undef(Qundef);
7
+
8
+ // Ruby auto detects VALUEs in the stack, so when an Object gets deleted make sure
9
+ // to clean up in case it is on the stack
10
+ inline Object::~Object()
11
+ {
12
+ this->value_ = Qnil;
13
+ }
14
+
15
+ // Move constructor
16
+ inline Object::Object(Object&& other)
17
+ {
18
+ this->value_ = other.value_;
19
+ other.value_ = Qnil;
20
+ }
21
+
22
+ // Move assignment
23
+ inline Object& Object::operator=(Object&& other)
24
+ {
25
+ this->value_ = other.value_;
26
+ other.value_ = Qnil;
27
+ return *this;
28
+ }
29
+
30
+ template<typename ...Arg_Ts>
31
+ inline Object Object::call(Identifier id, Arg_Ts... args) const
32
+ {
33
+ /* IMPORTANT - We store VALUEs in an array that is a local variable.
34
+ That allows the Ruby garbage collector to find them when scanning
35
+ the stack and thus mark them. If instead we use a vector, then Ruby's GC
36
+ can't find the VALUEs and may garbage collect them before they are sent
37
+ to the destination method resulting in a segmentation fault. This is
38
+ easy to duplicate by setting GC.stress to true and calling a constructor
39
+ that takes multiple values like a std::pair wrapper. */
40
+ std::array<VALUE, sizeof...(Arg_Ts)> values = { detail::To_Ruby<detail::remove_cv_recursive_t<Arg_Ts>>().convert(std::forward<Arg_Ts>(args))... };
41
+ return detail::protect(rb_funcallv, value(), id.id(), (int)values.size(), (const VALUE*)values.data());
42
+ }
43
+
44
+ template<typename ...Arg_Ts>
45
+ inline Object Object::call_kw(Identifier id, Arg_Ts... args) const
46
+ {
47
+ /* IMPORTANT - See call() above */
48
+ std::array<VALUE, sizeof...(Arg_Ts)> values = { detail::To_Ruby<detail::remove_cv_recursive_t<Arg_Ts>>().convert(args)... };
49
+ return detail::protect(rb_funcallv_kw, value(), id.id(), (int)values.size(), (const VALUE*)values.data(), RB_PASS_KEYWORDS);
50
+ }
51
+
52
+ template<typename T>
53
+ inline void Object::iv_set(Identifier name, T const& value)
54
+ {
55
+ detail::protect(rb_ivar_set, this->value(), name.id(), detail::To_Ruby<T>().convert(value));
56
+ }
57
+
58
+ inline int Object::compare(Object const& other) const
59
+ {
60
+ Object result = call("<=>", other);
61
+ return detail::From_Ruby<int>().convert(result);
62
+ }
63
+
64
+ inline bool Object::is_equal(const Object& other) const
65
+ {
66
+ VALUE result = detail::protect(rb_equal, this->value_, other.value_);
67
+ return RB_TEST(result);
68
+ }
69
+
70
+ inline bool Object::is_eql(const Object& other) const
71
+ {
72
+ VALUE result = detail::protect(rb_eql, this->value_, other.value_);
73
+ return RB_TEST(result);
74
+ }
75
+
76
+ inline void Object::freeze()
77
+ {
78
+ detail::protect(rb_obj_freeze, value());
79
+ }
80
+
81
+ inline bool Object::is_frozen() const
82
+ {
83
+ return RB_OBJ_FROZEN(value());
84
+ }
85
+
86
+ inline int Object::rb_type() const
87
+ {
88
+ return ::rb_type(this->value());
89
+ }
90
+
91
+ inline VALUE Object::object_id() const
92
+ {
93
+ return detail::protect(rb_obj_id, this->value());
94
+ }
95
+
96
+ inline bool Object::is_a(Object klass) const
97
+ {
98
+ VALUE result = detail::protect(rb_obj_is_kind_of, this->value(), klass.value());
99
+ return RB_TEST(result);
100
+ }
101
+
102
+ inline bool Object::respond_to(Identifier id) const
103
+ {
104
+ return bool(rb_respond_to(this->value(), id.id()));
105
+ }
106
+
107
+ inline bool Object::is_instance_of(Object klass) const
108
+ {
109
+ VALUE result = detail::protect(rb_obj_is_instance_of, this->value(), klass.value());
110
+ return RB_TEST(result);
111
+ }
112
+
113
+ inline Object Object::iv_get(Identifier name) const
114
+ {
115
+ return detail::protect(rb_ivar_get, this->value(), name.id());
116
+ }
117
+
118
+ inline Object Object::attr_get(Identifier name) const
119
+ {
120
+ return detail::protect(rb_attr_get, this->value(), name.id());
121
+ }
122
+
123
+ inline void Object::set_value(VALUE v)
124
+ {
125
+ value_ = v;
126
+ }
127
+
128
+ inline Object Object::const_get(Identifier name) const
129
+ {
130
+ return detail::protect(rb_const_get, this->value(), name.id());
131
+ }
132
+
133
+ inline bool Object::const_defined(Identifier name) const
134
+ {
135
+ size_t result = detail::protect(rb_const_defined, this->value(), name.id());
136
+ return bool(result);
137
+ }
138
+
139
+ inline Object Object::const_set(Identifier name, Object value)
140
+ {
141
+ detail::protect(rb_const_set, this->value(), name.id(), value.value());
142
+ return value;
143
+ }
144
+
145
+ inline Object Object::const_set_maybe(Identifier name, Object value)
146
+ {
147
+ if (!this->const_defined(name))
148
+ {
149
+ this->const_set(name, value);
150
+ }
151
+ return value;
152
+ }
153
+
154
+ inline void Object::remove_const(Identifier name)
155
+ {
156
+ detail::protect(rb_mod_remove_const, this->value(), name.to_sym());
157
+ }
158
+
159
+ inline bool operator==(Object const& lhs, Object const& rhs)
160
+ {
161
+ VALUE result = detail::protect(rb_equal, lhs.value(), rhs.value());
162
+ return result == Qtrue ? true : false;
163
+ }
164
+
165
+ inline bool operator!=(Object const& lhs, Object const& rhs)
166
+ {
167
+ return !(lhs == rhs);
168
+ }
169
+
170
+ inline bool operator<(Object const& lhs, Object const& rhs)
171
+ {
172
+ Object result = lhs.call("<", rhs);
173
+ return result.test();
174
+ }
175
+
176
+ inline bool operator>(Object const& lhs, Object const& rhs)
177
+ {
178
+ Object result = lhs.call(">", rhs);
179
+ return result.test();
180
+ }
181
+ }
182
+
183
+ namespace Rice::detail
184
+ {
185
+ template<>
186
+ struct Type<Object>
187
+ {
188
+ static bool verify()
189
+ {
190
+ return true;
191
+ }
192
+ };
193
+
194
+ template<>
195
+ class To_Ruby<Object>
196
+ {
197
+ public:
198
+ static VALUE convert(Object const& x)
199
+ {
200
+ return x.value();
201
+ }
202
+ };
203
+
204
+ template<>
205
+ class To_Ruby<Object&>
206
+ {
207
+ public:
208
+ static VALUE convert(Object const& x)
209
+ {
210
+ return x.value();
211
+ }
212
+ };
213
+
214
+ template<>
215
+ class From_Ruby<Object>
216
+ {
217
+ public:
218
+ Convertible is_convertible(VALUE value)
219
+ {
220
+ switch (rb_type(value))
221
+ {
222
+ case RUBY_T_OBJECT:
223
+ return Convertible::Exact;
224
+ break;
225
+ default:
226
+ return Convertible::None;
227
+ }
228
+ }
229
+
230
+ Object convert(VALUE value)
231
+ {
232
+ return Object(value);
233
+ }
234
+ };
235
+ }
@@ -0,0 +1,74 @@
1
+ #ifndef Rice__String__hpp_
2
+ #define Rice__String__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ //! A Wraper for the ruby String class.
7
+ /*! This class provides a C++-style interface to ruby's String class and
8
+ * its associated rb_str_* functions.
9
+ *
10
+ * Example:
11
+ * \code
12
+ * String s(String::format("%s: %d", "foo", 42));
13
+ * std::cout << s.length() << std::endl;
14
+ * \endcode
15
+ */
16
+ class String
17
+ : public Builtin_Object<T_STRING>
18
+ {
19
+ public:
20
+ //! Construct a new string.
21
+ String();
22
+
23
+ //! Wrap an existing string.
24
+ String(VALUE v);
25
+
26
+ //! Wrap an existing string.
27
+ String(Object v);
28
+
29
+ //! Construct a String from an Identifier.
30
+ String(Identifier id);
31
+
32
+ //! Construct a String from a null-terminated C string.
33
+ String(char const* s);
34
+
35
+ //! Construct a String from an std::string.
36
+ String(std::string const& s);
37
+
38
+ //! Construct a String from an std::string_view.
39
+ String(std::string_view const& s);
40
+
41
+ //! Format a string using printf-style formatting.
42
+ template <typename... Arg_Ts>
43
+ static inline String format(char const* fmt, Arg_Ts&&...args);
44
+
45
+ //! Get the length of the String.
46
+ /*! \return the length of the string.
47
+ */
48
+ size_t length() const;
49
+
50
+ //! Get the character at the given index.
51
+ /*! \param index the desired index.
52
+ * \return the character at the given index.
53
+ */
54
+ char operator[](ptrdiff_t index) const;
55
+
56
+ //! Return a pointer to the beginning of the underlying C string.
57
+ char const* c_str() const;
58
+
59
+ //! Return a copy of the string as an std::string.
60
+ std::string str() const;
61
+
62
+ //! Return an array from a string by unpacking it
63
+ template<typename T>
64
+ Array unpack() const;
65
+
66
+ //! Create an Identifier from the String.
67
+ /*! Calls rb_intern to create an ID.
68
+ * \return an Identifier holding the ID returned from rb_intern.
69
+ */
70
+ Identifier intern() const;
71
+ };
72
+ } // namespace Rice
73
+
74
+ #endif // Rice__String__hpp_
@@ -0,0 +1,120 @@
1
+ namespace Rice
2
+ {
3
+ inline String::String() : Builtin_Object<T_STRING>(detail::protect(rb_str_new2, ""))
4
+ {
5
+ }
6
+
7
+ inline String::String(VALUE v) : Builtin_Object<T_STRING>(v)
8
+ {
9
+ }
10
+
11
+ inline String::String(Object v) : Builtin_Object<T_STRING>(v)
12
+ {
13
+ }
14
+
15
+ inline String::String(char const* s) : Builtin_Object<T_STRING>(detail::protect(rb_utf8_str_new_cstr, s))
16
+ {
17
+ }
18
+
19
+ inline String::String(std::string const& s) : Builtin_Object<T_STRING>(detail::protect(rb_utf8_str_new, s.data(), (long)s.length()))
20
+ {
21
+ }
22
+
23
+ inline String::String(std::string_view const& s) : Builtin_Object<T_STRING>(detail::protect(rb_utf8_str_new, s.data(), (long)s.length()))
24
+ {
25
+ }
26
+
27
+ inline String::String(Identifier id) : Builtin_Object<T_STRING>(detail::protect(rb_utf8_str_new_cstr, id.c_str()))
28
+ {
29
+ }
30
+
31
+ template <typename... Arg_Ts>
32
+ inline String String::format(char const* fmt, Arg_Ts&&...args)
33
+ {
34
+ size_t size = std::snprintf(nullptr, 0, fmt, std::forward<Arg_Ts>(args)...);
35
+ std::string temp(size, '\0');
36
+
37
+ // size+1 avoids truncating the string. Otherwise snprintf writes n - 1 characters
38
+ // to allow space for null character but we don't need that since std::string
39
+ // will add a null character internally at n + 1
40
+ std::snprintf(&temp[0], size + 1, fmt, std::forward<Arg_Ts>(args)...);
41
+
42
+ String s = String(temp.c_str());
43
+ return s;
44
+ }
45
+
46
+ inline size_t String::length() const
47
+ {
48
+ return RSTRING_LEN(value());
49
+ }
50
+
51
+ inline char String::operator[](ptrdiff_t index) const
52
+ {
53
+ return RSTRING_PTR(value())[index];
54
+ }
55
+
56
+ inline char const* String::c_str() const
57
+ {
58
+ return RSTRING_PTR(value());
59
+ }
60
+
61
+ inline std::string String::str() const
62
+ {
63
+ return std::string(RSTRING_PTR(value()), length());
64
+ }
65
+
66
+ template<typename T>
67
+ inline Array String::unpack() const
68
+ {
69
+ return this->call("unpack", detail::RubyType<T>::packTemplate.c_str());
70
+ }
71
+
72
+ inline Identifier String::intern() const
73
+ {
74
+ return rb_intern(c_str());
75
+ }
76
+ }
77
+
78
+ namespace Rice::detail
79
+ {
80
+ template<>
81
+ struct Type<String>
82
+ {
83
+ static bool verify()
84
+ {
85
+ return true;
86
+ }
87
+ };
88
+
89
+ template<>
90
+ class To_Ruby<String>
91
+ {
92
+ public:
93
+ VALUE convert(String const& x)
94
+ {
95
+ return x.value();
96
+ }
97
+ };
98
+
99
+ template<>
100
+ class From_Ruby<String>
101
+ {
102
+ public:
103
+ Convertible is_convertible(VALUE value)
104
+ {
105
+ switch (rb_type(value))
106
+ {
107
+ case RUBY_T_STRING:
108
+ return Convertible::Exact;
109
+ break;
110
+ default:
111
+ return Convertible::None;
112
+ }
113
+ }
114
+
115
+ String convert(VALUE value)
116
+ {
117
+ return String(value);
118
+ }
119
+ };
120
+ }