00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <ncbi_pch.hpp>
00033 #include <corelib/ncbistd.hpp>
00034 #include <corelib/ncbiutil.hpp>
00035 #include <corelib/ncbimtx.hpp>
00036
00037 #include <serial/impl/classinfo.hpp>
00038 #include <serial/objistr.hpp>
00039 #include <serial/objostr.hpp>
00040 #include <serial/objcopy.hpp>
00041 #include <serial/delaybuf.hpp>
00042 #include <serial/impl/stdtypes.hpp>
00043 #include <serial/serialbase.hpp>
00044
00045 BEGIN_NCBI_SCOPE
00046
00047 CClassTypeInfo::CClassTypeInfo(size_t size, const char* name,
00048 const void* nonCObject, TTypeCreate createFunc,
00049 const type_info& ti, TGetTypeIdFunction idFunc)
00050 : CParent(eTypeFamilyClass, size, name, nonCObject, createFunc, ti),
00051 m_GetTypeIdFunction(idFunc)
00052 {
00053 InitClassTypeInfo();
00054 }
00055
00056 CClassTypeInfo::CClassTypeInfo(size_t size, const char* name,
00057 const CObject* cObject, TTypeCreate createFunc,
00058 const type_info& ti, TGetTypeIdFunction idFunc)
00059 : CParent(eTypeFamilyClass, size, name, cObject, createFunc, ti),
00060 m_GetTypeIdFunction(idFunc)
00061 {
00062 InitClassTypeInfo();
00063 }
00064
00065 CClassTypeInfo::CClassTypeInfo(size_t size, const string& name,
00066 const void* nonCObject, TTypeCreate createFunc,
00067 const type_info& ti, TGetTypeIdFunction idFunc)
00068 : CParent(eTypeFamilyClass, size, name, nonCObject, createFunc, ti),
00069 m_GetTypeIdFunction(idFunc)
00070 {
00071 InitClassTypeInfo();
00072 }
00073
00074 CClassTypeInfo::CClassTypeInfo(size_t size, const string& name,
00075 const CObject* cObject, TTypeCreate createFunc,
00076 const type_info& ti, TGetTypeIdFunction idFunc)
00077 : CParent(eTypeFamilyClass, size, name, cObject, createFunc, ti),
00078 m_GetTypeIdFunction(idFunc)
00079 {
00080 InitClassTypeInfo();
00081 }
00082
00083 void CClassTypeInfo::InitClassTypeInfo(void)
00084 {
00085 m_ClassType = eSequential;
00086 m_ParentClassInfo = 0;
00087
00088 UpdateFunctions();
00089 }
00090
00091 CClassTypeInfo* CClassTypeInfo::SetRandomOrder(bool random)
00092 {
00093 _ASSERT(!Implicit());
00094 m_ClassType = random? eRandom: eSequential;
00095 UpdateFunctions();
00096 return this;
00097 }
00098
00099 CClassTypeInfo* CClassTypeInfo::SetImplicit(void)
00100 {
00101 m_ClassType = eImplicit;
00102 UpdateFunctions();
00103 return this;
00104 }
00105
00106 bool CClassTypeInfo::IsImplicitNonEmpty(void) const
00107 {
00108 _ASSERT(Implicit());
00109 return GetImplicitMember()->NonEmpty();
00110 }
00111
00112 void CClassTypeInfo::AddSubClass(const CMemberId& id,
00113 const CTypeRef& type)
00114 {
00115 TSubClasses* subclasses = m_SubClasses.get();
00116 if ( !subclasses )
00117 m_SubClasses.reset(subclasses = new TSubClasses);
00118 subclasses->push_back(make_pair(id, type));
00119 }
00120
00121 void CClassTypeInfo::AddSubClassNull(const CMemberId& id)
00122 {
00123 AddSubClass(id, CTypeRef(TTypeInfo(0)));
00124 }
00125
00126 void CClassTypeInfo::AddSubClass(const char* id, TTypeInfoGetter getter)
00127 {
00128 AddSubClass(CMemberId(id), getter);
00129 }
00130
00131 void CClassTypeInfo::AddSubClassNull(const char* id)
00132 {
00133 AddSubClassNull(CMemberId(id));
00134 }
00135
00136 const CClassTypeInfo* CClassTypeInfo::GetParentClassInfo(void) const
00137 {
00138 return m_ParentClassInfo;
00139 }
00140
00141 void CClassTypeInfo::SetParentClass(TTypeInfo parentType)
00142 {
00143 if ( parentType->GetTypeFamily() != eTypeFamilyClass )
00144 NCBI_THROW(CSerialException,eInvalidData,
00145 string("invalid parent class type: ") +
00146 parentType->GetName());
00147 const CClassTypeInfo* parentClass =
00148 CTypeConverter<CClassTypeInfo>::SafeCast(parentType);
00149 _ASSERT(parentClass != 0);
00150 _ASSERT(IsCObject() == parentClass->IsCObject());
00151 _ASSERT(!m_ParentClassInfo);
00152 m_ParentClassInfo = parentClass;
00153 _ASSERT(GetMembers().Empty());
00154 AddMember(NcbiEmptyString, 0, parentType)->SetParentClass();
00155 }
00156
00157 TTypeInfo CClassTypeInfo::GetRealTypeInfo(TConstObjectPtr object) const
00158 {
00159 if ( !m_SubClasses.get() ) {
00160
00161 return this;
00162 }
00163 const type_info* ti = GetCPlusPlusTypeInfo(object);
00164 if ( ti == 0 || ti == &GetId() )
00165 return this;
00166 RegisterSubClasses();
00167 return GetClassInfoById(*ti);
00168 }
00169
00170 void CClassTypeInfo::RegisterSubClasses(void) const
00171 {
00172 const TSubClasses* subclasses = m_SubClasses.get();
00173 if ( subclasses ) {
00174 for ( TSubClasses::const_iterator i = subclasses->begin();
00175 i != subclasses->end();
00176 ++i ) {
00177 TTypeInfo subClass = i->second.Get();
00178 if ( subClass->GetTypeFamily() == eTypeFamilyClass ) {
00179 CTypeConverter<CClassTypeInfo>::SafeCast(subClass)->RegisterSubClasses();
00180 }
00181 }
00182 }
00183 }
00184
00185 static inline
00186 TObjectPtr GetMember(const CMemberInfo* memberInfo, TObjectPtr object)
00187 {
00188 if ( memberInfo->CanBeDelayed() )
00189 memberInfo->GetDelayBuffer(object).Update();
00190 return memberInfo->GetItemPtr(object);
00191 }
00192
00193 static inline
00194 TConstObjectPtr GetMember(const CMemberInfo* memberInfo,
00195 TConstObjectPtr object)
00196 {
00197 if ( memberInfo->CanBeDelayed() )
00198 const_cast<CDelayBuffer&>(memberInfo->GetDelayBuffer(object)).Update();
00199 return memberInfo->GetItemPtr(object);
00200 }
00201
00202 void CClassTypeInfo::AssignMemberDefault(TObjectPtr object,
00203 const CMemberInfo* info) const
00204 {
00205
00206 bool haveSetFlag = info->HaveSetFlag();
00207 if ( haveSetFlag && info->GetSetFlagNo(object) )
00208 return;
00209
00210 TObjectPtr member = GetMember(info, object);
00211
00212 TTypeInfo memberType = info->GetTypeInfo();
00213 TConstObjectPtr def = info->GetDefault();
00214 if ( def == 0 ) {
00215 if ( !memberType->IsDefault(member) )
00216 memberType->SetDefault(member);
00217 }
00218 else {
00219 memberType->Assign(member, def);
00220 }
00221
00222 if ( haveSetFlag )
00223 info->UpdateSetFlagNo(object);
00224 }
00225
00226 void CClassTypeInfo::AssignMemberDefault(TObjectPtr object,
00227 TMemberIndex index) const
00228 {
00229 AssignMemberDefault(object, GetMemberInfo(index));
00230 }
00231
00232
00233 const CMemberInfo* CClassTypeInfo::GetImplicitMember(void) const
00234 {
00235 _ASSERT(GetMembers().FirstIndex() == GetMembers().LastIndex());
00236 return GetMemberInfo(GetMembers().FirstIndex());
00237 }
00238
00239 void CClassTypeInfo::UpdateFunctions(void)
00240 {
00241 switch ( m_ClassType ) {
00242 case eSequential:
00243 SetReadFunction(&ReadClassSequential);
00244 SetWriteFunction(&WriteClassSequential);
00245 SetCopyFunction(&CopyClassSequential);
00246 SetSkipFunction(&SkipClassSequential);
00247 break;
00248 case eRandom:
00249 SetReadFunction(&ReadClassRandom);
00250 SetWriteFunction(&WriteClassRandom);
00251 SetCopyFunction(&CopyClassRandom);
00252 SetSkipFunction(&SkipClassRandom);
00253 break;
00254 case eImplicit:
00255 SetReadFunction(&ReadImplicitMember);
00256 SetWriteFunction(&WriteImplicitMember);
00257 SetCopyFunction(&CopyImplicitMember);
00258 SetSkipFunction(&SkipImplicitMember);
00259 break;
00260 }
00261 }
00262
00263 void CClassTypeInfo::ReadClassSequential(CObjectIStream& in,
00264 TTypeInfo objectType,
00265 TObjectPtr objectPtr)
00266 {
00267 const CClassTypeInfo* classType =
00268 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00269
00270 in.ReadClassSequential(classType, objectPtr);
00271 }
00272
00273 void CClassTypeInfo::ReadClassRandom(CObjectIStream& in,
00274 TTypeInfo objectType,
00275 TObjectPtr objectPtr)
00276 {
00277 const CClassTypeInfo* classType =
00278 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00279
00280 in.ReadClassRandom(classType, objectPtr);
00281 }
00282
00283 void CClassTypeInfo::ReadImplicitMember(CObjectIStream& in,
00284 TTypeInfo objectType,
00285 TObjectPtr objectPtr)
00286 {
00287 const CClassTypeInfo* classType =
00288 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00289
00290 const CMemberInfo* memberInfo = classType->GetImplicitMember();
00291 if( memberInfo->HaveSetFlag()) {
00292 memberInfo->UpdateSetFlagYes(objectPtr);
00293 }
00294 in.ReadNamedType(classType,
00295 memberInfo->GetTypeInfo(),
00296 memberInfo->GetItemPtr(objectPtr));
00297 }
00298
00299 void CClassTypeInfo::WriteClassRandom(CObjectOStream& out,
00300 TTypeInfo objectType,
00301 TConstObjectPtr objectPtr)
00302 {
00303 const CClassTypeInfo* classType =
00304 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00305
00306 out.WriteClassRandom(classType, objectPtr);
00307 }
00308
00309 void CClassTypeInfo::WriteClassSequential(CObjectOStream& out,
00310 TTypeInfo objectType,
00311 TConstObjectPtr objectPtr)
00312 {
00313 const CClassTypeInfo* classType =
00314 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00315
00316 out.WriteClassSequential(classType, objectPtr);
00317 }
00318
00319 void CClassTypeInfo::WriteImplicitMember(CObjectOStream& out,
00320 TTypeInfo objectType,
00321 TConstObjectPtr objectPtr)
00322 {
00323 const CClassTypeInfo* classType =
00324 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00325
00326 const CMemberInfo* memberInfo = classType->GetImplicitMember();
00327 if (memberInfo->HaveSetFlag() && memberInfo->GetSetFlagNo(objectPtr)) {
00328 if (memberInfo->Optional()) {
00329 return;
00330 }
00331 if (memberInfo->NonEmpty() ||
00332 memberInfo->GetTypeInfo()->GetTypeFamily() != eTypeFamilyContainer) {
00333 ESerialVerifyData verify = out.GetVerifyData();
00334 if (verify == eSerialVerifyData_Yes) {
00335 out.ThrowError(CObjectOStream::fUnassigned,
00336 string("Unassigned member: ")+classType->GetName());
00337 } else if (verify == eSerialVerifyData_No) {
00338 return;
00339 }
00340 }
00341 }
00342 out.WriteNamedType(classType,
00343 memberInfo->GetTypeInfo(),
00344 memberInfo->GetItemPtr(objectPtr));
00345 }
00346
00347 void CClassTypeInfo::CopyClassRandom(CObjectStreamCopier& copier,
00348 TTypeInfo objectType)
00349 {
00350 const CClassTypeInfo* classType =
00351 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00352
00353 copier.CopyClassRandom(classType);
00354 }
00355
00356 void CClassTypeInfo::CopyClassSequential(CObjectStreamCopier& copier,
00357 TTypeInfo objectType)
00358 {
00359 const CClassTypeInfo* classType =
00360 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00361
00362 copier.CopyClassSequential(classType);
00363 }
00364
00365 void CClassTypeInfo::CopyImplicitMember(CObjectStreamCopier& copier,
00366 TTypeInfo objectType)
00367 {
00368 const CClassTypeInfo* classType =
00369 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00370
00371 const CMemberInfo* memberInfo = classType->GetImplicitMember();
00372 copier.CopyNamedType(classType, memberInfo->GetTypeInfo());
00373 }
00374
00375 void CClassTypeInfo::SkipClassRandom(CObjectIStream& in,
00376 TTypeInfo objectType)
00377 {
00378 const CClassTypeInfo* classType =
00379 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00380
00381 in.SkipClassRandom(classType);
00382 }
00383
00384 void CClassTypeInfo::SkipClassSequential(CObjectIStream& in,
00385 TTypeInfo objectType)
00386 {
00387 const CClassTypeInfo* classType =
00388 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00389
00390 in.SkipClassSequential(classType);
00391 }
00392
00393 void CClassTypeInfo::SkipImplicitMember(CObjectIStream& in,
00394 TTypeInfo objectType)
00395 {
00396 const CClassTypeInfo* classType =
00397 CTypeConverter<CClassTypeInfo>::SafeCast(objectType);
00398
00399 const CMemberInfo* memberInfo = classType->GetImplicitMember();
00400 in.SkipNamedType(classType, memberInfo->GetTypeInfo());
00401 }
00402
00403 bool CClassTypeInfo::IsDefault(TConstObjectPtr ) const
00404 {
00405 return false;
00406 }
00407
00408 void CClassTypeInfo::SetDefault(TObjectPtr dst) const
00409 {
00410 for ( TMemberIndex i = GetMembers().FirstIndex(),
00411 last = GetMembers().LastIndex();
00412 i <= last; ++i ) {
00413 AssignMemberDefault(dst, i);
00414 }
00415 }
00416
00417 bool CClassTypeInfo::Equals(TConstObjectPtr object1, TConstObjectPtr object2,
00418 ESerialRecursionMode how) const
00419 {
00420 for ( TMemberIndex i = GetMembers().FirstIndex(),
00421 last = GetMembers().LastIndex();
00422 i <= last; ++i ) {
00423 const CMemberInfo* info = GetMemberInfo(i);
00424 if ( !info->GetTypeInfo()->Equals(GetMember(info, object1),
00425 GetMember(info, object2), how) )
00426 return false;
00427 if ( info->HaveSetFlag() ) {
00428 if ( !info->CompareSetFlags(object1,object2) )
00429 return false;
00430 }
00431 }
00432
00433
00434 if ( IsCObject() ) {
00435 const CSerialUserOp* op1 =
00436 dynamic_cast<const CSerialUserOp*>
00437 (static_cast<const CObject*>(object1));
00438 const CSerialUserOp* op2 =
00439 dynamic_cast<const CSerialUserOp*>
00440 (static_cast<const CObject*>(object2));
00441 if ( op1 && op2 ) {
00442 return op1->UserOp_Equals(*op2);
00443 }
00444 }
00445 return true;
00446 }
00447
00448 void CClassTypeInfo::Assign(TObjectPtr dst, TConstObjectPtr src,
00449 ESerialRecursionMode how) const
00450 {
00451 for ( TMemberIndex i = GetMembers().FirstIndex(),
00452 last = GetMembers().LastIndex();
00453 i <= last; ++i ) {
00454 const CMemberInfo* info = GetMemberInfo(i);
00455 info->GetTypeInfo()->Assign(GetMember(info, dst),
00456 GetMember(info, src), how);
00457 if ( info->HaveSetFlag() ) {
00458 info->UpdateSetFlag(dst,info->GetSetFlag(src));
00459 }
00460 }
00461
00462
00463 if ( IsCObject() ) {
00464 const CSerialUserOp* opsrc =
00465 dynamic_cast<const CSerialUserOp*>
00466 (static_cast<const CObject*>(src));
00467 CSerialUserOp* opdst =
00468 dynamic_cast<CSerialUserOp*>
00469 (static_cast<CObject*>(dst));
00470 if ( opdst && opsrc ) {
00471 opdst->UserOp_Assign(*opsrc);
00472 }
00473 }
00474 }
00475
00476 bool CClassTypeInfo::IsType(TTypeInfo typeInfo) const
00477 {
00478 return typeInfo == this || typeInfo->IsParentClassOf(this);
00479 }
00480
00481 bool CClassTypeInfo::IsParentClassOf(const CClassTypeInfo* typeInfo) const
00482 {
00483 do {
00484 typeInfo = typeInfo->m_ParentClassInfo;
00485 if ( typeInfo == this )
00486 return true;
00487 } while ( typeInfo );
00488 return false;
00489 }
00490
00491 CTypeInfo::EMayContainType
00492 CClassTypeInfo::CalcMayContainType(TTypeInfo typeInfo) const
00493 {
00494 const CClassTypeInfoBase* parentClass = m_ParentClassInfo;
00495 EMayContainType ret = eMayContainType_no;
00496 if ( parentClass ) {
00497 ret = parentClass->GetMayContainType(typeInfo);
00498 if ( ret == eMayContainType_yes ) {
00499 return ret;
00500 }
00501 }
00502 EMayContainType ret2 = CParent::CalcMayContainType(typeInfo);
00503 if ( ret2 != eMayContainType_no ) {
00504 ret = ret2;
00505 }
00506 return ret;
00507 }
00508
00509 END_NCBI_SCOPE
00510
00511