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(); }
ArrayData* EmptyArray::ToDict(ArrayData*, bool) { return staticEmptyDictArray(); }
void tvCastToDictInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); ArrayData* a; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: raise_warning("Null to dict conversion"); a = staticEmptyDictArray(); continue; case KindOfBoolean: raise_warning("Bool to dict conversion"); a = staticEmptyDictArray(); continue; case KindOfInt64: raise_warning("Int to dict conversion"); a = staticEmptyDictArray(); continue; case KindOfDouble: raise_warning("Double to dict conversion"); a = staticEmptyDictArray(); continue; case KindOfPersistentString: case KindOfString: raise_warning("String to dict conversion"); a = staticEmptyDictArray(); decRefStr(tv->m_data.pstr); continue; case KindOfResource: raise_warning("Resource to dict conversion"); a = staticEmptyDictArray(); decRefRes(tv->m_data.pres); continue; case KindOfPersistentVec: case KindOfVec: { auto* adIn = tv->m_data.parr; assert(adIn->isVecArray()); a = PackedArray::ToDictVec(adIn, adIn->cowCheck()); assert(a != adIn); decRefArr(adIn); continue; } case KindOfPersistentKeyset: case KindOfKeyset: { auto* adIn = tv->m_data.parr; assert(adIn->isKeyset()); a = MixedArray::ToDictKeyset(adIn, adIn->cowCheck()); if (a != adIn) decRefArr(adIn); continue; } case KindOfPersistentArray: case KindOfArray: { auto* adIn = tv->m_data.parr; assert(adIn->isPHPArray()); a = adIn->toDict(adIn->cowCheck()); if (a != adIn) decRefArr(adIn); continue; } case KindOfPersistentDict: case KindOfDict: assert(tv->m_data.parr->isDict()); return; case KindOfObject: { auto* obj = tv->m_data.pobj; if (!obj->isCollection()) { raise_warning("Non-collection object conversion to dict"); a = staticEmptyDictArray(); } else { auto dict = collections::toArray(obj).toDict(); decRefObj(obj); a = dict.detach(); } continue; } case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); assert(!a->isRefCounted() || a->hasExactlyOneRef()); tv->m_data.parr = a; tv->m_type = KindOfDict; assert(cellIsPlausible(*tv)); }