ALWAYS_INLINE typename std::enable_if< std::is_base_of<BaseMap, TMap>::value, Object>::type BaseMap::php_zip(const Variant& iterable) const { size_t sz; ArrayIter iter = getArrayIterHelper(iterable, sz); auto map = req::make<TMap>(); if (!m_size) { return Object{std::move(map)}; } map->reserve(std::min(sz, size_t(m_size))); uint32_t used = posLimit(); for (uint32_t i = 0; i < used && iter; ++i) { if (isTombstone(i)) continue; const Elm& e = data()[i]; Variant v = iter.second(); auto pair = req::make<c_Pair>(c_Pair::NoInit{}); pair->initAdd(&e.data); pair->initAdd(v); TypedValue tv; tv.m_data.pobj = pair.detach(); tv.m_type = KindOfObject; if (e.hasIntKey()) { map->setRaw(e.ikey, &tv); } else { assert(e.hasStrKey()); map->setRaw(e.skey, &tv); } ++iter; } return Object{std::move(map)}; }
void BaseMap::setAllImpl(const Variant& iterable) { if (iterable.isNull()) return; size_t sz; ArrayIter iter = getArrayIterHelper(iterable, sz); for (; iter; ++iter) { set(iter.first(), iter.second()); } }
void BaseVector::init(CVarRef t) { size_t sz; ArrayIter iter = getArrayIterHelper(t, sz); if (sz) { reserve(sz); } for (; iter; ++iter) { Variant v = iter.second(); TypedValue* tv = cvarToCell(&v); add(tv); } }
typename std::enable_if< std::is_base_of<BaseSet, TSet>::value, Object>::type BaseSet::php_zip(const Variant& iterable) { size_t sz; ArrayIter iter = getArrayIterHelper(iterable, sz); if (m_size && iter) { // At present, BaseSets only support int values and string values, // so if this BaseSet is non empty and the iterable is non empty // the zip operation will always fail throwBadValueType(); } return Object(req::make<TSet>()); }
void BaseMap::addAllPairs(const Variant& iterable) { if (iterable.isNull()) return; VMRegGuard _; size_t sz; ArrayIter iter = getArrayIterHelper(iterable, sz); auto oldCap = cap(); reserve(m_size + sz); // presume minimum key collisions ... for (; iter; ++iter) { add(iter.second()); } // ... and shrink back if that was incorrect shrinkIfCapacityTooHigh(oldCap); }
void BaseVector::zip(BaseVector* bvec, CVarRef iterable) { size_t itSize; ArrayIter iter = getArrayIterHelper(iterable, itSize); uint sz = m_size; bvec->reserve(std::min(itSize, size_t(sz))); for (uint i = 0; i < sz && iter; ++i, ++iter) { Variant v = iter.second(); if (bvec->m_capacity <= bvec->m_size) { bvec->grow(); } c_Pair* pair = NEWOBJ(c_Pair)(); pair->incRefCount(); pair->initAdd(&m_data[i]); pair->initAdd(cvarToCell(&v)); bvec->m_data[i].m_data.pobj = pair; bvec->m_data[i].m_type = KindOfObject; ++bvec->m_size; } }
typename std::enable_if< std::is_base_of<BaseVector, TVector>::value, Object>::type BaseSet::php_concat(const Variant& iterable) { size_t itSize; ArrayIter iter = getArrayIterHelper(iterable, itSize); auto vec = req::make<TVector>(); uint32_t sz = m_size; vec->reserve((size_t)sz + itSize); assert(vec->canMutateBuffer()); vec->setSize(sz); uint32_t used = posLimit(); for (uint32_t i = 0, j = 0; i < used; ++i) { if (isTombstone(i)) { continue; } cellDup(data()[i].data, vec->data()[j]); ++j; } for (; iter; ++iter) { vec->addRaw(iter.second()); } return Object{std::move(vec)}; }
ALWAYS_INLINE typename std::enable_if< std::is_base_of<BaseMap, TMap>::value, Object>::type BaseMap::FromItems(const Class*, const Variant& iterable) { if (iterable.isNull()) return Object{req::make<TMap>()}; VMRegGuard _; size_t sz; ArrayIter iter = getArrayIterHelper(iterable, sz); auto target = req::make<TMap>(); target->reserve(sz); for (; iter; ++iter) { Variant v = iter.second(); TypedValue* tv = v.asCell(); if (UNLIKELY(tv->m_type != KindOfObject || tv->m_data.pobj->getVMClass() != c_Pair::classof())) { SystemLib::throwInvalidArgumentExceptionObject( "Parameter must be an instance of Iterable<Pair>"); } auto pair = static_cast<c_Pair*>(tv->m_data.pobj); target->setRaw(&pair->elm0, &pair->elm1); } return Object{std::move(target)}; }