static void walk_func(VRefParam value, CVarRef key, CVarRef userdata, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant sink; TypedValue args[3] = { *value->asRef(), *key.asCell(), *userdata.asCell() }; g_vmContext->invokeFuncFew(sink.asTypedValue(), *ctx, 3, args); }
static Variant reduce_func(CVarRef result, CVarRef operand, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant ret; TypedValue args[2] = { *result.asCell(), *operand.asCell() }; g_vmContext->invokeFuncFew(ret.asTypedValue(), *ctx, 2, args); return ret; }
bool UnaryOpExpression::preCompute(CVarRef value, Variant &result) { bool ret = true; try { g_context->setThrowAllErrors(true); switch(m_op) { case '!': result = (!toBoolean(value)); break; case '+': cellSet(cellAdd(make_tv<KindOfInt64>(0), *value.asCell()), *result.asCell()); break; case '-': cellSet(cellSub(make_tv<KindOfInt64>(0), *value.asCell()), *result.asCell()); break; case '~': tvSet(*value.asCell(), *result.asTypedValue()); cellBitNot(*result.asCell()); break; case '@': result = value; break; case T_INT_CAST: result = value.toInt64(); break; case T_DOUBLE_CAST: result = toDouble(value); break; case T_STRING_CAST: result = toString(value); break; case T_BOOL_CAST: result = toBoolean(value); break; case T_EMPTY: result = !toBoolean(value); break; case T_ISSET: result = is_not_null(value); break; case T_INC: case T_DEC: assert(false); default: ret = false; break; } } catch (...) { ret = false; } g_context->setThrowAllErrors(false); return ret; }
bool f_define(const String& name, CVarRef value, bool case_insensitive /* = false */) { if (case_insensitive) { raise_warning(Strings::CONSTANTS_CASE_SENSITIVE); } return Unit::defCns(name.get(), value.asCell()); }
bool same(CVarRef v1, int64_t v2) { auto const cell = v1.asCell(); switch (cell->m_type) { case KindOfInt64: return v2 == cell->m_data.num; default: break; } return false; }
Variant f_array_combine(CVarRef keys, CVarRef values) { const auto& cell_keys = *keys.asCell(); const auto& cell_values = *values.asCell(); if (UNLIKELY(!isContainer(cell_keys) || !isContainer(cell_values))) { raise_warning("Invalid operand type was used: array_combine expects " "arrays or collections"); return uninit_null(); } if (UNLIKELY(getContainerSize(cell_keys) != getContainerSize(cell_values))) { raise_warning("array_combine(): Both parameters should have an equal " "number of elements"); return false; } Array ret = ArrayData::Create(); for (ArrayIter iter1(cell_keys), iter2(cell_values); iter1; ++iter1, ++iter2) { ret.lvalAt(iter1.secondRefPlus()).setWithRef(iter2.secondRefPlus()); } return ret; }
HOT_FUNC bool f_array_key_exists(CVarRef key, CVarRef search) { const ArrayData *ad; auto const searchCell = search.asCell(); if (LIKELY(searchCell->m_type == KindOfArray)) { ad = searchCell->m_data.parr; } else if (searchCell->m_type == KindOfObject) { ObjectData* obj = searchCell->m_data.pobj; if (obj->isCollection()) { return collectionOffsetContains(obj, key); } return f_array_key_exists(key, toArray(search)); } else { throw_bad_type_exception("array_key_exists expects an array or an object; " "false returned."); return false; } auto const cell = key.asCell(); switch (cell->m_type) { case KindOfString: case KindOfStaticString: { int64_t n = 0; StringData *sd = cell->m_data.pstr; if (sd->isStrictlyInteger(n)) { return ad->exists(n); } return ad->exists(StrNR(sd)); } case KindOfInt64: return ad->exists(cell->m_data.num); case KindOfUninit: case KindOfNull: return ad->exists(empty_string); default: break; } raise_warning("Array key should be either a string or an integer"); return false; }
void objOffsetUnset(ObjectData* base, CVarRef offset) { objArrayAccess(base); static StringData* sd__offsetUnset = makeStaticString("offsetUnset"); assert(!base->isCollection()); const Func* method = base->methodNamed(sd__offsetUnset); assert(method != nullptr); TypedValue tv; tvWriteUninit(&tv); g_vmContext->invokeFuncFew(&tv, method, base, nullptr, 1, offset.asCell()); tvRefcountedDecRef(&tv); }
Variant f_array_values(CVarRef input) { const auto& cell_input = *input.asCell(); if (!isContainer(cell_input)) { raise_warning("array_values() expects parameter 1 to be an array " "or collection"); return uninit_null(); } PackedArrayInit ai(getContainerSize(cell_input)); for (ArrayIter iter(cell_input); iter; ++iter) { ai.appendWithRef(iter.secondRefPlus()); } return ai.toArray(); }
static bool objOffsetExists(ObjectData* base, CVarRef offset) { objArrayAccess(base); TypedValue tvResult; tvWriteUninit(&tvResult); static StringData* sd__offsetExists = makeStaticString("offsetExists"); assert(!base->isCollection()); const Func* method = base->methodNamed(sd__offsetExists); assert(method != nullptr); g_vmContext->invokeFuncFew(&tvResult, method, base, nullptr, 1, offset.asCell()); tvCastToBooleanInPlace(&tvResult); return bool(tvResult.m_data.num); }
void StringBuffer::append(CVarRef v) { auto const cell = v.asCell(); switch (cell->m_type) { case KindOfStaticString: case KindOfString: append(cell->m_data.pstr); break; case KindOfInt64: append(cell->m_data.num); break; default: append(v.toString()); } }
void objOffsetSet(ObjectData* base, CVarRef offset, TypedValue* val, bool validate /* = true */) { if (validate) { objArrayAccess(base); } static StringData* sd__offsetSet = makeStaticString("offsetSet"); assert(!base->isCollection()); const Func* method = base->methodNamed(sd__offsetSet); assert(method != nullptr); TypedValue tvResult; tvWriteUninit(&tvResult); TypedValue args[2] = { *offset.asCell(), *tvToCell(val) }; g_vmContext->invokeFuncFew(&tvResult, method, base, nullptr, 2, args); tvRefcountedDecRef(&tvResult); }
Variant f_array_keys(CVarRef input, CVarRef search_value /* = null_variant */, bool strict /* = false */) { const auto& cell_input = *input.asCell(); if (UNLIKELY(!isContainer(cell_input))) { goto warn; } { // We treat Sets differently. For Sets, we pretend the values are // also the keys (similar to how Set::toArray() behaves). bool isSetType = cell_input.m_type == KindOfObject && cell_input.m_data.pobj->getCollectionType() == Collection::SetType; if (UNLIKELY(isSetType)) { return arrayKeysSetHelper(cell_input, search_value, strict); } ArrayIter iter(cell_input); if (LIKELY(!search_value.isInitialized())) { PackedArrayInit ai(getContainerSize(cell_input)); for (; iter; ++iter) { ai.append(iter.first()); } return ai.toArray(); } Array ai = Array::attach(HphpArray::MakeReserve(0)); for (; iter; ++iter) { if ((strict && HPHP::same(iter.secondRefPlus(), search_value)) || (!strict && HPHP::equal(iter.secondRefPlus(), search_value))) { ai.append(iter.first()); } } return ai; } warn: raise_warning("array_keys() expects parameter 1 to be an array " "or collection"); return uninit_null(); }
bool f_is_callable(CVarRef v, bool syntax /* = false */, VRefParam name /* = null */) { bool ret = true; if (LIKELY(!syntax)) { CallerFrame cf; ObjectData* obj = NULL; HPHP::Class* cls = NULL; StringData* invName = NULL; const HPHP::Func* f = vm_decode_function(v, cf(), false, obj, cls, invName, false); if (f == NULL) { ret = false; } if (invName != NULL) { decRefStr(invName); } if (!name.isReferenced()) return ret; } auto const tv_func = v.asCell(); if (IS_STRING_TYPE(tv_func->m_type)) { if (name.isReferenced()) name = tv_func->m_data.pstr; return ret; } if (tv_func->m_type == KindOfArray) { CArrRef arr = tv_func->m_data.parr; CVarRef clsname = arr.rvalAtRef(int64_t(0)); CVarRef mthname = arr.rvalAtRef(int64_t(1)); if (arr.size() != 2 || &clsname == &null_variant || &mthname == &null_variant) { name = v.toString(); return false; } auto const tv_meth = mthname.asCell(); if (!IS_STRING_TYPE(tv_meth->m_type)) { if (name.isReferenced()) name = v.toString(); return false; } auto const tv_cls = clsname.asCell(); if (tv_cls->m_type == KindOfObject) { name = tv_cls->m_data.pobj->o_getClassName(); } else if (IS_STRING_TYPE(tv_cls->m_type)) { name = tv_cls->m_data.pstr; } else { name = v.toString(); return false; } name = concat3(name, s_colon2, tv_meth->m_data.pstr); return ret; } if (tv_func->m_type == KindOfObject) { ObjectData *d = tv_func->m_data.pobj; const Func* invoke = d->getVMClass()->lookupMethod(s__invoke.get()); if (name.isReferenced()) { if (d->instanceof(c_Closure::classof())) { // Hack to stop the mangled name from showing up name = s_Closure__invoke; } else { name = d->o_getClassName() + "::__invoke"; } } return invoke != NULL; } return false; }
static bool filter_func(CVarRef value, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant ret; g_vmContext->invokeFuncFew((TypedValue*)&ret, *ctx, 1, value.asCell() ); return ret.toBoolean(); }
CVarRef ArrayData::get(CVarRef k, bool error) const { assert(IsValidKey(k)); auto const cell = k.asCell(); return isIntKey(cell) ? get(getIntKey(cell), error) : get(getStringKey(cell), error); }
Object c_StaticResultWaitHandle::ti_create(CVarRef result) { return Create(*result.asCell()); }