ArrayData *ZendArray::addLval(int64 k, Variant *&ret, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->addLvalImpl(k, &ret, false); return result; } addLvalImpl(k, &ret, false); return NULL; }
ArrayData *ZendArray::addLval(CStrRef k, Variant *&ret, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->addLvalImpl(k.get(), k->hash(), &ret, false); return result; } addLvalImpl(k.get(), k->hash(), &ret, false); return NULL; }
ArrayData* StructArray::LvalInt( ArrayData* ad, int64_t k, Variant*& ret, bool copy ) { auto structArray = asStructArray(ad); auto mixedArray = copy ? ToMixedCopy(structArray) : ToMixed(structArray); return mixedArray->addLvalImpl(k, ret); }
ArrayData* StructArray::LvalStr( ArrayData* ad, StringData* property, Variant*& ret, bool copy ) { auto structArray = asStructArray(ad); auto shape = structArray->shape(); auto offset = shape->offsetFor(property); if (offset != PropertyTable::kInvalidOffset) { auto const result = asStructArray( copy ? Copy(structArray) : structArray); ret = &tvAsVariant(&result->data()[offset]); return result; } auto convertToMixedAndAdd = [&]() { auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray); return mixed->addLvalImpl(property, ret); }; // We don't support adding non-static strings yet. StringData* staticKey; if (property->isStatic()) { staticKey = property; } else { staticKey = lookupStaticString(property); if (!staticKey) return convertToMixedAndAdd(); } auto newShape = shape->transition(staticKey); if (!newShape) return convertToMixedAndAdd(); auto result = copy ? CopyAndResizeIfNeeded(structArray, newShape) : ResizeIfNeeded(structArray, newShape); assert(newShape->hasOffsetFor(staticKey)); offset = newShape->offsetFor(staticKey); tvWriteNull(&result->data()[offset]); ret = &tvAsVariant(&result->data()[offset]); return result; }
ArrayData *ZendArray::lval(int64 k, Variant *&ret, bool copy, bool checkExist /* = false */) { if (!copy) { addLvalImpl(k, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret); return a; } Bucket *p = find(k); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret, p); return a; }
ArrayData* PackedArray::LvalInt(ArrayData* adIn, int64_t k, Variant*& ret, bool copy) { assert(checkInvariants(adIn)); if (LIKELY(size_t(k) < adIn->m_size)) { auto const ad = copy ? Copy(adIn) : adIn; ret = &tvAsVariant(&packedData(ad)[k]); return ad; } // We can stay packed if the index is m_size, and the operation does // the same thing as LvalNew. if (size_t(k) == adIn->m_size) return LvalNew(adIn, ret, copy); // Promote-to-mixed path, we know the key is new and should be using // findForNewInsert but aren't yet TODO(#2606310). auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn); return mixed->addLvalImpl(k, ret); }
ArrayData *ZendArray::lval(CStrRef k, Variant *&ret, bool copy, bool checkExist /* = false */) { StringData *key = k.get(); int64 prehash = key->hash(); if (!copy) { addLvalImpl(key, prehash, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret); return a; } Bucket *p = find(key->data(), key->size(), prehash); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret, p); return a; }
Variant &Array::addLval(CStrRef key, bool isKey /* = false */) { if (isKey) return addLvalImpl(key); return addLvalImpl(key.toKey()); }
Variant &Array::addLval(litstr key, bool isKey /* = false */) { if (isKey) return addLvalImpl(String(key)); return addLvalImpl(String(key).toKey()); }