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
data/rice/Enum.hpp CHANGED
@@ -1,117 +1,67 @@
1
1
  #ifndef Rice__Enum__hpp_
2
2
  #define Rice__Enum__hpp_
3
3
 
4
- #include "to_from_ruby_defn.hpp"
5
- #include "Address_Registration_Guard.hpp"
6
- #include "Array.hpp"
7
- #include "Hash.hpp"
8
- #include "String.hpp"
9
- #include "Module.hpp"
10
4
  #include "Data_Type.hpp"
5
+ #include <map>
11
6
 
12
7
  namespace Rice
13
8
  {
14
-
15
- //! Default traits for the Enum class template.
16
- template<typename Enum_T>
17
- struct Default_Enum_Traits
18
- {
19
- //! Converts the enum value to a long.
20
- static long as_long(Enum_T value);
21
- };
22
-
23
- /*!
24
- * \example enum/sample_enum.cpp
25
- */
26
-
27
- //! A wrapper for enumerated types.
28
- /*! Provides a simple type-safe wrapper for enumerated types. At the
29
- * ruby level, the class will have convenience methods for iterating
30
- * over all the defined enum values, converting the values to strings,
31
- * and more.
32
- *
33
- * \param Enum_T the enumerated type
34
- * \param Enum_Traits specifies the traits of the enumerated type.
35
- *
36
- * Example:
37
- * \code
38
- * enum Color { Red, Green, Blue };
39
- * Enum<Color> rb_cColor = define_enum<Color>("Color")
40
- * .define_value("Red", Red)
41
- * .define_value("Green", Green)
42
- * .define_value("Blue", Blue);
43
- * \endcode
44
- */
45
- template<typename Enum_T, typename Enum_Traits = Default_Enum_Traits<Enum_T> >
46
- class Enum
47
- : public Module_impl<Data_Type<Enum_T>, Enum<Enum_T, Enum_Traits> >
48
- {
49
- public:
50
- //! Default constructor.
51
- Enum();
52
-
53
- //! Construct and initialize.
54
- Enum(
55
- char const * name,
56
- Module module = rb_cObject);
57
-
58
- //! Copy constructor.
59
- Enum(Enum const & other);
60
-
61
- //! Assignment operator.
62
- Enum & operator=(Enum const & other);
63
-
64
- //! Destructor.
65
- virtual ~Enum();
66
-
67
- //! Define a new enum value.
68
- /*! \param name the name of the enum value.
69
- * \param value the value to associate with name.
70
- * \return *this
9
+ /*!
10
+ * \example enum/sample_enum.cpp
71
11
  */
72
- Enum<Enum_T, Enum_Traits> & define_value(
73
- char const * name,
74
- Enum_T value);
75
-
76
- void swap(Enum & other);
77
-
78
- private:
79
- //! Initialize the enum type.
80
- /*! Must be called only once.
81
- * \param name the name of the class to define
82
- * \param module the module in which to place the enum class.
83
- * \return *this
84
- */
85
- Enum<Enum_T, Enum_Traits> & initialize(
86
- char const * name,
87
- Module module = rb_cObject);
88
-
89
- private:
90
- static Object each(Object self);
91
- static Object to_s(Object self);
92
- static Object to_i(Object self);
93
- static Object inspect(Object self);
94
- static Object compare(Object lhs, Object rhs);
95
- static Object eql(Object lhs, Object rhs);
96
- static Object hash(Object self);
97
- static Object from_int(Class klass, Object i);
98
-
99
- private:
100
- Array enums_;
101
- Address_Registration_Guard enums_guard_;
102
-
103
- Hash names_;
104
- Address_Registration_Guard names_guard_;
105
- };
106
-
107
- template<typename T>
108
- Enum<T> define_enum(
109
- char const * name,
110
- Module module = rb_cObject);
111
12
 
13
+ //! A wrapper for enumerated types.
14
+ /*! Provides a simple type-safe wrapper for enumerated types. At the
15
+ * ruby level, the class will have convenience methods for iterating
16
+ * over all the defined enum values, converting the values to strings,
17
+ * and more.
18
+ *
19
+ * \param Enum_T the enumerated type
20
+ *
21
+ * Example:
22
+ * \code
23
+ * enum Color { Red, Green, Blue };
24
+ * Enum<Color> rb_cColor = define_enum<Color>("Color")
25
+ * .define_value("Red", Red)
26
+ * .define_value("Green", Green)
27
+ * .define_value("Blue", Blue);
28
+ * \endcode
29
+ */
30
+ template<typename Enum_T>
31
+ class Enum : public Data_Type<Enum_T>
32
+ {
33
+ using Underlying_T = std::underlying_type_t<Enum_T>;
34
+
35
+ public:
36
+
37
+ Enum() = default;
38
+
39
+ //! Construct and initialize.
40
+ Enum(char const* name, Module module = rb_cObject);
41
+
42
+ //! Define a new enum value.
43
+ /*! \param name the name of the enum value.
44
+ * \param value the value to associate with name.
45
+ * \return *this
46
+ */
47
+ Enum<Enum_T>& define_value(std::string name, Enum_T value);
48
+
49
+ //! Maps an enum value to the correct Ruby object
50
+ /*! \param klass The bound Ruby class
51
+ * \param enumValue The enum value
52
+ * \return Object - The Ruby wrapper */
53
+ static Object from_enum(Class klass, Enum_T enumValue);
54
+
55
+ private:
56
+ void define_methods(Data_Type<Enum_T> klass);
57
+
58
+ static inline std::map<Enum_T, std::string> valuesToNames_;
59
+ };
60
+
61
+ template<typename T>
62
+ Enum<T> define_enum(char const* name, Module module = rb_cObject);
112
63
  } // namespace Rice
