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 ///////////////////////////////////////////////////////////////////////////////
29 // Forward declare to avoid including tv-conversions.h and creating a cycle.
30 ObjectData
* tvCastToObjectData(TypedValue tv
);
33 * Object type wrapping around ObjectData to implement reference count.
37 req::ptr
<ObjectData
> m_obj
;
39 using NoIncRef
= req::ptr
<ObjectData
>::NoIncRef
;
44 ObjectData
* get() const { return m_obj
.get(); }
45 void reset(ObjectData
* obj
= nullptr) { m_obj
.reset(obj
); }
47 ObjectData
* operator->() const {
54 explicit Object(ObjectData
*data
) : m_obj(data
) {
55 // The object must have at least two refs here. One pre-existing ref, and
56 // one caused by placing it under m_obj's control.
57 assertx(!data
|| data
->hasMultipleRefs());
59 /* implicit */ Object(const Object
& src
) : m_obj(src
.m_obj
) {
60 assertx(!m_obj
|| m_obj
->hasMultipleRefs());
64 explicit Object(const req::ptr
<T
> &ptr
) : m_obj(ptr
) {
65 assertx(!m_obj
|| m_obj
->hasMultipleRefs());
69 explicit Object(req::ptr
<T
>&& ptr
) : m_obj(std::move(ptr
)) {
70 assertx(!m_obj
|| m_obj
->checkCount());
73 explicit Object(Class
* cls
)
74 : m_obj(ObjectData::newInstance(cls
), NoIncRef
{}) {
75 // References to the object can escape inside newInstance, so we only know
76 // that the ref-count is at least 1 here.
77 assertx(!m_obj
|| m_obj
->checkCount());
80 explicit Object(Class
* cls
, ArrayData
* reifiedTypes
)
81 : m_obj(ObjectData::newInstanceReified(cls
, reifiedTypes
), NoIncRef
{}) {
82 // References to the object can escape inside newInstance, so we only know
83 // that the ref-count is at least 1 here.
84 assertx(!m_obj
|| m_obj
->checkCount());
88 Object(Object
&& src
) noexcept
: m_obj(std::move(src
.m_obj
)) {
89 assertx(!m_obj
|| m_obj
->checkCount());
93 Object
& operator=(const Object
& src
) {
95 assertx(!m_obj
|| m_obj
->hasMultipleRefs());
100 Object
& operator=(const req::ptr
<T
>& src
) {
102 assertx(!m_obj
|| m_obj
->hasMultipleRefs());
107 Object
& operator=(Object
&& src
) {
108 m_obj
= std::move(src
.m_obj
);
109 assertx(!m_obj
|| m_obj
->checkCount());
113 template <typename T
>
114 Object
& operator=(req::ptr
<T
>&& src
) {
115 m_obj
= std::move(src
);
116 assertx(!m_obj
|| m_obj
->checkCount());
123 explicit operator bool() const { return (bool)m_obj
; }
125 bool isNull() const { return !m_obj
; }
126 bool instanceof(const String
& s
) const {
127 return m_obj
&& m_obj
->instanceof(s
);
129 bool instanceof(const Class
* cls
) const {
130 return m_obj
&& m_obj
->instanceof(cls
);
136 bool toBoolean() const { return m_obj
? m_obj
->toBoolean() : false; }
137 char toByte () const { return toInt64(); }
138 int16_t toInt16 () const { return toInt64(); }
139 int32_t toInt32 () const { return toInt64(); }
140 int64_t toInt64 () const { return m_obj
? m_obj
->toInt64() : 0; }
141 double toDouble () const { return m_obj
? m_obj
->toDouble() : 0; }
142 String
toString () const;
143 Array
toArray () const;
145 // Transfer ownership of our reference to this object.
146 ObjectData
*detach() { return m_obj
.detach(); }
148 // Take ownership of a reference without touching the ref count
149 static Object
attach(ObjectData
*object
) {
150 assertx(!object
|| object
->checkCount());
151 return Object
{req::ptr
<ObjectData
>::attach(object
)};
155 template <typename T
>
156 friend typename
std::enable_if
<
157 std::is_base_of
<ObjectData
,T
>::value
,
159 >::type
deref(const Object
& o
) { return o
.get(); }
161 template <typename T
>
162 friend typename
std::enable_if
<
163 std::is_base_of
<ObjectData
,T
>::value
,
165 >::type
detach(Object
&& o
) { return o
.detach(); }
167 static void compileTimeAssertions();
169 const char* classname_cstr() const;
172 extern const Object null_object
;
174 ///////////////////////////////////////////////////////////////////////////////
178 explicit ObjNR(ObjectData
* data
) {
183 return *reinterpret_cast<Object
*>(this); // XXX
186 const Object
& asObject() const {
187 return const_cast<ObjNR
*>(this)->asObject();
193 static void compileTimeAssertions();
196 ///////////////////////////////////////////////////////////////////////////////
198 ALWAYS_INLINE
const Object
& asCObjRef(tv_rval tv
) {
199 assertx(tvIsObject(tv
));
200 return reinterpret_cast<const Object
&>(val(tv
).pobj
);
203 ALWAYS_INLINE Object
toObject(tv_rval tv
) {
204 if (tvIsObject(tv
)) return Object
{assert_not_null(val(tv
).pobj
)};
205 return Object::attach(tvCastToObjectData(*tv
));
210 #endif // incl_HPHP_OBJECT_H_