void BaseMap::addAllImpl(const Variant& iterable) { if (iterable.isNull()) return; VMRegGuard _; decltype(cap()) oldCap = 0; bool ok = IterateKV( *iterable.asTypedValue(), [&](ArrayData* adata) { auto sz = adata->size(); if (!sz) return true; if (!m_size) { if (adata->isMixed()) { replaceArray(adata); updateIntLikeStrKeys(); return true; } } else { oldCap = cap(); // assume minimal collisions } reserve(m_size + sz); mutateAndBump(); return false; }, [this](const TypedValue* key, const TypedValue* value) { setRaw(tvAsCVarRef(key), tvAsCVarRef(value)); }, [this](ObjectData* coll) { switch (coll->collectionType()) { case CollectionType::Map: case CollectionType::Set: { if (m_size) break; auto hc = static_cast<HashCollection*>(coll); replaceArray(hc->arrayData()); setIntLikeStrKeys(BaseMap::intLikeStrKeys(hc)); return true; } case CollectionType::Pair: mutateAndBump(); break; default: break; } return false; }, [this](const TypedValue* key, const TypedValue* value) { set(tvAsCVarRef(key), tvAsCVarRef(value)); }); if (UNLIKELY(!ok)) { throw_invalid_collection_parameter(); } // ... and shrink back if that was incorrect if (oldCap) shrinkIfCapacityTooHigh(oldCap); }
void BaseSet::addAll(const Variant& t) { if (t.isNull()) { return; } // nothing to do decltype(cap()) oldCap = 0; bool ok = IterateV( *t.asTypedValue(), [&](ArrayData* adata) { auto sz = adata->size(); if (!sz) return true; if (m_size) { oldCap = cap(); // assume minimal collisions } reserve(m_size + sz); mutateAndBump(); return false; }, [this](const TypedValue* value) { addRaw(tvAsCVarRef(value)); }, [this](ObjectData* coll) { if (!m_size && coll->collectionType() == CollectionType::Set) { auto hc = static_cast<HashCollection*>(coll); replaceArray(hc->arrayData()); setIntLikeStrKeys(BaseSet::intLikeStrKeys(hc)); return true; } if (coll->collectionType() == CollectionType::Pair) { mutateAndBump(); } return false; }, [this](const TypedValue* value) { add(tvAsCVarRef(value)); }); if (UNLIKELY(!ok)) { throw_invalid_collection_parameter(); } // ... and shrink back if that was incorrect if (oldCap) shrinkIfCapacityTooHigh(oldCap); }