113
64
 
114
65
  #include "Enum.ipp"
115
66
 
116
- #endif // Rice__Enum__hpp_
117
-
67
+ #endif // Rice__Enum__hpp_
data/rice/Enum.ipp CHANGED
@@ -1,246 +1,120 @@
1
- #ifndef Rice__Enum__ipp_
2
- #define Rice__Enum__ipp_
3
-
1
+ #include "detail/TypeRegistry.hpp"
4
2
  #include "Data_Object.hpp"
5
- #include "Class.hpp"
6
- #include "String.hpp"
7
- #include "protect.hpp"
8
- #include <memory>
9
-
10
- template<typename Enum_T>
11
- long Rice::Default_Enum_Traits<Enum_T>::as_long(Enum_T value)
12
- {
13
- return static_cast<long>(value);
14
- }
15
-
16
- template<typename Enum_T, typename Enum_Traits>
17
- Rice::Enum<Enum_T, Enum_Traits>::
18
- Enum()
19
- : Module_impl<Data_Type<Enum_T>, Enum<Enum_T, Enum_Traits> >()
20
- , enums_()
21
- , enums_guard_(&enums_)
22
- , names_()
23
- , names_guard_(&names_)
24
- {
25
- }
26
-
27
- template<typename Enum_T, typename Enum_Traits>
28
- Rice::Enum<Enum_T, Enum_Traits>::
29
- Enum(
30
- char const * name,
31
- Module module)
32
- : Module_impl<Data_Type<Enum_T>, Enum<Enum_T, Enum_Traits> >()
33
- , enums_()
34
- , enums_guard_(&enums_)
35
- , names_()
36
- , names_guard_(&names_)
37
- {
38
- this->template bind<void>(initialize(name, module));
39
- }
40
-
41
- template<typename Enum_T, typename Enum_Traits>
42
- Rice::Enum<Enum_T, Enum_Traits>::
43
- Enum(Enum<Enum_T, Enum_Traits> const & other)
44
- : Module_impl<Data_Type<Enum_T>, Enum<Enum_T, Enum_Traits> >(other)
45
- , enums_(other.enums_)
46
- , enums_guard_(&enums_)
47
- , names_(other.names_)
48
- , names_guard_(&names_)
49
- {
50
- }
51
-
52
- template<typename Enum_T, typename Enum_Traits>
53
- Rice::Enum<Enum_T, Enum_Traits> & Rice::Enum<Enum_T, Enum_Traits>::
54
- operator=(Rice::Enum<Enum_T, Enum_Traits> const & other)
55
- {
56
- Rice::Enum<Enum_T, Enum_Traits> tmp(other);
57
- this->swap(tmp);
58
- return *this;
59
- }
60
-
61
- template<typename Enum_T, typename Enum_Traits>
62
- Rice::Enum<Enum_T, Enum_Traits>::
63
- ~Enum()
64
- {
65
- }
66
-
67
- template<typename Enum_T, typename Enum_Traits>
68
- Rice::Enum<Enum_T, Enum_Traits> & Rice::Enum<Enum_T, Enum_Traits>::
69
- initialize(
70
- char const * name,
71
- Module module)
72
- {
73
- Class c = Rice::define_class_under<Enum_T>(module, name)
74
- .define_method("to_s", to_s)
75
- .define_method("to_i", to_i)
76
- .define_method("inspect", inspect)
77
- .define_method("<=>", compare)
78
- .define_method("hash", hash)
79
- .define_method("eql?", eql)
80
- .define_method("==", eql)
81
- .define_method("===", eql)
82
- .define_singleton_method("each", each)
83
- .define_singleton_method("from_int", from_int)
84
- .include_module(rb_mComparable);
85
-
86
- // TODO: This should be unnecessary (it should be taken care of when
87
- // define_class_under binds the C++ and ruby types)
88
- this->set_value(c);
89
-
90
- protect(rb_iv_set, c, "enums", enums_);
91
- protect(rb_iv_set, c, "names", names_);
92
-
93
- return *this;
94
- }
95
-
96
- template<typename Enum_T, typename Enum_Traits>
97
- Rice::Enum<Enum_T, Enum_Traits> & Rice::Enum<Enum_T, Enum_Traits>::
98
- define_value(
99
- char const * name,
100
- Enum_T value)
101
- {
102
- std_unique_ptr<Enum_T> copy(new Enum_T(value));
103
- Rice::Data_Object<Enum_T> m(copy.get(), *this);
104
- copy.release();
105
- names_[m] = String(name);
106
- this->const_set(name, m);
107
- enums_.push(m);
108
-
109
- return *this;
110
- }
3
+ #include "cpp_api/String.hpp"
111
4
 
