2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_OBJECT_H_
18 #define incl_HPHP_OBJECT_H_
20 #include "hphp/runtime/base/object-data.h"
21 #include "hphp/runtime/base/req-ptr.h"
22 #include "hphp/runtime/base/typed-value.h"
27 ///////////////////////////////////////////////////////////////////////////////
30 * Object type wrapping around ObjectData to implement reference count.
34 req::ptr
<ObjectData
> m_obj
;
36 using NoIncRef
= req::ptr
<ObjectData
>::NoIncRef
;
41 ObjectData
* get() const { return m_obj
.get(); }
42 void reset(ObjectData
* obj
= nullptr) { m_obj
.reset(obj
); }
44 ObjectData
* operator->() const {
51 explicit Object(ObjectData
*data
) : m_obj(data
) {
52 // The object must have at least two refs here. One pre-existing ref, and
53 // one caused by placing it under m_obj's control.
54 assert(!data
|| data
->hasMultipleRefs());
56 /* implicit */ Object(const Object
& src
) : m_obj(src
.m_obj
) {
57 assert(!m_obj
|| m_obj
->hasMultipleRefs());
61 explicit Object(const req::ptr
<T
> &ptr
) : m_obj(ptr
) {
62 assert(!m_obj
|| m_obj
->hasMultipleRefs());
66 explicit Object(req::ptr
<T
>&& ptr
) : m_obj(std::move(ptr
)) {
67 assert(!m_obj
|| m_obj
->checkCount());
70 explicit Object(Class
* cls
)
71 : m_obj(ObjectData::newInstance(cls
), NoIncRef
{}) {
72 // References to the object can escape inside newInstance, so we only know
73 // that the ref-count is at least 1 here.
74 assert(!m_obj
|| m_obj
->checkCount());
78 Object(Object
&& src
) noexcept
: m_obj(std::move(src
.m_obj
)) {
79 assert(!m_obj
|| m_obj
->checkCount());
83 Object
& operator=(const Object
& src
) {
85 assert(!m_obj
|| m_obj
->hasMultipleRefs());
90 Object
& operator=(const req::ptr
<T
>& src
) {
92 assert(!m_obj
|| m_obj
->hasMultipleRefs());
97 Object
& operator=(Object
&& src
) {
98 m_obj
= std::move(src
.m_obj
);
99 assert(!m_obj
|| m_obj
->checkCount());
103 template <typename T
>
104 Object
& operator=(req::ptr
<T
>&& src
) {
105 m_obj
= std::move(src
);
106 assert(!m_obj
|| m_obj
->checkCount());
113 explicit operator bool() const { return (bool)m_obj
; }
115 bool isNull() const { return !m_obj
; }
116 bool instanceof(const String
& s
) const {
117 return m_obj
&& m_obj
->instanceof(s
);
119 bool instanceof(const Class
* cls
) const {
120 return m_obj
&& m_obj
->instanceof(cls
);
124 * getTyped() and is() are intended for use with C++ classes that derive
127 * Prefer using the following functions instead of getTyped:
128 * o.getTyped<T>(false, false) -> cast<T>(o)
129 * o.getTyped<T>(true, false) -> cast_or_null<T>(o)
130 * o.getTyped<T>(false, true) -> dyn_cast<T>(o)
131 * o.getTyped<T>(true, true) -> dyn_cast_or_null<T>(o)
134 [[deprecated("Please use one of the cast family of functions instead.")]]
135 req::ptr
<T
> getTyped(bool nullOkay
= false, bool badTypeOkay
= false) const {
136 static_assert(std::is_base_of
<ObjectData
, T
>::value
, "");
138 ObjectData
*cur
= get();
141 throw_null_pointer_exception();
145 if (!cur
->instanceof(T::classof())) {
147 throw_invalid_object_type(classname_cstr());
152 return req::ptr
<T
>(static_cast<T
*>(cur
));
157 return m_obj
&& m_obj
->instanceof(T::classof());
163 bool toBoolean() const { return m_obj
? m_obj
->toBoolean() : false; }
164 char toByte () const { return toInt64(); }
165 int16_t toInt16 () const { return toInt64(); }
166 int32_t toInt32 () const { return toInt64(); }
167 int64_t toInt64 () const { return m_obj
? m_obj
->toInt64() : 0; }
168 double toDouble () const { return m_obj
? m_obj
->toDouble() : 0; }
169 String
toString () const;
170 Array
toArray () const;
172 int64_t toInt64ForCompare() const;
173 double toDoubleForCompare() const;
178 bool same(const Object
& v2
) const { return m_obj
== v2
.m_obj
; }
179 bool equal(const Object
& v2
) const {
181 (v2
.m_obj
&& m_obj
->equal(*v2
.m_obj
.get())) :
184 bool less(const Object
& v2
) const {
186 (v2
.m_obj
&& m_obj
->less(*v2
.m_obj
.get())) :
187 static_cast<bool>(v2
.m_obj
);
189 bool lessEqual(const Object
& v2
) const { return less(v2
) || equal(v2
); }
190 bool more(const Object
& v2
) const {
191 return m_obj
&& (!v2
.m_obj
|| m_obj
->more(*v2
.m_obj
.get()));
193 bool moreEqual(const Object
& v2
) const { return more(v2
) || equal(v2
); }
195 // Transfer ownership of our reference to this object.
196 ObjectData
*detach() { return m_obj
.detach(); }
198 // Take ownership of a reference without touching the ref count
199 static Object
attach(ObjectData
*object
) {
200 assert(!object
|| object
->checkCount());
201 return Object
{req::ptr
<ObjectData
>::attach(object
)};
205 template <typename T
>
206 friend typename
std::enable_if
<
207 std::is_base_of
<ObjectData
,T
>::value
,
209 >::type
deref(const Object
& o
) { return o
.get(); }
211 template <typename T
>
212 friend typename
std::enable_if
<
213 std::is_base_of
<ObjectData
,T
>::value
,
215 >::type
detach(Object
&& o
) { return o
.detach(); }
217 static void compileTimeAssertions();
219 const char* classname_cstr() const;
222 extern const Object null_object
;
224 ///////////////////////////////////////////////////////////////////////////////
228 explicit ObjNR(ObjectData
* data
) {
233 return *reinterpret_cast<Object
*>(this); // XXX
236 const Object
& asObject() const {
237 return const_cast<ObjNR
*>(this)->asObject();
243 static void compileTimeAssertions();
246 ///////////////////////////////////////////////////////////////////////////////
249 #endif // incl_HPHP_OBJECT_H_