void CChoiceTypeInfo::Assign(TObjectPtr dst, TConstObjectPtr src, ESerialRecursionMode how) const { TMemberIndex index; index = GetVariants().FirstIndex(); const CVariantInfo* variantInfo = GetVariantInfo(index); if (variantInfo->GetId().IsAttlist()) { const CMemberInfo* info = dynamic_cast<const CMemberInfo*>(GetVariants().GetItemInfo(index)); info->GetTypeInfo()->Assign(GetMember(info, dst), GetMember(info, src),how); } index = GetIndex(src); if ( index == kEmptyChoice ) ResetIndex(dst); else { _ASSERT(index >= GetVariants().FirstIndex() && index <= GetVariants().LastIndex()); SetIndex(dst, index); GetVariantInfo(index)->GetTypeInfo()->Assign(GetData(dst, index), GetData(src, index), how); } // User defined assignment CallUserOp_Assign(dst, src); }
void CChoicePointerTypeInfo::SetPointerType(TTypeInfo base) { m_NullPointerIndex = kEmptyChoice; if ( base->GetTypeFamily() != eTypeFamilyPointer ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument: must be CPointerTypeInfo"); const CPointerTypeInfo* ptrType = CTypeConverter<CPointerTypeInfo>::SafeCast(base); m_PointerTypeInfo = ptrType; if ( ptrType->GetPointedType()->GetTypeFamily() != eTypeFamilyClass ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument: data must be CClassTypeInfo"); const CClassTypeInfo* classType = CTypeConverter<CClassTypeInfo>::SafeCast(ptrType->GetPointedType()); /* Do we really need it to be CObject??? if ( !classType->IsCObject() ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument:: choice ptr type must be CObject"); */ const CClassTypeInfo::TSubClasses* subclasses = classType->SubClasses(); if ( !subclasses ) return; TTypeInfo nullTypeInfo = CNullTypeInfo::GetTypeInfo(); for ( CClassTypeInfo::TSubClasses::const_iterator i = subclasses->begin(); i != subclasses->end(); ++i ) { TTypeInfo variantType = i->second.Get(); if ( !variantType ) { // null variantType = nullTypeInfo; } AddVariant(i->first, 0, variantType)->SetSubClass(); TMemberIndex index = GetVariants().LastIndex(); if ( variantType == nullTypeInfo ) { if ( m_NullPointerIndex == kEmptyChoice ) m_NullPointerIndex = index; else { ERR_POST_X(1, "double null"); } } else { const type_info* id = &CTypeConverter<CClassTypeInfo>::SafeCast(variantType)->GetId(); if ( !m_VariantsByType.insert(TVariantsByType::value_type(id, index)).second ) { NCBI_THROW(CSerialException,eInvalidData, "conflict subclasses: "+variantType->GetName()); } } } }
bool CChoiceTypeInfo::Equals(TConstObjectPtr object1, TConstObjectPtr object2, ESerialRecursionMode how) const { // User defined comparison if ( IsCObject() ) { if ( const CSerialUserOp* op1 = dynamic_cast<const CSerialUserOp*> (static_cast<const CObject*>(object1)) ) { if ( const CSerialUserOp* op2 = dynamic_cast<const CSerialUserOp*> (static_cast<const CObject*>(object2)) ) { if ( !op1->UserOp_Equals(*op2) ) return false; } } } TMemberIndex index; index = GetVariants().FirstIndex(); const CVariantInfo* variantInfo = GetVariantInfo(index); if (variantInfo->GetId().IsAttlist()) { const CMemberInfo* info = dynamic_cast<const CMemberInfo*>(GetVariants().GetItemInfo(index)); if ( !info->GetTypeInfo()->Equals(GetMember(info, object1), GetMember(info, object2), how) ) { return false; } } // Default comparison index = GetIndex(object1); if ( index != GetIndex(object2) ) return false; if ( index == kEmptyChoice ) return true; return GetVariantInfo(index)->GetTypeInfo()->Equals(GetData(object1, index), GetData(object2, index), how); }
CVariantInfo* CChoiceTypeInfo::AddVariant(const CMemberId& memberId, const void* memberPtr, const CTypeRef& memberType) { if ( GetVariants().Size() == 1 && !GetVariantInfo(kFirstMemberIndex)->GetId().IsAttlist() ) { // simple SetReadFunction(&TFunc::ReadChoiceSimple); SetSkipFunction(&TFunc::SkipChoiceSimple); } CVariantInfo* variantInfo = new CVariantInfo(this, memberId, TPointerOffsetType(memberPtr), memberType); GetItems().AddItem(variantInfo); return variantInfo; }