Array HashCollection::toValuesArray() { PackedArrayInit ai(m_size); auto* eLimit = elmLimit(); for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) { ai.append(tvAsCVarRef(&e->data)); } return ai.toArray(); }
Variant BaseMap::firstKey() { if (!m_size) return null_variant; auto* e = firstElm(); assert(e != elmLimit()); if (e->hasIntKey()) { return e->ikey; } else { assert(e->hasStrKey()); return Variant{e->skey}; } }
Array HashCollection::toKeysArray() { PackedArrayInit ai(m_size); auto* eLimit = elmLimit(); for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) { if (e->hasIntKey()) { ai.append(int64_t{e->ikey}); } else { assert(e->hasStrKey()); ai.append(VarNR(e->skey).tv()); } } return ai.toArray(); }
bool BaseSet::Equals(const ObjectData* obj1, const ObjectData* obj2) { auto st1 = static_cast<const BaseSet*>(obj1); auto st2 = static_cast<const BaseSet*>(obj2); if (st1->m_size != st2->m_size) return false; auto eLimit = st1->elmLimit(); for (auto e = st1->firstElm(); e != eLimit; e = nextElm(e, eLimit)) { if (e->hasIntKey()) { if (!st2->contains(e->data.m_data.num)) return false; } else { assert(e->hasStrKey()); if (!st2->contains(e->data.m_data.pstr)) return false; } } return true; }
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; }
ALWAYS_INLINE typename std::enable_if< std::is_base_of<BaseMap, TMap>::value, Object>::type BaseMap::php_skipWhile(const Variant& fn) { CallCtx ctx; vm_decode_function(fn, nullptr, false, ctx); if (!ctx.func) { SystemLib::throwInvalidArgumentExceptionObject( "Parameter must be a valid callback"); } auto map = req::make<TMap>(); if (!m_size) return Object{std::move(map)}; int32_t version; if (std::is_same<c_Map, TMap>::value) { version = m_version; } ssize_t pos; for (pos = iter_begin(); iter_valid(pos); pos = iter_next(pos)) { auto* e = iter_elm(pos); bool b = invokeAndCastToBool(ctx, 1, &e->data); if (std::is_same<c_Map, TMap>::value) { if (UNLIKELY(version != m_version)) { throw_collection_modified(); } } if (!b) break; } if (iter_valid(pos)) { auto* eLimit = elmLimit(); auto* e = iter_elm(pos); for (; e != eLimit; e = nextElm(e, eLimit)) { if (e->hasIntKey()) { map->set(e->ikey, &e->data); } else { assert(e->hasStrKey()); map->set(e->skey, &e->data); } } } return Object{std::move(map)}; }
NEVER_INLINE void HashCollection::warnOnStrIntDup() const { req::hash_set<int64_t> seenVals; auto* eLimit = elmLimit(); for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) { int64_t newVal = 0; if (e->hasIntKey()) { newVal = e->ikey; } else { assert(e->hasStrKey()); // isStriclyInteger() puts the int value in newVal as a side effect. if (!e->skey->isStrictlyInteger(newVal)) continue; } if (seenVals.find(newVal) != seenVals.end()) { auto cls = getVMClass()->name()->toCppString(); auto pos = cls.rfind('\\'); if (pos != std::string::npos) { cls = cls.substr(pos + 1); } raise_warning( "%s::toArray() for a %s containing both int(%" PRId64 ") " "and string('%" PRId64 "')", cls.c_str(), toLower(cls).c_str(), newVal, newVal ); return; } seenVals.insert(newVal); } // Do nothing if no 'duplicates' were found. }
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"); } }
ALWAYS_INLINE typename std::enable_if< std::is_base_of<BaseMap, TMap>::value, Object>::type BaseMap::php_differenceByKey(const Variant& it) { if (!it.isObject()) { SystemLib::throwInvalidArgumentExceptionObject( "Parameter it must be an instance of Iterable"); } ObjectData* obj = it.getObjectData(); TMap* target = BaseMap::Clone<TMap>(this); auto ret = Object::attach(target); if (obj->isCollection()) { if (isMapCollection(obj->collectionType())) { auto map = static_cast<BaseMap*>(obj); auto* eLimit = map->elmLimit(); for (auto* e = map->firstElm(); e != eLimit; e = nextElm(e, eLimit)) { if (e->hasIntKey()) { target->remove((int64_t)e->ikey); } else { assert(e->hasStrKey()); target->remove(e->skey); } } return ret; } } for (ArrayIter iter(obj); iter; ++iter) { Variant k = iter.first(); if (k.isInteger()) { target->remove(k.toInt64()); } else { assert(k.isString()); target->remove(k.getStringData()); } } return ret; }
Variant BaseSet::firstValue() { if (!m_size) return init_null(); auto e = firstElm(); assert(e != elmLimit()); return tvAsCVarRef(&e->data); }
Variant BaseMap::firstValue() { if (!m_size) return null_variant; auto* e = firstElm(); assert(e != elmLimit()); return tvAsCVarRef(&e->data); }