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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/vm/globals-array.h"
18 #include "hphp/runtime/base/array-init.h"
19 #include "hphp/runtime/base/array-iterator.h"
20 #include "hphp/runtime/base/rds-local.h"
21 #include "hphp/runtime/base/tv-val.h"
22 #include "hphp/runtime/base/mixed-array-defs.h"
23 #include "hphp/runtime/base/runtime-error.h"
27 //////////////////////////////////////////////////////////////////////
29 static RDS_LOCAL_NO_CHECK(GlobalsArray
*, g_variables
)(nullptr);
31 GlobalsArray
* get_global_variables() {
32 assertx(*g_variables
!= nullptr);
36 GlobalsArray::GlobalsArray(NameValueTable
* tab
)
37 : ArrayData(kGlobalsKind
)
40 Variant
arr(staticEmptyArray());
41 #define X(s,v) tab->set(makeStaticString(#s), v.asTypedValue());
43 X(argc
, init_null_variant
);
44 X(argv
, init_null_variant
);
53 X(HTTP_RAW_POST_DATA
, init_null_variant
);
57 assertx(hasExactlyOneRef());
60 inline GlobalsArray
* GlobalsArray::asGlobals(ArrayData
* ad
) {
61 assertx(ad
->kind() == kGlobalsKind
);
62 return static_cast<GlobalsArray
*>(ad
);
65 inline const GlobalsArray
*
66 GlobalsArray::asGlobals(const ArrayData
* ad
) {
67 assertx(ad
->kind() == kGlobalsKind
);
68 return static_cast<const GlobalsArray
*>(ad
);
71 size_t GlobalsArray::Vsize(const ArrayData
* ad
) {
72 // We need to iterate to find out the actual size, since kNamedLocalDataType
73 // elements in the array may have been set to KindOfUninit.
74 auto a
= asGlobals(ad
);
75 if (a
->m_tab
->leaked()) return 0;
77 auto iter_limit
= IterEnd(a
);
78 for (auto iter
= IterBegin(a
);
80 iter
= IterAdvance(a
, iter
)) {
86 Cell
GlobalsArray::NvGetKey(const ArrayData
* ad
, ssize_t pos
) {
87 auto a
= asGlobals(ad
);
88 NameValueTable::Iterator
iter(a
->m_tab
, pos
);
90 auto k
= iter
.curKey();
91 if (k
->isRefCounted()) {
93 return make_tv
<KindOfString
>(const_cast<StringData
*>(k
));
95 return make_tv
<KindOfPersistentString
>(k
);
97 return make_tv
<KindOfUninit
>();
100 tv_rval
GlobalsArray::GetValueRef(const ArrayData
* ad
, ssize_t pos
) {
101 auto a
= asGlobals(ad
);
102 NameValueTable::Iterator
iter(a
->m_tab
, pos
);
103 return iter
.valid() ? iter
.curVal() : uninit_variant
.asTypedValue();
107 GlobalsArray::ExistsInt(const ArrayData
* ad
, int64_t k
) {
108 return ExistsStr(ad
, String(k
).get());
112 GlobalsArray::ExistsStr(const ArrayData
* ad
, const StringData
* k
) {
113 return asGlobals(ad
)->m_tab
->lookup(k
) != nullptr;
116 tv_rval
GlobalsArray::NvGetStr(const ArrayData
* ad
, const StringData
* k
) {
117 return asGlobals(ad
)->m_tab
->lookup(k
);
120 tv_rval
GlobalsArray::NvGetInt(const ArrayData
* ad
, int64_t k
) {
121 return asGlobals(ad
)->m_tab
->lookup(String(k
).get());
124 arr_lval
GlobalsArray::LvalInt(ArrayData
* ad
, int64_t k
, bool copy
) {
125 return LvalStr(ad
, String(k
).get(), copy
);
128 arr_lval
GlobalsArray::LvalStr(ArrayData
* ad
, StringData
* k
, bool /*copy*/) {
129 auto a
= asGlobals(ad
);
130 TypedValue
* tv
= a
->m_tab
->lookup(k
);
134 tv
= a
->m_tab
->set(k
, &nulVal
);
136 return arr_lval
{ ad
, tv
};
139 arr_lval
GlobalsArray::LvalNew(ArrayData
* ad
, bool /*copy*/) {
140 return arr_lval
{ ad
, lvalBlackHole().asTypedValue() };
143 ArrayData
* GlobalsArray::SetIntInPlace(ArrayData
* ad
, int64_t k
, Cell v
) {
144 return SetStrInPlace(ad
, String(k
).get(), v
);
148 GlobalsArray::SetStrInPlace(ArrayData
* ad
, StringData
* k
, Cell v
) {
149 auto a
= asGlobals(ad
);
150 cellSet(v
, *tvToCell(a
->m_tab
->lookupAdd(k
)));
155 GlobalsArray::SetWithRefIntInPlace(ArrayData
* ad
, int64_t k
, TypedValue v
) {
156 return SetWithRefStrInPlace(ad
, String(k
).get(), v
);
160 GlobalsArray::SetWithRefStrInPlace(ArrayData
* ad
, StringData
* k
, TypedValue v
) {
161 auto a
= asGlobals(ad
);
162 tvSetWithRef(v
, *a
->m_tab
->lookupAdd(k
));
167 GlobalsArray::SetRefIntInPlace(ArrayData
* ad
, int64_t k
, tv_lval v
) {
168 return SetRefStrInPlace(ad
, String(k
).get(), v
);
172 GlobalsArray::SetRefStrInPlace(ArrayData
* ad
, StringData
* k
, tv_lval v
) {
173 auto a
= asGlobals(ad
);
174 tvAsVariant(a
->m_tab
->lookupAdd(k
)).assignRef(v
);
179 GlobalsArray::RemoveIntInPlace(ArrayData
* ad
, int64_t k
) {
180 return RemoveStrInPlace(ad
, String(k
).get());
184 GlobalsArray::RemoveStrInPlace(ArrayData
* ad
, const StringData
* k
) {
185 auto a
= asGlobals(ad
);
191 * The messages in the user-visible exceptions below claim we are
192 * $GLOBALS, because the only user-visible GlobalsArray array
193 * is currently $GLOBALS.
196 ArrayData
* GlobalsArray::AppendInPlace(ArrayData
*, Cell
/*v*/) {
197 throw_not_implemented("append on $GLOBALS");
200 ArrayData
* GlobalsArray::AppendRefInPlace(ArrayData
*, tv_lval
) {
201 throw_not_implemented("appendRef on $GLOBALS");
204 ArrayData
* GlobalsArray::AppendWithRefInPlace(ArrayData
*, TypedValue
) {
205 throw_not_implemented("appendWithRef on $GLOBALS");
208 ArrayData
* GlobalsArray::PlusEq(ArrayData
*, const ArrayData
*) {
209 throw_not_implemented("plus on $GLOBALS");
212 ArrayData
* GlobalsArray::Merge(ArrayData
*, const ArrayData
*) {
213 throw_not_implemented("merge on $GLOBALS");
216 ArrayData
* GlobalsArray::Prepend(ArrayData
*, Cell
) {
217 throw_not_implemented("prepend on $GLOBALS");
220 ssize_t
GlobalsArray::IterBegin(const ArrayData
* ad
) {
221 auto a
= asGlobals(ad
);
222 NameValueTable::Iterator
iter(a
->m_tab
);
223 return iter
.toInteger();
226 ssize_t
GlobalsArray::IterLast(const ArrayData
* ad
) {
227 auto a
= asGlobals(ad
);
228 return NameValueTable::Iterator::getLast(a
->m_tab
).toInteger();
231 ssize_t
GlobalsArray::IterEnd(const ArrayData
* ad
) {
232 auto a
= asGlobals(ad
);
233 return NameValueTable::Iterator::getEnd(a
->m_tab
).toInteger();
236 ssize_t
GlobalsArray::IterAdvance(const ArrayData
* ad
, ssize_t prev
) {
237 auto a
= asGlobals(ad
);
238 NameValueTable::Iterator
iter(a
->m_tab
, prev
);
240 return iter
.toInteger();
243 ssize_t
GlobalsArray::IterRewind(const ArrayData
* ad
, ssize_t prev
) {
244 auto a
= asGlobals(ad
);
245 NameValueTable::Iterator
iter(a
->m_tab
, prev
);
247 return iter
.toInteger();
251 GlobalsArray::ValidMArrayIter(const ArrayData
* ad
,
252 const MArrayIter
& fp
) {
253 assertx(fp
.getContainer() == ad
);
254 auto a
= asGlobals(ad
);
255 if (fp
.getResetFlag()) return false;
256 if (fp
.m_pos
== IterEnd(a
)) return false;
257 NameValueTable::Iterator
iter(a
->m_tab
, fp
.m_pos
);
261 bool GlobalsArray::AdvanceMArrayIter(ArrayData
* ad
, MArrayIter
& fp
) {
262 auto a
= asGlobals(ad
);
263 bool reset
= fp
.getResetFlag();
264 NameValueTable::Iterator iter
= reset
?
265 NameValueTable::Iterator(a
->m_tab
) :
266 NameValueTable::Iterator(a
->m_tab
, fp
.m_pos
);
268 fp
.setResetFlag(false);
275 fp
.m_pos
= iter
.toInteger();
276 if (!iter
.valid()) return false;
277 // To conform to PHP behavior, we need to set the internal
278 // cursor to point to the next element.
280 a
->m_pos
= iter
.toInteger();
284 ArrayData
* GlobalsArray::EscalateForSort(ArrayData
* ad
, SortFunction
/*sf*/) {
285 raise_warning("Sorting the $GLOBALS array is not supported");
288 void GlobalsArray::Ksort(ArrayData
*, int /*sort_flags*/, bool /*ascending*/) {}
289 void GlobalsArray::Sort(ArrayData
*, int /*sort_flags*/, bool /*ascending*/) {}
290 void GlobalsArray::Asort(ArrayData
*, int /*sort_flags*/, bool /*ascending*/) {}
291 bool GlobalsArray::Uksort(ArrayData
*, const Variant
& /*cmp_function*/) {
294 bool GlobalsArray::Usort(ArrayData
*, const Variant
& /*cmp_function*/) {
297 bool GlobalsArray::Uasort(ArrayData
*, const Variant
& /*cmp_function*/) {
301 bool GlobalsArray::IsVectorData(const ArrayData
*) {
305 ArrayData
* GlobalsArray::CopyStatic(const ArrayData
*) {
306 raise_fatal_error("GlobalsArray::copyStatic "
310 void GlobalsArray::Renumber(ArrayData
*) {}
312 void GlobalsArray::OnSetEvalScalar(ArrayData
*) {
316 //////////////////////////////////////////////////////////////////////