Fixed some C/C++ compiler errors due to stricter checks.
[rubinius.git] / machine / object_utils.hpp
blob37bc277b076cb572a0c72f4f89ec5280d9f18561
1 #ifndef RBX_VM_OBJECT_UTILS_HPP
2 #define RBX_VM_OBJECT_UTILS_HPP
4 #include "class/object.hpp"
5 #include "exception.hpp"
7 /**
8 * @file object_utils.hpp
10 * Defines all the most common operations for dealing with
11 * objects, such as type checking and casting.
14 #define SPECIALIZATION_STORAGE
16 namespace rubinius {
18 /**
19 * Ruby type system subtype check.
21 * Given builtin-class +T+, return true if +obj+ is of class +T+
23 template <class T>
24 static bool kind_of(const MemoryHeader* obj) {
25 if(obj->reference_p()) {
26 return obj->type_id() == T::type;
28 return false;
31 template <class T>
32 static bool kind_of(const Object* obj) {
33 if(obj->reference_p()) {
34 return obj->type_id() == T::type;
36 return false;
39 /**
40 * A specialized version for completeness.
42 template <>
43 bool kind_of<Object>(const Object* obj) {
44 return true;
47 /**
48 * Ruby type system class check.
50 * Another version of kind_of that shouldn't be specialized for subtype
51 * compatibility. I.e., only whether object's class is this specific
52 * one.
54 template <class T>
55 static bool instance_of(const Object* obj) {
56 if(obj->reference_p()) {
57 return obj->type_id() == T::type;
59 return false;
62 /**
63 * A specialized version for completeness.
65 template <>
66 bool instance_of<Object>(const Object* obj) {
67 return obj->reference_p() && (obj->type_id() == ObjectType);
71 * There is NO reason why as() or try_as() should be getting
72 * NULL arguments. That means something has not been properly
73 * initialised (to cNil if nothing else.)
76 /**
77 * Cast Object* into builtin T*.
79 * Given builtin class +T+, return +obj+ cast as type +T*+. If
80 * +obj+ is not of type +T+, throw's a TypeError exception.
82 * @see builtin/object.cpp has specialised versions.
84 template <class T>
85 static T* as(Object* obj) {
86 if(!kind_of<T>(obj)) {
87 TypeError::raise(T::type, obj);
90 return static_cast<T*>(obj);
93 /**
94 * Cast const Object* into builtin const T*.
96 * Given builtin class +T+, return +obj+ cast as type +T*+. If
97 * +obj+ is not of type +T+, throw's a TypeError exception.
99 * @see builtin/object.cpp has specialised versions.
101 template <class T>
102 static const T* as(const Object* obj) {
103 if(!kind_of<T>(obj)) {
104 TypeError::raise(T::type, obj);
107 return static_cast<const T*>(obj);
111 * A specialized version for completeness.
113 template <>
114 Object* as<Object>(Object* obj) {
115 return obj;
119 * A specialized version for completeness.
121 template <>
122 const Object* as<Object>(const Object* obj) {
123 return obj;
127 * Cast Object* into builtin T*.
129 * Given builtin class +T+, return +obj+ cast as type +T*+. If
130 * +obj+ is not exactly of type +T+, throw's a TypeError exception.
132 * @see builtin/object.cpp has specialised versions.
134 template <class T>
135 static T* as_instance(Object* obj) {
136 if(!instance_of<T>(obj)) {
137 TypeError::raise(T::type, obj);
140 return static_cast<T*>(obj);
144 * Cast const Object* into builtin const T*.
146 * Given builtin class +T+, return +obj+ cast as type +T*+. If
147 * +obj+ is not exactly of type +T+, throw's a TypeError exception.
149 * @see builtin/object.cpp has specialised versions.
151 template <class T>
152 static const T* as_instance(const Object* obj) {
153 if(!instance_of<T>(obj)) {
154 TypeError::raise(T::type, obj);
157 return static_cast<const T*>(obj);
161 * Non-raising version of as().
163 * Similar to as<>, but returns NULL if the type is invalid. ONLY
164 * use this when doing a conditional cast.
166 * @see builtin/object.cpp has specialised versions.
168 template <class T>
169 static T* try_as(MemoryHeader* obj) {
170 if(!kind_of<T>(obj)) {
171 return nullptr;
174 return static_cast<T*>(obj);
177 template <class T>
178 static T* try_as(Object* obj) {
179 if(!kind_of<T>(obj)) {
180 return NULL;
183 return static_cast<T*>(obj);
187 * Non-raising version of as(), for const objects.
189 * Similar to as<>, but returns NULL if the type is invalid. ONLY
190 * use this when doing a conditional cast.
192 * @see builtin/object.cpp has specialised versions.
194 template <class T>
195 static const T* try_as(const MemoryHeader* obj) {
196 if(!kind_of<T>(obj)) {
197 return nullptr;
200 return static_cast<const T*>(obj);
203 template <class T>
204 static const T* try_as(const Object* obj) {
205 if(!kind_of<T>(obj)) {
206 return NULL;
209 return static_cast<const T*>(obj);
213 * Non-raising version of as_instance().
215 * Similar to as_instance<>, but returns NULL if the type is invalid. ONLY
216 * use this when doing a conditional cast.
218 * @see builtin/object.cpp has specialised versions.
220 template <class T>
221 static T* try_as_instance(Object* obj) {
222 if(!instance_of<T>(obj)) {
223 return NULL;
226 return static_cast<T*>(obj);
230 * Non-raising version of as(), for const objects.
232 * Similar to as<>, but returns NULL if the type is invalid. ONLY
233 * use this when doing a conditional cast.
235 * @see builtin/object.cpp has specialised versions.
237 template <class T>
238 static const T* try_as_instance(const Object* obj) {
239 if(!instance_of<T>(obj)) {
240 return NULL;
243 return static_cast<const T*>(obj);
247 * Returns cNil cast to another type of rubinius::Object. Useful in
248 * cases where e.g. a String* would be returned but cNil is returned
249 * as an exceptional value.
252 template <class T>
253 static T* nil() { return static_cast<T*>(cNil); }
256 * Converts one type into another without a type check. This is
257 * like reinterprete_cast<>(), but we use it so we can easily
258 * find where we're doing explicit force casts.
260 template <class T>
261 static T* force_as(ObjectHeader* obj) {
262 return reinterpret_cast<T*>(obj);
265 template <class T>
266 static const T* force_as(const ObjectHeader* obj) {
267 return reinterpret_cast<const T*>(obj);
270 void type_assert(STATE, Object* obj, object_type type, const char* reason);
272 #include "kind_of.hpp"
276 #endif