2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 #include "hphp/runtime/vm/member-operations.h"
18 #include "hphp/runtime/ext/ext_collections.h"
22 StringData
* prepareAnyKey(TypedValue
* tv
) {
23 if (IS_STRING_TYPE(tv
->m_type
)) {
24 StringData
* str
= tv
->m_data
.pstr
;
28 return tvAsCVarRef(tv
).toString().detach();
32 void objArrayAccess(ObjectData
* base
) {
33 assert(!base
->isCollection());
34 if (!base
->getVMClass()->classof(SystemLib::s_ArrayAccessClass
)) {
35 raise_error("Object does not implement ArrayAccess");
39 TypedValue
* objOffsetGet(TypedValue
& tvRef
, ObjectData
* base
,
40 const Variant
& offset
, bool validate
/* = true */) {
45 assert(!base
->isCollection());
46 static StringData
* sd__offsetGet
= makeStaticString("offsetGet");
47 const Func
* method
= base
->methodNamed(sd__offsetGet
);
48 assert(method
!= nullptr);
49 g_context
->invokeFuncFew(&tvRef
, method
, base
, nullptr, 1, offset
.asCell());
54 static bool objOffsetExists(ObjectData
* base
, const Variant
& offset
) {
57 tvWriteUninit(&tvResult
);
58 static StringData
* sd__offsetExists
59 = makeStaticString("offsetExists");
60 assert(!base
->isCollection());
61 const Func
* method
= base
->methodNamed(sd__offsetExists
);
62 assert(method
!= nullptr);
63 g_context
->invokeFuncFew(&tvResult
, method
, base
, nullptr, 1,
65 tvCastToBooleanInPlace(&tvResult
);
66 return bool(tvResult
.m_data
.num
);
69 bool objOffsetIsset(TypedValue
& tvRef
, ObjectData
* base
, const Variant
& offset
,
70 bool validate
/* = true */) {
71 auto exists
= objOffsetExists(base
, offset
);
77 if (!base
->getVMClass()->classof(SystemLib::s_ArrayObjectClass
)) {
82 tvWriteUninit(&tvResult
);
83 return is_not_null(tvAsVariant(objOffsetGet(tvResult
, base
, offset
)));
86 bool objOffsetEmpty(TypedValue
& tvRef
, ObjectData
* base
, const Variant
& offset
,
87 bool validate
/* = true */) {
88 if (!objOffsetExists(base
, offset
)) {
91 TypedValue
* result
= objOffsetGet(tvRef
, base
, offset
, false);
93 return !cellToBool(*tvToCell(result
));
96 void objOffsetAppend(ObjectData
* base
, TypedValue
* val
,
97 bool validate
/* = true */) {
98 assert(!base
->isCollection());
100 objArrayAccess(base
);
102 objOffsetSet(base
, init_null_variant
, val
, false);
105 void objOffsetSet(ObjectData
* base
, const Variant
& offset
, TypedValue
* val
,
106 bool validate
/* = true */) {
108 objArrayAccess(base
);
110 static StringData
* sd__offsetSet
= makeStaticString("offsetSet");
111 assert(!base
->isCollection());
112 const Func
* method
= base
->methodNamed(sd__offsetSet
);
113 assert(method
!= nullptr);
115 tvWriteUninit(&tvResult
);
116 TypedValue args
[2] = { *offset
.asCell(), *tvToCell(val
) };
117 g_context
->invokeFuncFew(&tvResult
, method
, base
, nullptr, 2, args
);
118 tvRefcountedDecRef(&tvResult
);
121 void objOffsetUnset(ObjectData
* base
, const Variant
& offset
) {
122 objArrayAccess(base
);
123 static StringData
* sd__offsetUnset
124 = makeStaticString("offsetUnset");
125 assert(!base
->isCollection());
126 const Func
* method
= base
->methodNamed(sd__offsetUnset
);
127 assert(method
!= nullptr);
130 g_context
->invokeFuncFew(&tv
, method
, base
, nullptr, 1, offset
.asCell());
131 tvRefcountedDecRef(&tv
);
134 // Mutable collections support appending new elements using [] without a key
135 // like so: "$vector[] = 123;". However, collections do not support using []
136 // without a key to implicitly create a new element without supplying assigning
137 // an initial value (ex "$vector[]['a'] = 73;").
138 void throw_cannot_use_newelem_for_lval_read() {
139 Object
e(SystemLib::AllocInvalidOperationExceptionObject(
140 "Cannot use [] with collections for reading in an lvalue context"));
144 ///////////////////////////////////////////////////////////////////////////////