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::AssignVisitor::visitObject(const ObjectRefPtr& dest) { Slice::TypePtr type = dest->getType(); ObjectRefPtr src = ObjectRefPtr::dynamicCast(_src); if(!src) { typeMismatchError(type, _src->getType()); } 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)) { dest->setValue(srcValue); } else { typeMismatchError(type, srcValueType); } } }
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); }
bool FreezeScript::invokeMemberFunction(const string& name, const DataPtr& target, const DataList& args, DataPtr& result, const DataFactoryPtr& factory, const ErrorReporterPtr& errorReporter) { // // string // StringDataPtr targetStr = StringDataPtr::dynamicCast(target); if(targetStr) { if(name == "find") { StringDataPtr argData; IntegerDataPtr startData; if(args.size() > 0) { argData = StringDataPtr::dynamicCast(args[0]); } if(args.size() > 1) { startData = IntegerDataPtr::dynamicCast(args[1]); } if(args.size() == 0 || args.size() > 2 || !argData || (args.size() == 2 && !startData)) { errorReporter->error("invalid arguments to find(string str[, int len])"); } string targ = targetStr->stringValue(); string arg = argData->stringValue(); string::size_type pos; if(startData) { string::size_type start = static_cast<string::size_type>(startData->integerValue()); pos = targ.find(arg, start); } else { pos = targ.find(arg); } result = factory->createInteger(pos == string::npos ? -1 : static_cast<Ice::Long>(pos), false); return true; } else if(name == "substr") { IntegerDataPtr startData; IntegerDataPtr lenData; if(args.size() > 0) { startData = IntegerDataPtr::dynamicCast(args[0]); } if(args.size() > 1) { lenData = IntegerDataPtr::dynamicCast(args[1]); } if(args.size() == 0 || args.size() > 2 || !startData || (args.size() == 2 && !lenData)) { errorReporter->error("invalid arguments to substr(int start[, int len])"); } string targ = targetStr->stringValue(); string::size_type start = static_cast<string::size_type>(startData->integerValue()); string::size_type len = string::npos; if(lenData) { len = static_cast<string::size_type>(lenData->integerValue()); } if(start > targ.size()) { ostringstream ostr; ostr << "substr() starting position (" << start << ") is greater than string length (" << targ.size() << ")"; errorReporter->error(ostr.str()); } result = factory->createString(targ.substr(start, len), false); return true; } else if(name == "replace") { IntegerDataPtr startData; IntegerDataPtr lenData; StringDataPtr strData; if(args.size() == 3) { startData = IntegerDataPtr::dynamicCast(args[0]); lenData = IntegerDataPtr::dynamicCast(args[1]); strData = StringDataPtr::dynamicCast(args[2]); } if(args.size() != 3 || !startData || !lenData || !strData) { errorReporter->error("invalid arguments to replace(int start, int len, string val)"); } string targ = targetStr->stringValue(); string::size_type start = static_cast<string::size_type>(startData->integerValue()); string::size_type len = static_cast<string::size_type>(lenData->integerValue()); string str = strData->stringValue(); if(start > targ.size()) { ostringstream ostr; ostr << "replace() starting position (" << start << ") is greater than string length (" << targ.size() << ")"; errorReporter->error(ostr.str()); } result = factory->createString(targ.replace(start, len, str), false); return true; } return false; } // // Object // ObjectRefPtr targetObj = ObjectRefPtr::dynamicCast(target); if(targetObj) { if(name == "ice_isA") { ObjectDataPtr value = targetObj->getValue(); if(!value) { errorReporter->error("ice_isA() invoked on nil object"); } StringDataPtr str; if(args.size() > 0) { str = StringDataPtr::dynamicCast(args.front()); } if(args.size() != 1 || !str) { errorReporter->error("invalid arguments to ice_isA(string id)"); } string id = str->stringValue(); if(id == "::Ice::Object") { result = factory->createBoolean(true, false); return true; } Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(value->getType()); if(!decl) { // // Ice::Object // result = factory->createBoolean(false, false); return true; } Slice::ClassDefPtr def = decl->definition(); assert(def); result = factory->createBoolean(def->isA(id), false); return true; } return false; } return false; }