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_ARRAY_DATA_DEFS_H_
18 #define incl_HPHP_ARRAY_DATA_DEFS_H_
20 #include "hphp/runtime/base/array-data.h"
22 #include "hphp/runtime/base/member-val.h"
23 #include "hphp/runtime/base/string-data.h"
24 #include "hphp/runtime/base/type-variant.h"
30 ///////////////////////////////////////////////////////////////////////////////
32 extern const StaticString s_InvalidKeysetOperationMsg
;
33 extern const StaticString s_VecUnsetMsg
;
35 ///////////////////////////////////////////////////////////////////////////////
37 inline ArrayData
* ArrayData::Create(const Variant
& value
) {
38 return Create(*value
.asTypedValue());
41 inline ArrayData
* ArrayData::Create(const Variant
& name
, TypedValue value
) {
42 return Create(*name
.asTypedValue(), value
);
45 inline ArrayData
* ArrayData::Create(const Variant
& name
, const Variant
& value
) {
46 return Create(*name
.asTypedValue(), *value
.asTypedValue());
49 inline ArrayData
* ArrayData::CreateWithRef(const Variant
& name
,
51 return CreateWithRef(*name
.asTypedValue(), value
);
54 inline ArrayData
* ArrayData::CreateRef(const Variant
& name
, Variant
& value
) {
55 return CreateRef(*name
.asTypedValue(), value
);
58 ///////////////////////////////////////////////////////////////////////////////
59 // ArrayFunction dispatch.
61 inline ArrayData
* ArrayData::copy() const {
62 return g_array_funcs
.copy
[kind()](this);
65 inline ArrayData
* ArrayData::copyStatic() const {
66 auto ret
= g_array_funcs
.copyStatic
[kind()](this);
67 assert(ret
!= this && ret
->isStatic());
71 inline ArrayData
* ArrayData::toPHPArray(bool copy
) {
72 return g_array_funcs
.toPHPArray
[kind()](this, copy
);
75 inline ArrayData
* ArrayData::toDict(bool copy
) {
76 return g_array_funcs
.toDict
[kind()](this, copy
);
79 inline ArrayData
* ArrayData::toVec(bool copy
) {
80 return g_array_funcs
.toVec
[kind()](this, copy
);
83 inline ArrayData
* ArrayData::toKeyset(bool copy
) {
84 return g_array_funcs
.toKeyset
[kind()](this, copy
);
87 inline ArrayData
* ArrayData::toVArray(bool copy
) {
88 return g_array_funcs
.toVArray
[kind()](this, copy
);
91 inline ArrayData
* ArrayData::toDArray(bool copy
) {
92 return g_array_funcs
.toDArray
[kind()](this, copy
);
95 inline ArrayData
* ArrayData::escalate() const {
96 return g_array_funcs
.escalate
[kind()](this);
99 inline bool ArrayData::isVectorData() const {
100 return g_array_funcs
.isVectorData
[kind()](this);
103 inline void ArrayData::release() noexcept
{
104 assert(hasExactlyOneRef());
105 g_array_funcs
.release
[kind()](this);
106 AARCH64_WALKABLE_FRAME();
109 inline bool ArrayData::exists(int64_t k
) const {
110 return g_array_funcs
.existsInt
[kind()](this, k
);
113 inline bool ArrayData::exists(const StringData
* k
) const {
114 return g_array_funcs
.existsStr
[kind()](this, k
);
117 inline member_lval
ArrayData::lval(int64_t k
, bool copy
) {
118 return g_array_funcs
.lvalInt
[kind()](this, k
, copy
);
121 inline member_lval
ArrayData::lval(StringData
* k
, bool copy
) {
122 return g_array_funcs
.lvalStr
[kind()](this, k
, copy
);
125 inline member_lval
ArrayData::lvalRef(int64_t k
, bool copy
) {
126 return g_array_funcs
.lvalIntRef
[kind()](this, k
, copy
);
129 inline member_lval
ArrayData::lvalRef(StringData
* k
, bool copy
) {
130 return g_array_funcs
.lvalStrRef
[kind()](this, k
, copy
);
133 inline member_lval
ArrayData::lvalNew(bool copy
) {
134 return g_array_funcs
.lvalNew
[kind()](this, copy
);
137 inline member_lval
ArrayData::lvalNewRef(bool copy
) {
138 return g_array_funcs
.lvalNewRef
[kind()](this, copy
);
141 inline member_rval
ArrayData::rval(int64_t k
) const {
142 return member_rval
{ this, g_array_funcs
.nvGetInt
[kind()](this, k
) };
145 inline member_rval
ArrayData::rval(const StringData
* k
) const {
146 return member_rval
{ this, g_array_funcs
.nvGetStr
[kind()](this, k
) };
149 inline member_rval
ArrayData::rvalStrict(int64_t k
) const {
150 return member_rval
{ this, g_array_funcs
.nvTryGetInt
[kind()](this, k
) };
153 inline member_rval
ArrayData::rvalStrict(const StringData
* k
) const {
154 return member_rval
{ this, g_array_funcs
.nvTryGetStr
[kind()](this, k
) };
157 inline member_rval
ArrayData::rvalPos(ssize_t pos
) const {
158 return member_rval
{ this, g_array_funcs
.nvGetPos
[kind()](this, pos
) };
161 inline Cell
ArrayData::nvGetKey(ssize_t pos
) const {
162 return g_array_funcs
.nvGetKey
[kind()](this, pos
);
165 inline ArrayData
* ArrayData::set(int64_t k
, Cell v
, bool copy
) {
166 assertx(cellIsPlausible(v
));
167 return g_array_funcs
.setInt
[kind()](this, k
, v
, copy
);
170 inline ArrayData
* ArrayData::set(StringData
* k
, Cell v
, bool copy
) {
171 assertx(cellIsPlausible(v
));
172 return g_array_funcs
.setStr
[kind()](this, k
, v
, copy
);
175 inline ArrayData
* ArrayData::set(int64_t k
, const Variant
& v
, bool copy
) {
176 return g_array_funcs
.setInt
[kind()](this, k
, *v
.asCell(), copy
);
179 inline ArrayData
* ArrayData::set(StringData
* k
, const Variant
& v
, bool copy
) {
180 return g_array_funcs
.setStr
[kind()](this, k
, *v
.asCell(), copy
);
183 inline ArrayData
* ArrayData::setWithRef(int64_t k
, TypedValue v
, bool copy
) {
184 assertx(tvIsPlausible(v
));
185 return g_array_funcs
.setWithRefInt
[kind()](this, k
, v
, copy
);
188 inline ArrayData
* ArrayData::setWithRef(StringData
* k
,
189 TypedValue v
, bool copy
) {
190 assertx(tvIsPlausible(v
));
191 return g_array_funcs
.setWithRefStr
[kind()](this, k
, v
, copy
);
194 inline ArrayData
* ArrayData::setRef(int64_t k
, member_lval v
, bool copy
) {
195 return g_array_funcs
.setRefInt
[kind()](this, k
, v
, copy
);
198 inline ArrayData
* ArrayData::setRef(StringData
* k
, member_lval v
, bool copy
) {
199 return g_array_funcs
.setRefStr
[kind()](this, k
, v
, copy
);
202 inline ArrayData
* ArrayData::add(int64_t k
, Cell v
, bool copy
) {
203 assertx(cellIsPlausible(v
));
204 return g_array_funcs
.addInt
[kind()](this, k
, v
, copy
);
207 inline ArrayData
* ArrayData::add(StringData
* k
, Cell v
, bool copy
) {
208 assertx(cellIsPlausible(v
));
209 return g_array_funcs
.addStr
[kind()](this, k
, v
, copy
);
212 inline ArrayData
* ArrayData::add(int64_t k
, const Variant
& v
, bool copy
) {
213 return g_array_funcs
.addInt
[kind()](this, k
, *v
.asCell(), copy
);
216 inline ArrayData
* ArrayData::add(StringData
* k
, const Variant
& v
, bool copy
) {
217 return g_array_funcs
.addStr
[kind()](this, k
, *v
.asCell(), copy
);
220 inline ArrayData
* ArrayData::remove(int64_t k
, bool copy
) {
221 return g_array_funcs
.removeInt
[kind()](this, k
, copy
);
224 inline ArrayData
* ArrayData::remove(const StringData
* k
, bool copy
) {
225 return g_array_funcs
.removeStr
[kind()](this, k
, copy
);
228 inline ArrayData
* ArrayData::append(Cell v
, bool copy
) {
229 assertx(v
.m_type
!= KindOfUninit
);
230 return g_array_funcs
.append
[kind()](this, v
, copy
);
233 inline ArrayData
* ArrayData::appendWithRef(TypedValue v
, bool copy
) {
234 return g_array_funcs
.appendWithRef
[kind()](this, v
, copy
);
237 inline ArrayData
* ArrayData::appendWithRef(const Variant
& v
, bool copy
) {
238 return g_array_funcs
.appendWithRef
[kind()](this, *v
.asTypedValue(), copy
);
241 inline ArrayData
* ArrayData::appendRef(member_lval v
, bool copy
) {
242 return g_array_funcs
.appendRef
[kind()](this, v
, copy
);
245 inline ssize_t
ArrayData::iter_begin() const {
246 return g_array_funcs
.iterBegin
[kind()](this);
249 inline ssize_t
ArrayData::iter_last() const {
250 return g_array_funcs
.iterLast
[kind()](this);
253 inline ssize_t
ArrayData::iter_end() const {
254 return g_array_funcs
.iterEnd
[kind()](this);
257 inline ssize_t
ArrayData::iter_advance(ssize_t pos
) const {
258 return g_array_funcs
.iterAdvance
[kind()](this, pos
);
261 inline ssize_t
ArrayData::iter_rewind(ssize_t pos
) const {
262 return g_array_funcs
.iterRewind
[kind()](this, pos
);
265 inline bool ArrayData::validMArrayIter(const MArrayIter
& fp
) const {
266 return g_array_funcs
.validMArrayIter
[kind()](this, fp
);
269 inline bool ArrayData::advanceMArrayIter(MArrayIter
& fp
) {
270 return g_array_funcs
.advanceMArrayIter
[kind()](this, fp
);
273 inline ArrayData
* ArrayData::escalateForSort(SortFunction sf
) {
274 return g_array_funcs
.escalateForSort
[kind()](this, sf
);
277 inline void ArrayData::ksort(int sort_flags
, bool ascending
) {
278 return g_array_funcs
.ksort
[kind()](this, sort_flags
, ascending
);
281 inline void ArrayData::sort(int sort_flags
, bool ascending
) {
282 return g_array_funcs
.sort
[kind()](this, sort_flags
, ascending
);
285 inline void ArrayData::asort(int sort_flags
, bool ascending
) {
286 return g_array_funcs
.asort
[kind()](this, sort_flags
, ascending
);
289 inline bool ArrayData::uksort(const Variant
& compare
) {
290 return g_array_funcs
.uksort
[kind()](this, compare
);
293 inline bool ArrayData::usort(const Variant
& compare
) {
294 return g_array_funcs
.usort
[kind()](this, compare
);
297 inline bool ArrayData::uasort(const Variant
& compare
) {
298 return g_array_funcs
.uasort
[kind()](this, compare
);
301 inline ArrayData
* ArrayData::plusEq(const ArrayData
* elms
) {
302 return g_array_funcs
.plusEq
[kind()](this, elms
);
305 inline ArrayData
* ArrayData::merge(const ArrayData
* elms
) {
306 auto ret
= g_array_funcs
.merge
[kind()](this, elms
);
307 assertx(ret
->isPHPArray());
308 assertx(ret
->isNotDVArray());
312 inline ArrayData
* ArrayData::pop(Variant
& value
) {
313 return g_array_funcs
.pop
[kind()](this, value
);
316 inline ArrayData
* ArrayData::dequeue(Variant
& value
) {
317 return g_array_funcs
.dequeue
[kind()](this, value
);
320 inline ArrayData
* ArrayData::prepend(Cell v
, bool copy
) {
321 assertx(v
.m_type
!= KindOfUninit
);
322 return g_array_funcs
.prepend
[kind()](this, v
, copy
);
325 inline void ArrayData::onSetEvalScalar() {
326 return g_array_funcs
.onSetEvalScalar
[kind()](this);
329 inline void ArrayData::renumber() {
330 return g_array_funcs
.renumber
[kind()](this);
333 ///////////////////////////////////////////////////////////////////////////////
337 inline bool isIntKey(Cell cell
) {
338 assert(isIntType(cell
.m_type
) || isStringType(cell
.m_type
));
339 return isIntType(cell
.m_type
);
342 inline int64_t getIntKey(Cell cell
) {
343 assert(isIntType(cell
.m_type
));
344 return cell
.m_data
.num
;
347 inline StringData
* getStringKey(Cell cell
) {
348 assert(isStringType(cell
.m_type
));
349 return cell
.m_data
.pstr
;
354 ///////////////////////////////////////////////////////////////////////////////
355 // Element manipulation.
357 inline bool ArrayData::exists(Cell k
) const {
358 assert(IsValidKey(k
));
359 return detail::isIntKey(k
) ? exists(detail::getIntKey(k
))
360 : exists(detail::getStringKey(k
));
363 inline member_lval
ArrayData::lval(Cell k
, bool copy
) {
364 assert(IsValidKey(k
));
365 return detail::isIntKey(k
) ? lval(detail::getIntKey(k
), copy
)
366 : lval(detail::getStringKey(k
), copy
);
369 inline member_lval
ArrayData::lvalRef(Cell k
, bool copy
) {
370 assert(IsValidKey(k
));
371 return detail::isIntKey(k
) ? lvalRef(detail::getIntKey(k
), copy
)
372 : lvalRef(detail::getStringKey(k
), copy
);
375 inline member_rval
ArrayData::get(int64_t k
, bool error
) const {
376 auto r
= error
? rvalStrict(k
) : rval(k
);
377 return r
? r
: getNotFound(k
, error
);
380 inline member_rval
ArrayData::get(const StringData
* k
, bool error
) const {
381 auto r
= error
? rvalStrict(k
) : rval(k
);
382 return r
? r
: getNotFound(k
, error
);
385 inline member_rval
ArrayData::get(Cell k
, bool error
) const {
386 assert(IsValidKey(k
));
387 return detail::isIntKey(k
) ? get(detail::getIntKey(k
), error
)
388 : get(detail::getStringKey(k
), error
);
391 inline TypedValue
ArrayData::at(int64_t k
) const {
395 inline TypedValue
ArrayData::at(const StringData
* k
) const {
399 inline TypedValue
ArrayData::atPos(ssize_t pos
) const {
400 return rvalPos(pos
).tv();
403 inline ArrayData
* ArrayData::set(Cell k
, Cell v
, bool copy
) {
404 assertx(cellIsPlausible(k
));
405 assertx(cellIsPlausible(v
));
406 assertx(IsValidKey(k
));
408 return detail::isIntKey(k
) ? set(detail::getIntKey(k
), v
, copy
)
409 : set(detail::getStringKey(k
), v
, copy
);
412 inline ArrayData
* ArrayData::setWithRef(Cell k
, TypedValue v
, bool copy
) {
413 assertx(cellIsPlausible(k
));
414 assertx(tvIsPlausible(v
));
415 assertx(IsValidKey(k
));
417 return detail::isIntKey(k
) ? setWithRef(detail::getIntKey(k
), v
, copy
)
418 : setWithRef(detail::getStringKey(k
), v
, copy
);
421 inline ArrayData
* ArrayData::setRef(Cell k
, member_lval v
, bool copy
) {
422 assert(IsValidKey(k
));
423 return detail::isIntKey(k
) ? setRef(detail::getIntKey(k
), v
, copy
)
424 : setRef(detail::getStringKey(k
), v
, copy
);
427 inline ArrayData
* ArrayData::setRef(int64_t k
, Variant
& v
, bool copy
) {
428 return setRef(k
, member_lval::raw(v
.asTypedValue()), copy
);
431 inline ArrayData
* ArrayData::setRef(StringData
* k
, Variant
& v
, bool copy
) {
432 return setRef(k
, member_lval::raw(v
.asTypedValue()), copy
);
435 inline ArrayData
* ArrayData::setRef(Cell k
, Variant
& v
, bool copy
) {
436 return setRef(k
, member_lval::raw(v
.asTypedValue()), copy
);
439 inline ArrayData
* ArrayData::add(Cell k
, Cell v
, bool copy
) {
440 assertx(cellIsPlausible(k
));
441 assertx(cellIsPlausible(v
));
442 assertx(IsValidKey(k
));
444 return detail::isIntKey(k
) ? add(detail::getIntKey(k
), v
, copy
)
445 : add(detail::getStringKey(k
), v
, copy
);
448 inline ArrayData
* ArrayData::remove(Cell k
, bool copy
) {
449 assert(IsValidKey(k
));
450 return detail::isIntKey(k
) ? remove(detail::getIntKey(k
), copy
)
451 : remove(detail::getStringKey(k
), copy
);
454 ///////////////////////////////////////////////////////////////////////////////
456 inline bool ArrayData::exists(const String
& k
) const {
457 assert(IsValidKey(k
));
458 return exists(k
.get());
461 inline bool ArrayData::exists(const Variant
& k
) const {
462 return exists(*k
.asCell());
465 inline member_lval
ArrayData::lval(const String
& k
, bool copy
) {
466 assert(IsValidKey(k
));
467 return lval(k
.get(), copy
);
470 inline member_lval
ArrayData::lval(const Variant
& k
, bool copy
) {
471 return lval(*k
.asCell(), copy
);
474 inline member_lval
ArrayData::lvalRef(const String
& k
, bool copy
) {
475 assert(IsValidKey(k
));
476 return lvalRef(k
.get(), copy
);
479 inline member_lval
ArrayData::lvalRef(const Variant
& k
, bool copy
) {
480 return lvalRef(*k
.asCell(), copy
);
483 inline member_rval
ArrayData::get(const String
& k
, bool error
) const {
484 assert(IsValidKey(k
));
485 return get(k
.get(), error
);
488 inline member_rval
ArrayData::get(const Variant
& k
, bool error
) const {
489 return get(*k
.asCell(), error
);
492 inline ArrayData
* ArrayData::set(const String
& k
, Cell v
, bool copy
) {
493 assertx(cellIsPlausible(v
));
494 assertx(IsValidKey(k
));
495 return set(k
.get(), v
, copy
);
498 inline ArrayData
* ArrayData::set(const String
& k
, const Variant
& v
,
500 return set(k
, *v
.asCell(), copy
);
503 inline ArrayData
* ArrayData::set(const Variant
& k
, const Variant
& v
,
505 return set(*k
.asCell(), *v
.asCell(), copy
);
508 inline ArrayData
* ArrayData::setWithRef(const String
& k
,
509 TypedValue v
, bool copy
) {
510 assertx(tvIsPlausible(v
));
511 assertx(IsValidKey(k
));
512 return setWithRef(k
.get(), v
, copy
);
516 ArrayData::setRef(const String
& k
, member_lval v
, bool copy
) {
517 assert(IsValidKey(k
));
518 return setRef(k
.get(), v
, copy
);
522 ArrayData::setRef(const Variant
& k
, member_lval v
, bool copy
) {
523 return setRef(*k
.asCell(), v
, copy
);
526 inline ArrayData
* ArrayData::setRef(const String
& k
, Variant
& v
, bool copy
) {
527 return setRef(k
, member_lval::raw(v
.asTypedValue()), copy
);
530 inline ArrayData
* ArrayData::setRef(const Variant
& k
, Variant
& v
, bool copy
) {
531 return setRef(k
, member_lval::raw(v
.asTypedValue()), copy
);
534 inline ArrayData
* ArrayData::add(const String
& k
, Cell v
, bool copy
) {
535 assertx(cellIsPlausible(v
));
536 assert(IsValidKey(k
));
537 return add(k
.get(), v
, copy
);
540 inline ArrayData
* ArrayData::add(const String
& k
, const Variant
& v
,
542 return add(k
, *v
.asCell(), copy
);
545 inline ArrayData
* ArrayData::add(const Variant
& k
, const Variant
& v
,
547 return add(*k
.asCell(), *v
.asCell(), copy
);
550 inline ArrayData
* ArrayData::remove(const String
& k
, bool copy
) {
551 assert(IsValidKey(k
));
552 return remove(k
.get(), copy
);
555 inline ArrayData
* ArrayData::remove(const Variant
& k
, bool copy
) {
556 return remove(*k
.asCell(), copy
);
559 inline ArrayData
* ArrayData::appendRef(Variant
& v
, bool copy
) {
560 return appendRef(member_lval::raw(v
.asTypedValue()), copy
);
563 inline Variant
ArrayData::getValue(ssize_t pos
) const {
564 return tvAsCVarRef(rvalPos(pos
).tv_ptr());
567 inline Variant
ArrayData::getKey(ssize_t pos
) const {
568 auto key
= nvGetKey(pos
);
569 return std::move(cellAsVariant(key
));
572 ///////////////////////////////////////////////////////////////////////////////
574 ALWAYS_INLINE
bool ArrayData::convertKey(const StringData
* key
,
577 auto const result
= key
->isStrictlyInteger(i
) && useWeakKeys();
578 if (UNLIKELY(result
&& notice
)) raise_intish_index_cast();
582 ///////////////////////////////////////////////////////////////////////////////