APCHandle* APCArray::MakeShared(ArrayData* arr, size_t& size, bool inner, bool unserializeObj) { if (!inner) { // only need to call traverseData() on the toplevel array DataWalker walker(DataWalker::LookupFeature::HasObjectOrResource); DataWalker::DataFeature features = walker.traverseData(arr); if (features.isCircular() || features.hasCollection()) { String s = apc_serialize(arr); APCHandle* handle = APCString::MakeShared(KindOfArray, s.get(), size); handle->setSerializedArray(); return handle; } if (apcExtension::UseUncounted && !features.hasObjectOrResource() && !arr->empty()) { size = getMemSize(arr) + sizeof(APCTypedValue); return APCTypedValue::MakeSharedArray(arr); } } if (arr->isVectorData()) { return APCArray::MakePackedShared(arr, size, unserializeObj); } return APCArray::MakeShared(arr, size, unserializeObj); }
APCHandle* APCObject::MakeAPCObject(APCHandle* obj, CVarRef value) { if (!value.is(KindOfObject) || obj->getObjAttempted()) { return nullptr; } obj->setObjAttempted(); ObjectData *o = value.getObjectData(); DataWalker walker(DataWalker::LookupFeature::DetectSerializable); DataWalker::DataFeature features = walker.traverseData(o); if (features.isCircular() || features.hasCollection() || features.hasSerializableReference()) { return nullptr; } APCHandle* tmp = APCHandle::Create(value, false, true, true); tmp->setObjAttempted(); return tmp; }
APCHandle* APCObject::MakeAPCObject( APCHandle* obj, size_t& size, const Variant& value) { if (!value.is(KindOfObject) || obj->objAttempted()) { return nullptr; } obj->setObjAttempted(); ObjectData *o = value.getObjectData(); if (apcExtension::OptimizeSerialization) { return MakeShared(o, size, false, false); } DataWalker walker(DataWalker::LookupFeature::DetectSerializable); DataWalker::DataFeature features = walker.traverseData(o); if (features.isCircular() || features.hasCollection() || features.hasSerializableReference()) { return nullptr; } APCHandle* tmp = APCHandle::Create(value, size, false, true, true); tmp->setObjAttempted(); return tmp; }