bool Globals::isHead(ssize_t pos) const { if (staticSize() > 0) return pos == 0; if (pos < -1) { ArrayData *arr = Array::get(); ASSERT(arr); return !arr->empty() && wrapIter(pos) == arr->iter_begin(); } return false; }
ssize_t Globals::iter_advance(ssize_t prev) const { ArrayData *arr = Array::get(); if (prev < -1) { return wrapIter(arr->iter_advance(wrapIter(prev))); } ssize_t next = prev + 1; if (next == staticSize()) { if (arr) return wrapIter(arr->iter_begin()); return ArrayData::invalid_index; } return next; }
ALWAYS_INLINE typename std::enable_if< std::is_base_of<BaseMap, TMap>::value, Object>::type BaseMap::FromArray(const Class*, const Variant& arr) { if (!arr.isArray()) { SystemLib::throwInvalidArgumentExceptionObject( "Parameter arr must be an array"); } auto map = req::make<TMap>(); ArrayData* ad = arr.getArrayData(); map->reserve(ad->size()); for (ssize_t pos = ad->iter_begin(), limit = ad->iter_end(); pos != limit; pos = ad->iter_advance(pos)) { Variant k = ad->getKey(pos); auto* tv = ad->getValueRef(pos).asCell(); if (k.isInteger()) { map->setRaw(k.toInt64(), tv); } else { assert(k.isString()); map->setRaw(k.getStringData(), tv); } } return Object(std::move(map)); }
ALWAYS_INLINE static int64_t extract_impl(VRefParam vref_array, int extract_type /* = EXTR_OVERWRITE */, const String& prefix /* = "" */) { auto arrByRef = false; auto arr_tv = vref_array.wrapped().asTypedValue(); if (arr_tv->m_type == KindOfRef) { arr_tv = arr_tv->m_data.pref->tv(); arrByRef = true; } if (!isArrayType(arr_tv->m_type)) { raise_warning("extract() expects parameter 1 to be array"); return 0; } bool reference = extract_type & EXTR_REFS; extract_type &= ~EXTR_REFS; VMRegAnchor _; auto const varEnv = g_context->getOrCreateVarEnv(); if (!varEnv) return 0; auto& carr = tvAsCVarRef(arr_tv).asCArrRef(); if (UNLIKELY(reference)) { auto extr_refs = [&](Array& arr) { if (arr.size() > 0) { // force arr to escalate (if necessary) by getting an lvalue to the // first element. ArrayData* ad = arr.get(); auto const& first_key = ad->getKey(ad->iter_begin()); arr.lvalAt(first_key); } int count = 0; for (ArrayIter iter(arr); iter; ++iter) { auto name = iter.first().toString(); if (!modify_extract_name(varEnv, name, extract_type, prefix)) continue; // The const_cast is safe because we escalated the array. We can't use // arr.lvalAt(name), because arr may have been modified as a side // effect of an earlier iteration. auto& ref = const_cast<Variant&>(iter.secondRef()); g_context->bindVar(name.get(), ref.asTypedValue()); ++count; } return count; }; if (arrByRef) { return extr_refs(tvAsVariant(vref_array.getRefData()->tv()).asArrRef()); } Array tmp = carr; return extr_refs(tmp); } int count = 0; for (ArrayIter iter(carr); iter; ++iter) { auto name = iter.first().toString(); if (!modify_extract_name(varEnv, name, extract_type, prefix)) continue; g_context->setVar(name.get(), iter.secondRef().asTypedValue()); ++count; } return count; }