ArrayData* ArrayCommon::ToKeyset(ArrayData* a, bool) { auto const size = a->size(); if (!size) return staticEmptyKeysetArray(); KeysetInit init{size}; IterateV( a, [&](const TypedValue* v) { if (UNLIKELY(v->m_type == KindOfRef)) { if (v->m_data.pref->isReferenced()) { throwRefInvalidArrayValueException(init.toArray()); } v = v->m_data.pref->tv(); assertx(v->m_type != KindOfRef); } if (LIKELY(isStringType(v->m_type))) { init.add(v->m_data.pstr); } else if (LIKELY(isIntType(v->m_type))) { init.add(v->m_data.num); } else { throwInvalidArrayKeyException(v, init.toArray().get()); } } ); return init.create(); }
ArrayData* ArrayCommon::ToVec(const ArrayData* a) { auto const size = a->size(); if (!size) return staticEmptyVecArray(); VecArrayInit init{size}; for (ArrayIter it{a}; it; ++it) { auto const& value = it.secondRef(); if (UNLIKELY(value.isReferenced())) { throwRefInvalidArrayValueException(init.toArray()); } init.append(value); } return init.create(); }
ArrayData* ArrayCommon::ToDict(ArrayData* a, bool) { auto const size = a->size(); if (!size) return staticEmptyDictArray(); DictInit init{size}; IterateKV( a, [&](const TypedValue* k, const TypedValue* v) { if (UNLIKELY(v->m_type == KindOfRef)) { if (v->m_data.pref->isReferenced()) { throwRefInvalidArrayValueException(init.toArray()); } } init.setValidKey(tvAsCVarRef(k), tvAsCVarRef(v)); } ); return init.create(); }