void tvCastToStringInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); auto string = [&](StringData* s) { tv->m_type = KindOfString; tv->m_data.pstr = s; }; auto persistentString = [&](StringData* s) { assert(!s->isRefCounted()); tv->m_type = KindOfPersistentString; tv->m_data.pstr = s; }; switch (tv->m_type) { case KindOfUninit: case KindOfNull: return persistentString(staticEmptyString()); case KindOfBoolean: return persistentString(tv->m_data.num ? s_1.get() : staticEmptyString()); case KindOfInt64: return string(buildStringData(tv->m_data.num)); case KindOfDouble: return string(buildStringData(tv->m_data.dbl)); case KindOfPersistentString: case KindOfString: return; case KindOfArray: case KindOfPersistentArray: raise_notice("Array to string conversion"); if (tv->m_type == KindOfArray) tvDecRefArr(tv); return persistentString(array_string.get()); case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->invokeToString(); return; case KindOfResource: // For resources, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pres->data()->o_toString(); return; case KindOfRef: case KindOfClass: break; } not_reached(); }
StringData* convCellToStrHelper(TypedValue tv) { switch (tv.m_type) { case KindOfUninit: case KindOfNull: return buildStringData(""); case KindOfBoolean: return buildStringData(tv.m_data.num ? "1" : ""); case KindOfInt64: return convIntToStrHelper(tv.m_data.num); case KindOfDouble: return convDblToStrHelper(tv.m_data.num); case KindOfStaticString: case KindOfString: return tv.m_data.pstr; case KindOfArray: tvDecRefArr(&tv); return buildStringData("Array"); case KindOfObject: return convObjToStrHelper(tv.m_data.pobj); default: not_reached(); } }
StringData* convCellToStrHelper(TypedValue tv) { switch (tv.m_type) { case KindOfUninit: case KindOfNull: return s_empty.get(); case KindOfBoolean: return tv.m_data.num ? s_1.get() : s_empty.get(); case KindOfInt64: return convIntToStrHelper(tv.m_data.num); case KindOfDouble: return convDblToStrHelper(tv.m_data.num); case KindOfStaticString: case KindOfString: // No incref, since there is also a logical decref of // our argument. return tv.m_data.pstr; case KindOfArray: tvDecRefArr(&tv); return s_Array.get(); case KindOfObject: return convObjToStrHelper(tv.m_data.pobj); case KindOfResource: return convResToStrHelper(tv.m_data.pres); default: not_reached(); } }
void tvCastToBooleanInPlace(TypedValue* tv) { tvUnboxIfNeeded(tv); bool b; switch (tv->m_type) { case KindOfUninit: case KindOfNull: b = false; break; case KindOfBoolean: return; case KindOfInt64: b = (tv->m_data.num != 0LL); break; case KindOfDouble: b = (tv->m_data.dbl != 0); break; case KindOfStaticString: b = tv->m_data.pstr->toBoolean(); break; case KindOfString: b = tv->m_data.pstr->toBoolean(); tvDecRefStr(tv); break; case KindOfArray: b = (!tv->m_data.parr->empty()); tvDecRefArr(tv); break; case KindOfObject: b = (tv->m_data.pobj != nullptr); tvDecRefObj(tv); break; default: assert(false); b = false; break; } tv->m_data.num = b; tv->m_type = KindOfBoolean; }
void cellCastToInt64InPlace(Cell* cell) { assert(cellIsPlausible(*cell)); int64_t i; switch (cell->m_type) { case KindOfUninit: case KindOfNull: cell->m_data.num = 0LL; // Fall through case KindOfBoolean: assert(cell->m_data.num == 0LL || cell->m_data.num == 1LL); cell->m_type = KindOfInt64; // Fall through case KindOfInt64: return; case KindOfDouble: { i = toInt64(cell->m_data.dbl); break; } case KindOfStaticString: i = (cell->m_data.pstr->toInt64()); break; case KindOfString: { i = cell->m_data.pstr->toInt64(); tvDecRefStr(cell); break; } case KindOfArray: i = cell->m_data.parr->empty() ? 0 : 1; tvDecRefArr(cell); break; case KindOfObject: i = cell->m_data.pobj->o_toInt64(); tvDecRefObj(cell); break; case KindOfResource: i = cell->m_data.pres->o_toInt64(); tvDecRefRes(cell); break; default: not_reached(); } cell->m_data.num = i; cell->m_type = KindOfInt64; }
void tvCastToStringInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); StringData * s; switch (tv->m_type) { case KindOfUninit: case KindOfNull: s = empty_string.get(); goto static_string; case KindOfBoolean: s = tv->m_data.num ? s_1.get() : empty_string.get(); goto static_string; case KindOfInt64: s = buildStringData(tv->m_data.num); break; case KindOfDouble: s = buildStringData(tv->m_data.dbl); break; case KindOfStaticString: case KindOfString: return; case KindOfArray: raise_notice("Array to string conversion"); s = s_Array.get(); tvDecRefArr(tv); goto static_string; case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->invokeToString(); return; case KindOfResource: // For resources, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pres->o_toString(); return; default: not_reached(); } s->incRefCount(); tv->m_data.pstr = s; tv->m_type = KindOfString; return; static_string: tv->m_data.pstr = s; tv->m_type = KindOfStaticString; }
void tvCastToInt64InPlace(TypedValue* tv, int base /* = 10 */) { tvUnboxIfNeeded(tv); int64_t i; switch (tv->m_type) { case KindOfUninit: case KindOfNull: tv->m_data.num = 0LL; // Fall through case KindOfBoolean: assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL); tv->m_type = KindOfInt64; // Fall through case KindOfInt64: return; case KindOfDouble: { i = toInt64(tv->m_data.dbl); break; } case KindOfStaticString: i = (tv->m_data.pstr->toInt64(base)); break; case KindOfString: { i = (tv->m_data.pstr->toInt64(base)); tvDecRefStr(tv); break; } case KindOfArray: { i = (tv->m_data.parr->empty() ? 0LL : 1LL); tvDecRefArr(tv); break; } case KindOfObject: { i = (tv->m_data.pobj ? tv->m_data.pobj->o_toInt64() : 0LL); tvDecRefObj(tv); break; } default: assert(false); i = 0LL; break; } tv->m_data.num = i; tv->m_type = KindOfInt64; }
void tvCastToBooleanInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); bool b; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: b = false; continue; case KindOfBoolean: return; case KindOfInt64: b = (tv->m_data.num != 0LL); continue; case KindOfDouble: b = (tv->m_data.dbl != 0); continue; case KindOfPersistentString: b = tv->m_data.pstr->toBoolean(); continue; case KindOfString: b = tv->m_data.pstr->toBoolean(); tvDecRefStr(tv); continue; case KindOfPersistentArray: b = !tv->m_data.parr->empty(); continue; case KindOfArray: b = !tv->m_data.parr->empty(); tvDecRefArr(tv); continue; case KindOfObject: b = tv->m_data.pobj->toBoolean(); tvDecRefObj(tv); continue; case KindOfResource: b = tv->m_data.pres->data()->o_toBoolean(); tvDecRefRes(tv); continue; case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); tv->m_data.num = b; tv->m_type = KindOfBoolean; }
void tvCastToArrayInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); ArrayData* a; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: a = ArrayData::Create(); continue; case KindOfBoolean: case KindOfInt64: case KindOfDouble: case KindOfPersistentString: a = ArrayData::Create(tvAsVariant(tv)); continue; case KindOfString: a = ArrayData::Create(tvAsVariant(tv)); tvDecRefStr(tv); continue; case KindOfPersistentVec: { auto* adIn = tv->m_data.parr; assert(adIn->isVecArray()); a = PackedArray::ToPHPArrayVec(adIn, true); assert(a != adIn); continue; } case KindOfVec: { auto* adIn = tv->m_data.parr; assert(adIn->isVecArray()); a = PackedArray::ToPHPArrayVec(adIn, adIn->cowCheck()); if (a != adIn) tvDecRefArr(tv); continue; } case KindOfPersistentDict: { auto* adIn = tv->m_data.parr; assert(adIn->isDict()); a = MixedArray::ToPHPArrayDict(adIn, true); assert(a != adIn); continue; } case KindOfDict: { auto* adIn = tv->m_data.parr; assert(adIn->isDict()); a = MixedArray::ToPHPArrayDict(adIn, adIn->cowCheck()); if (a != adIn) tvDecRefArr(tv); continue; } case KindOfPersistentKeyset: { auto* adIn = tv->m_data.parr; assert(adIn->isKeyset()); a = MixedArray::ToPHPArrayKeyset(adIn, true); assert(a != adIn); continue; } case KindOfKeyset: { auto* adIn = tv->m_data.parr; assert(adIn->isKeyset()); a = MixedArray::ToPHPArrayKeyset(adIn, adIn->cowCheck()); if (a != adIn) tvDecRefArr(tv); continue; } case KindOfPersistentArray: case KindOfArray: assert(tv->m_data.parr->isPHPArray()); return; case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->toArray(); return; case KindOfResource: a = ArrayData::Create(tvAsVariant(tv)); tvDecRefRes(tv); continue; case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); assert(!a->isRefCounted() || a->hasExactlyOneRef()); tv->m_data.parr = a; tv->m_type = KindOfArray; assert(cellIsPlausible(*tv)); }
void cellCastToInt64InPlace(Cell* cell) { assert(cellIsPlausible(*cell)); int64_t i; do { switch (cell->m_type) { case KindOfUninit: case KindOfNull: cell->m_data.num = 0LL; // fallthru case KindOfBoolean: assert(cell->m_data.num == 0LL || cell->m_data.num == 1LL); cell->m_type = KindOfInt64; // fallthru case KindOfInt64: return; case KindOfDouble: i = toInt64(cell->m_data.dbl); continue; case KindOfPersistentString: i = cell->m_data.pstr->toInt64(); continue; case KindOfString: i = cell->m_data.pstr->toInt64(); tvDecRefStr(cell); continue; case KindOfPersistentVec: case KindOfPersistentDict: case KindOfPersistentKeyset: case KindOfPersistentArray: i = cell->m_data.parr->empty() ? 0 : 1; continue; case KindOfVec: case KindOfDict: case KindOfKeyset: case KindOfArray: i = cell->m_data.parr->empty() ? 0 : 1; tvDecRefArr(cell); continue; case KindOfObject: i = cell->m_data.pobj->toInt64(); tvDecRefObj(cell); continue; case KindOfResource: i = cell->m_data.pres->data()->o_toInt64(); tvDecRefRes(cell); continue; case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); cell->m_data.num = i; cell->m_type = KindOfInt64; }
void tvCastToDoubleInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); double d; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: d = 0.0; continue; case KindOfBoolean: assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL); // fallthru case KindOfInt64: d = (double)(tv->m_data.num); continue; case KindOfDouble: return; case KindOfPersistentString: d = tv->m_data.pstr->toDouble(); continue; case KindOfString: d = tv->m_data.pstr->toDouble(); tvDecRefStr(tv); continue; case KindOfPersistentVec: case KindOfPersistentDict: case KindOfPersistentKeyset: case KindOfPersistentArray: d = tv->m_data.parr->empty() ? 0 : 1; continue; case KindOfVec: case KindOfDict: case KindOfKeyset: case KindOfArray: d = tv->m_data.parr->empty() ? 0 : 1; tvDecRefArr(tv); continue; case KindOfObject: d = tv->m_data.pobj->toDouble(); tvDecRefObj(tv); continue; case KindOfResource: d = tv->m_data.pres->data()->o_toDouble(); tvDecRefRes(tv); continue; case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); tv->m_data.dbl = d; tv->m_type = KindOfDouble; }