5
+ #include <stdexcept>
112
6
 
113
- template<typename Enum_T, typename Enum_Traits>
114
- void Rice::Enum<Enum_T, Enum_Traits>::
115
- swap(Enum<Enum_T, Enum_Traits> & other)
7
+ namespace Rice
116
8
  {
117
- Data_Type<Enum_T>::swap(other);
118
- enums_.swap(other.enums_);
119
- names_.swap(other.names_);
120
- }
121
-
122
- template<typename Enum_T, typename Enum_Traits>
123
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
124
- each(Object self)
125
- {
126
- VALUE enums_v = rb_iv_get(self, "enums");
127
- Check_Type(enums_v, T_ARRAY);
128
- Array enums(enums_v);
129
- for(size_t j = 0; j < enums.size(); ++j)
9
+ template<typename Enum_T>
10
+ Enum<Enum_T>::Enum(char const* name, Module module) : Data_Type<Enum_T>()
130
11
  {
131
- rb_yield(enums[j].value());
12
+ Data_Type<Enum_T> klass = define_class_under<Enum_T>(module, name);
13
+ define_methods(klass);
132
14
  }
133
- return Qnil;
134
- }
135
15
 
136
- template<typename Enum_T, typename Enum_Traits>
137
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
138
- to_s(Object self)
139
- {
140
- Data_Type<Enum_T> klass;
141
- Rice::Data_Object<Enum_T> m(self, klass);
142
- Object enum_class = rb_class_of(m);
143
- Hash names(rb_iv_get(enum_class, "names"));
144
- Object name = names[m];
145
- if(name.is_nil())
16
+ template<typename Enum_T>
17
+ inline Enum<Enum_T>& Enum<Enum_T>::define_value(std::string name, Enum_T value)
146
18
  {
147
- return String::format("INVALID(%d)", Enum_Traits::as_long(*m));
148
- }
149
- else
150
- {
151
- return String(name);
152
- }
153
- }
19
+ // Save mapping from value to name
20
+ valuesToNames_[value] = name;
154
21
 
155
- template<typename Enum_T, typename Enum_Traits>
156
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
157
- inspect(Object self)
158
- {
159
- return String::format(
160
- "#<%s::%s>",
161
- String(self.class_of().name()).c_str(),
162
- String(to_s(self)).c_str());
163
- }
22
+ // Store value as class constant available to Ruby
23
+ Data_Object<Enum_T> object(value, true, Enum<Enum_T>::klass());
24
+ this->const_set(name, object);
164
25
 
