void HashCollection::remove(StringData* key) { mutateAndBump(); auto p = findForRemove(key, key->hash()); if (validPos(p)) { erase(p); } }
void HashCollection::remove(int64_t key) { mutateAndBump(); auto p = findForRemove(key, hash_int64(key)); if (validPos(p)) { erase(p); } }
Object BaseMap::php_retain(const Variant& callback) { CallCtx ctx; vm_decode_function(callback, nullptr, false, ctx); if (!ctx.func) { SystemLib::throwInvalidArgumentExceptionObject( "Parameter must be a valid callback"); } auto size = m_size; if (!size) { return Object{this}; } constexpr int64_t argc = useKey ? 2 : 1; TypedValue argv[argc]; for (ssize_t pos = iter_begin(); iter_valid(pos); pos = iter_next(pos)) { auto* e = iter_elm(pos); if (useKey) { if (e->hasIntKey()) { argv[0].m_type = KindOfInt64; argv[0].m_data.num = e->ikey; } else { argv[0].m_type = KindOfString; argv[0].m_data.pstr = e->skey; } } argv[argc-1] = e->data; int32_t version = m_version; bool b = invokeAndCastToBool(ctx, argc, argv); if (UNLIKELY(version != m_version)) { throw_collection_modified(); } if (b) { continue; } mutateAndBump(); version = m_version; e = iter_elm(pos); ssize_t pp = (e->hasIntKey() ? findForRemove(e->ikey) : findForRemove(e->skey, e->skey->hash())); eraseNoCompact(pp); if (UNLIKELY(version != m_version)) { throw_collection_modified(); } } assert(m_size <= size); compactOrShrinkIfDensityTooLow(); return Object{this}; }
Variant BaseSet::popFront() { if (UNLIKELY(m_size == 0)) { SystemLib::throwInvalidOperationExceptionObject("Cannot pop empty Set"); } mutateAndBump(); auto e = data(); for (;; ++e) { assert(e != elmLimit()); if (!isTombstone(e)) break; } Variant ret = tvAsCVarRef(&e->data); auto h = e->hash(); auto ei = e->hasIntKey() ? findForRemove(e->ikey, h) : findForRemove(e->skey, h); erase(ei); return ret; }
ArrayData* StructArray::RemoveStr( ArrayData* ad, const StringData* k, bool copy ) { auto structArray = asStructArray(ad); if (structArray->shape()->hasOffsetFor(k)) { auto const mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray); auto pos = mixed->findForRemove(k, k->hash()); if (validPos(pos)) mixed->erase(pos); return mixed; } return copy ? Copy(structArray) : structArray; }
Variant BaseMap::popFront() { if (m_size) { mutateAndBump(); auto* e = data(); for (;; ++e) { assert(e != elmLimit()); if (!isTombstone(e)) break; } Variant ret = tvAsCVarRef(&e->data); ssize_t ei; if (e->hasIntKey()) { ei = findForRemove(e->ikey); } else { assert(e->hasStrKey()); ei = findForRemove(e->skey, e->skey->hash()); } erase(ei); return ret; } else { SystemLib::throwInvalidOperationExceptionObject( "Cannot pop empty Map"); } }
ArrayData* PackedArray::RemoveInt(ArrayData* adIn, int64_t k, bool copy) { assert(checkInvariants(adIn)); if (size_t(k) < adIn->m_size) { // Escalate to mixed for correctness; unset preserves m_nextKI. // // TODO(#2606310): if we're removing the /last/ element, we // probably could stay packed, but this needs to be verified. auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn); auto pos = mixed->findForRemove(k, false); if (validPos(pos)) mixed->erase(pos); return mixed; } // Key doesn't exist---we're still packed. return copy ? Copy(adIn) : adIn; }