src/serial/classinfo.cpp

Search Toolkit Book for info_8cpp-source

Go to the documentation of this file.
00001 /*  $Id: classinfo.cpp 103491 2007-05-04 17:18:18Z kazimird $
00002 * ===========================================================================
00003 *
00004 *                            PUBLIC DOMAIN NOTICE
00005 *               National Center for Biotechnology Information
00006 *
00007 *  This software/database is a "United States Government Work" under the
00008 *  terms of the United States Copyright Act.  It was written as part of
00009 *  the author's official duties as a United States Government employee and
00010 *  thus cannot be copyrighted.  This software/database is freely available
00011 *  to the public for use. The National Library of Medicine and the U.S.
00012 *  Government have not placed any restriction on its use or reproduction.
00013 *
00014 *  Although all reasonable efforts have been taken to ensure the accuracy
00015 *  and reliability of the software and data, the NLM and the U.S.
00016 *  Government do not and cannot warrant the performance or results that
00017 *  may be obtained by using this software or data. The NLM and the U.S.
00018 *  Government disclaim all warranties, express or implied, including
00019 *  warranties of performance, merchantability or fitness for any particular
00020 *  purpose.
00021 *
00022 *  Please cite the author in any work or product based on this material.
00023 *
00024 * ===========================================================================
00025 *
00026 * Author: Eugene Vasilchenko
00027 *
00028 * File Description:
00029 *   !!! PUT YOUR DESCRIPTION HERE !!!
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         // do not have subclasses -> real type is the same as our type
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     // check 'set' flag
00206     bool haveSetFlag = info->HaveSetFlag();
00207     if ( haveSetFlag && info->GetSetFlagNo(object) )
00208         return; // member not set
00209     
00210     TObjectPtr member = GetMember(info, object);
00211     // assign member default
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     // update 'set' flag
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 /*object*/) 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     // User defined comparison
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     // User defined assignment
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 

Generated on Wed Dec 9 05:23:13 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:18:14 2009 by modify_doxy.py rev. 173732