165
- template<typename Enum_T, typename Enum_Traits>
166
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
167
- compare(Object lhs, Object rhs)
168
- {
169
- if(lhs.class_of() != rhs.class_of())
170
- {
171
- String lhs_name(lhs.class_of().name());
172
- String rhs_name(rhs.class_of().name());
173
- rb_raise(
174
- rb_eTypeError,
175
- "Cannot compare %s to %s",
176
- lhs_name.c_str(),
177
- rhs_name.c_str());
26
+ return *this;
178
27
  }
179
28
 
180
- Data_Type<Enum_T> klass;
181
- Rice::Data_Object<Enum_T> l(lhs, klass);
182
- Rice::Data_Object<Enum_T> r(rhs, klass);
183
-
184
- Enum_T left(*l);
185
- Enum_T right(*r);
186
-
187
- if(left == right)
188
- {
189
- return INT2NUM(0);
190
- }
191
- else if(Enum_Traits::as_long(left) < Enum_Traits::as_long(right))
192
- {
193
- return INT2NUM(-1);
194
- }
195
- else
29
+ template<typename Enum_T>
30
+ inline void Enum<Enum_T>::define_methods(Data_Type<Enum_T> klass)
196
31
  {
197
- return INT2NUM(1);
32
+ // First we need a constructor
33
+ klass.define_constructor(Constructor<Enum_T>());
34
+
35
+ // Instance methods
36
+ klass.define_method("to_s", [](Enum_T& self)
37
+ {
38
+ // We have to return string because we don't know if std::string support has
39
+ // been included by the user
40
+ return String(valuesToNames_[self]);
41
+ })
42
+ .define_method("to_i", [](Enum_T& self) -> Underlying_T
43
+ {
44
+ return (Underlying_T)self;
45
+ })
46
+ .define_method("inspect", [](Enum_T& self)
47
+ {
48
+ std::stringstream result;
49
+ VALUE rubyKlass = Enum<Enum_T>::klass().value();
50
+ result << "#<" << detail::protect(rb_class2name, rubyKlass)
51
+ << "::" << Enum<Enum_T>::valuesToNames_[self] << ">";
52
+
53
+ // We have to return string because we don't know if std::string support has
54
+ // been included by the user
55
+ return String(result.str());
56
+ })
57
+ .define_method("<=>", [](Enum_T& self, Enum_T& other)
58
+ {
59
+ if (self == other)
60
+ {
61
+ return 0;
62
+ }
63
+ else if (self < other)
64
+ {
65
+ return -1;
66
+ }
67
+ else
68
+ {
69
+ return 1;
70
+ }
71
+ })
72
+ .define_method("hash", [](Enum_T& self) -> Underlying_T
73
+ {
74
+ return (Underlying_T)self;
75
+ })
76
+ .define_method("eql?", [](Enum_T& self, Enum_T& other)
77
+ {
78
+ return self == other;
79
+ });
80
+
81
+ // Add aliases
82
+ rb_define_alias(klass, "===", "eql?");
83
+
84
+ // Add comparable support
85
+ klass.include_module(rb_mComparable);
86
+
87
+ // Singleton methods
88
+ klass.define_singleton_method("each", [](VALUE klass)
89
+ {
90
+ for (auto& pair : valuesToNames_)
91
+ {
92
+ Enum_T enumValue = pair.first;
93
+ VALUE value = detail::To_Ruby<Enum_T>().convert(enumValue);
94
+ detail::protect(rb_yield, value);
95
+ }
96
+ })
97
+ .define_singleton_method("from_int", [](VALUE klass, int32_t value)
98
+ {
99
+ auto iter = Enum<Enum_T>::valuesToNames_.find((Enum_T)value);
100
+ if (iter == Enum<Enum_T>::valuesToNames_.end())
101
+ {
102
+ throw std::runtime_error("Unknown enum value: " + std::to_string(value));
103
+ }
104
+
105
+ std::string name = iter->second;
106
+ return Class(klass).const_get(name);
107
+ });
198
108
  }
199
- }
200
109
 
201
- template<typename Enum_T, typename Enum_Traits>
202
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
203
- eql(Object lhs, Object rhs)
204
- {
205
- using ::from_ruby; // Workaround for g++ 3.3.3
206
- bool is_equal = from_ruby<int>(compare(lhs, rhs)) == 0;
207
- return to_ruby(is_equal);
208
- }
209
-
210
- template<typename Enum_T, typename Enum_Traits>
211
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
212
- to_i(Object self)
213
- {
214
- Data_Type<Enum_T> klass;
215
- Rice::Data_Object<Enum_T> m(self, klass);
216
- return LONG2NUM(Enum_Traits::as_long(*m));
217
- }
218
-
219
- template<typename Enum_T, typename Enum_Traits>
220
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
221
- hash(Object self)
222
- {
223
- return to_i(self);
224
- }
225
-
226
- template<typename Enum_T, typename Enum_Traits>
227
- Rice::Object Rice::Enum<Enum_T, Enum_Traits>::
228
- from_int(Class klass, Object i)
229
- {
230
- using ::from_ruby; // Workaround for g++ 3.3.3
231
- Rice::Data_Object<Enum_T> m(
232
- new Enum_T(static_cast<Enum_T>(from_ruby<long>(i))),
233
- klass);
234
- return m.value();
235
- }
236
-
237
- template<typename T>
238
- Rice::Enum<T> Rice::
239
- define_enum(
240
- char const * name,
241
- Module module)
242
- {
243
- return Enum<T>(name, module);
244
- }
245
- #endif // Rice__Enum__ipp_
110
+ template<typename Enum_T>
111
+ Enum<Enum_T> define_enum(char const* name, Module module)
112
+ {
113
+ if (detail::TypeRegistry::isDefined<Enum_T>())
114
+ {
115
+ return Enum<Enum_T>();
116
+ }
246
117
 
118
+ return Enum<Enum_T>(name, module);
119
+ }
120
+ }