void FreezeScript::TransformVisitor::transformObject(const ObjectDataPtr& dest, const ObjectDataPtr& src) { // // The source object must be present in the object map (we currently don't support // transforming two ObjectData instances from the same Slice unit - this transform // would be handled by-reference at the ObjectRef level). We must update the object // map before transforming members in order to handle cycles. // ObjectDataMap& objectDataMap = _info->getObjectDataMap(); ObjectDataMap::iterator p = objectDataMap.find(src.get()); assert(p != objectDataMap.end()); assert(p->second == 0); objectDataMap.erase(p); objectDataMap.insert(ObjectDataMap::value_type(src.get(), dest)); p = objectDataMap.find(src.get()); try { // // Transform members with the same name. // DataMemberMap srcMap = src->getMembers(); DataMemberMap destMap = dest->getMembers(); string typeName = typeToString(dest->getType()); for(DataMemberMap::iterator q = destMap.begin(); q != destMap.end(); ++q) { DataMemberMap::iterator r = srcMap.find(q->first); if(r != srcMap.end()) { string context = typeName + " member " + q->first + " value"; TransformVisitor v(r->second, _info, context); q->second->visit(v); } } } catch(...) { objectDataMap.erase(p); #if (defined(_MSC_VER) && (_MSC_VER >= 1600)) objectDataMap.insert(ObjectDataMap::value_type(src.get(), static_cast<ObjectDataPtr>(nullptr))); #else objectDataMap.insert(ObjectDataMap::value_type(src.get(), 0)); #endif throw; } }
void FreezeScript::TransformVisitor::visitObject(const ObjectRefPtr& dest) { Slice::TypePtr type = dest->getType(); ObjectRefPtr src = ObjectRefPtr::dynamicCast(_src); if(!src) { typeMismatchError(type, _src->getType()); } else if(_info->doDefaultTransform(type)) { ObjectDataPtr srcValue = src->getValue(); Slice::TypePtr srcType = src->getType(); if(!srcValue) { // // Allow a nil value from type Object. // if(Slice::BuiltinPtr::dynamicCast(srcType) || isCompatible(type, srcType)) { dest->setValue(0); } else { typeMismatchError(type, srcType); } } else { Slice::TypePtr srcValueType = srcValue->getType(); if(isCompatible(type, srcValueType)) { // // If the types are in the same Slice unit, then we can simply // copy the reference. Otherwise, we check the object map to // see if an equivalent object has already been created, and // if not, then we have to create one. // if(type->unit().get() == srcValueType->unit().get()) { dest->setValue(srcValue); } else { ObjectDataMap& objectDataMap = _info->getObjectDataMap(); ObjectDataMap::iterator p = objectDataMap.find(srcValue.get()); if(p != objectDataMap.end() && p->second) { dest->setValue(p->second); } else { // // If the type has been renamed, we need to get its equivalent // in the new Slice definitions. // Slice::TypePtr newType = _info->getRenamedType(srcValueType); if(!newType) { string name = typeToString(srcValueType); Slice::TypeList l = type->unit()->lookupType(name, false); if(l.empty()) { throw ClassNotFoundException(name); } newType = l.front(); } // // Use createObject() so that an initializer is invoked if necessary. // DataPtr newObj = _info->getDataFactory()->createObject(newType, false); ObjectRefPtr newRef = ObjectRefPtr::dynamicCast(newObj); assert(newRef); ObjectDataPtr newValue = newRef->getValue(); try { transformObject(newValue, srcValue); } catch(...) { newObj->destroy(); throw; } dest->setValue(newValue); newObj->destroy(); } } } else { typeMismatchError(type, srcValueType); } } } _info->executeCustomTransform(dest, _src); }