NCBI C++ ToolKit
classinfob.cpp

Search Toolkit Book for infob_8cpp_source

Go to the documentation of this file.
00001 /*  $Id: classinfob.cpp 59586 2013-09-05 15:30:00Z gouriano $
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/ncbithr.hpp>
00035 #include <serial/impl/classinfob.hpp>
00036 #include <serial/objectinfo.hpp>
00037 #include <serial/objhook.hpp>
00038 #include <serial/serialimpl.hpp>
00039 
00040 BEGIN_NCBI_SCOPE
00041 
00042 DEFINE_STATIC_MUTEX(s_ClassInfoMutex);
00043 
00044 CClassTypeInfoBase::CClassTypeInfoBase(ETypeFamily typeFamily,
00045                                        size_t size, const char* name,
00046                                        const void* /*nonCObject*/,
00047                                        TTypeCreate createFunc,
00048                                        const type_info& ti)
00049     : CParent(typeFamily, size, name)
00050 {
00051     SetTag( CAsnBinaryDefs::eSequence);
00052     InitClassTypeInfoBase(ti);
00053     SetCreateFunction(createFunc);
00054 }
00055 
00056 CClassTypeInfoBase::CClassTypeInfoBase(ETypeFamily typeFamily,
00057                                        size_t size, const char* name,
00058                                        const CObject* /*cObject*/,
00059                                        TTypeCreate createFunc,
00060                                        const type_info& ti)
00061     : CParent(typeFamily, size, name)
00062 {
00063     m_IsCObject = true;
00064     SetTag( CAsnBinaryDefs::eSequence);
00065     InitClassTypeInfoBase(ti);
00066     SetCreateFunction(createFunc);
00067 }
00068 
00069 CClassTypeInfoBase::CClassTypeInfoBase(ETypeFamily typeFamily,
00070                                        size_t size, const string& name,
00071                                        const void* /*nonCObject*/,
00072                                        TTypeCreate createFunc,
00073                                        const type_info& ti)
00074     : CParent(typeFamily, size, name)
00075 {
00076     SetTag( CAsnBinaryDefs::eSequence);
00077     InitClassTypeInfoBase(ti);
00078     SetCreateFunction(createFunc);
00079 }
00080 
00081 CClassTypeInfoBase::CClassTypeInfoBase(ETypeFamily typeFamily,
00082                                        size_t size, const string& name,
00083                                        const CObject* /*cObject*/,
00084                                        TTypeCreate createFunc,
00085                                        const type_info& ti)
00086     : CParent(typeFamily, size, name)
00087 {
00088     m_IsCObject = true;
00089     SetTag( CAsnBinaryDefs::eSequence);
00090     InitClassTypeInfoBase(ti);
00091     SetCreateFunction(createFunc);
00092 }
00093 
00094 CClassTypeInfoBase::~CClassTypeInfoBase(void)
00095 {
00096     Deregister();
00097 }
00098 
00099 CMemberInfo* CClassTypeInfoBase::AddMember(const char* memberId,
00100                                            const void* memberPtr,
00101                                            const CTypeRef& memberType)
00102 {
00103     CMemberInfo* memberInfo = new CMemberInfo(this, memberId,
00104                                               TPointerOffsetType(memberPtr),
00105                                               memberType);
00106     GetItems().AddItem(memberInfo);
00107     return memberInfo;
00108 }
00109 
00110 CMemberInfo* CClassTypeInfoBase::AddMember(const CMemberId& memberId,
00111                                            const void* memberPtr,
00112                                            const CTypeRef& memberType)
00113 {
00114     CMemberInfo* memberInfo = new CMemberInfo(this, memberId,
00115                                               TPointerOffsetType(memberPtr),
00116                                               memberType);
00117     GetItems().AddItem(memberInfo);
00118     return memberInfo;
00119 }
00120 
00121 void CClassTypeInfoBase::AssignItemsTags(void)
00122 {
00123     GetItems().AssignItemsTags(GetTagType());
00124 }
00125 
00126 void CClassTypeInfoBase::InitClassTypeInfoBase(const type_info& id)
00127 {
00128     m_Id = &id;
00129     Register();
00130 }
00131 
00132 CClassTypeInfoBase::TClasses* CClassTypeInfoBase::sm_Classes = 0;
00133 CClassTypeInfoBase::TClassesById* CClassTypeInfoBase::sm_ClassesById = 0;
00134 CClassTypeInfoBase::TClassesByName* CClassTypeInfoBase::sm_ClassesByName = 0;
00135 set<string>* CClassTypeInfoBase::sm_Modules = 0;
00136 
00137 inline
00138 CClassTypeInfoBase::TClasses& CClassTypeInfoBase::Classes(void)
00139 {
00140     TClasses* classes = sm_Classes;
00141     if ( !classes ) {
00142         CMutexGuard GUARD(s_ClassInfoMutex);
00143         classes = sm_Classes;
00144         if ( !classes ) {
00145             classes = sm_Classes = new TClasses;
00146         }
00147     }
00148     return *classes;
00149 }
00150 
00151 inline
00152 CClassTypeInfoBase::TClassesById& CClassTypeInfoBase::ClassesById(void)
00153 {
00154     TClassesById* classes = sm_ClassesById;
00155     if ( !classes ) {
00156         CMutexGuard GUARD(s_ClassInfoMutex);
00157         classes = sm_ClassesById;
00158         if ( !classes ) {
00159             const TClasses& cc = Classes();
00160             auto_ptr<TClassesById> keep(classes = new TClassesById);
00161             ITERATE ( TClasses, i , cc ) {
00162                 const CClassTypeInfoBase* info = *i;
00163                 if ( info->GetId() != typeid(bool) ) {
00164                     if ( !classes->insert(
00165                         TClassesById::value_type(&info->GetId(),
00166                                                  info)).second ) {
00167                         NCBI_THROW(CSerialException,eInvalidData,
00168                                    string("duplicate class id: ")+
00169                                    info->GetId().name());
00170                     }
00171                 }
00172             }
00173             sm_ClassesById = keep.release();
00174         }
00175     }
00176     return *classes;
00177 }
00178 
00179 inline
00180 CClassTypeInfoBase::TClassesByName& CClassTypeInfoBase::ClassesByName(void)
00181 {
00182     TClassesByName* classes = sm_ClassesByName;
00183     if ( !classes ) {
00184         CMutexGuard GUARD(s_ClassInfoMutex);
00185         classes = sm_ClassesByName;
00186         if ( !classes ) {
00187             auto_ptr<TClassesByName> keep(classes = new TClassesByName);
00188             const TClasses& cc = Classes();
00189             ITERATE ( TClasses, i, cc ) {
00190                 const CClassTypeInfoBase* info = *i;
00191                 if ( !info->GetName().empty() ) {
00192                     classes->insert
00193                         (TClassesByName::value_type(info->GetName(), info));
00194                 }
00195             }
00196             sm_ClassesByName = keep.release();
00197         }
00198     }
00199     return *classes;
00200 }
00201 
00202 void CClassTypeInfoBase::Register(void)
00203 {
00204     CMutexGuard GUARD(s_ClassInfoMutex);
00205     delete sm_ClassesById;
00206     sm_ClassesById = 0;
00207     delete sm_ClassesByName;
00208     sm_ClassesByName = 0;
00209     Classes().insert(this);
00210 }
00211 
00212 void CClassTypeInfoBase::Deregister(void)
00213 {
00214     CMutexGuard GUARD(s_ClassInfoMutex);
00215     delete sm_ClassesById;
00216     sm_ClassesById = 0;
00217     delete sm_ClassesByName;
00218     sm_ClassesByName = 0;
00219     Classes().erase(this);
00220     if (Classes().size() == 0) {
00221         delete sm_Classes;
00222         sm_Classes = 0;
00223     }
00224 }
00225 
00226 TTypeInfo CClassTypeInfoBase::GetClassInfoById(const type_info& id)
00227 {
00228     TClassesById& types = ClassesById();
00229     TClassesById::iterator i = types.find(&id);
00230     if ( i == types.end() ) {
00231         string msg("class not found: ");
00232         msg += id.name();
00233         NCBI_THROW(CSerialException,eInvalidData, msg);
00234     }
00235     return i->second;
00236 }
00237 
00238 TTypeInfo CClassTypeInfoBase::GetClassInfoByName(const string& name)
00239 {
00240     TClassesByName& classes = ClassesByName();
00241     pair<TClassesByName::iterator, TClassesByName::iterator> i =
00242         classes.equal_range(name);
00243     if (  i.first == i.second ) {
00244         NCBI_THROW_FMT(CSerialException, eInvalidData,
00245                        "class not found: "<<name);
00246     }
00247     if ( --i.second != i.first ) {
00248         // multiple types with the same name
00249         const CClassTypeInfoBase* t1 = i.first->second;
00250         const CClassTypeInfoBase* t2 = i.second->second;
00251         NCBI_THROW_FMT
00252             (CSerialException, eInvalidData,
00253              "ambiguous class name: "<<t1->GetName()<<
00254              " ("<<t1->GetModuleName()<<"&"<<t2->GetModuleName()<<")");
00255     }
00256     return i.first->second;
00257 }
00258 
00259 void CClassTypeInfoBase::GetRegisteredModuleNames(
00260     CClassTypeInfoBase::TRegModules& modules)
00261 {
00262     modules.clear();
00263     CMutexGuard GUARD(s_ClassInfoMutex);
00264     if (sm_Modules) {
00265         modules.insert(sm_Modules->begin(), sm_Modules->end());
00266     }
00267 }
00268 
00269 void CClassTypeInfoBase::GetRegisteredClassNames(
00270     const string& module, CClassTypeInfoBase::TRegClasses& names)
00271 {
00272     names.clear();
00273     CMutexGuard GUARD(s_ClassInfoMutex);
00274     TClasses& cc = Classes();
00275     ITERATE ( TClasses, i , cc ) {
00276         const CClassTypeInfoBase* info = *i;
00277         if (info->GetModuleName() == module) {
00278             names.insert( info->GetName());
00279         }
00280     }
00281 }
00282 
00283 void CClassTypeInfoBase::RegisterModule(const string& module)
00284 {
00285     CMutexGuard GUARD(s_ClassInfoMutex);
00286     if (!sm_Modules) {
00287         sm_Modules = new set<string>;
00288     }
00289     sm_Modules->insert(module);
00290 }
00291 
00292 const CObject* CClassTypeInfoBase::GetCObjectPtr(TConstObjectPtr objectPtr) const
00293 {
00294     if ( IsCObject() ) {
00295         return static_cast<const CObject*>(objectPtr);
00296     }
00297     return 0;
00298 }
00299 
00300 CTypeInfo::EMayContainType
00301 CClassTypeInfoBase::GetMayContainType(TTypeInfo typeInfo) const
00302 {
00303     CMutexGuard GUARD(GetTypeInfoMutex());
00304     TContainedTypes* cache = m_ContainedTypes.get();
00305     if ( !cache ) {
00306         m_ContainedTypes.reset(cache = new TContainedTypes);
00307     }
00308     pair<TContainedTypes::iterator, bool> ins =
00309         cache->insert(TContainedTypes::value_type(typeInfo,
00310                                                   eMayContainType_recursion));
00311     if ( !ins.second ) {
00312         return ins.first->second;
00313     }
00314 
00315     static int recursion_level = 0;
00316     ++recursion_level;
00317     EMayContainType ret;
00318     try {
00319         ret = CalcMayContainType(typeInfo);
00320         --recursion_level;
00321         if ( ret == eMayContainType_recursion ) {
00322             if ( recursion_level == 0 ) {
00323                 ins.first->second = ret = eMayContainType_no;
00324             }
00325             else {
00326                 cache->erase(ins.first);
00327             }
00328         }
00329         else {
00330             ins.first->second = ret;
00331         }
00332     }
00333     catch ( ... ) {
00334         --recursion_level;
00335         cache->erase(ins.first);
00336         throw;
00337     }
00338     return ret;
00339 }
00340 
00341 CTypeInfo::EMayContainType
00342 CClassTypeInfoBase::CalcMayContainType(TTypeInfo typeInfo) const
00343 {
00344     EMayContainType ret = eMayContainType_no;
00345     // check members
00346     for ( TMemberIndex i = GetItems().FirstIndex(),
00347               last = GetItems().LastIndex(); i <= last; ++i ) {
00348         EMayContainType contains = GetItems().GetItemInfo(i)->GetTypeInfo()->
00349             IsOrMayContainType(typeInfo);
00350         if ( contains == eMayContainType_yes ) {
00351             return contains;
00352         }
00353         if ( contains == eMayContainType_recursion ) {
00354             ret = contains;
00355         }
00356     }
00357     return ret;
00358 }
00359 
00360 class CPreReadHook : public CReadObjectHook
00361 {
00362     typedef CReadObjectHook CParent;
00363 public:
00364     typedef CClassTypeInfoBase::TPreReadFunction TPreReadFunction;
00365 
00366     CPreReadHook(TPreReadFunction func);
00367 
00368     void ReadObject(CObjectIStream& in, const CObjectInfo& object);
00369 
00370 private:
00371     TPreReadFunction m_PreRead;
00372 };
00373 
00374 CPreReadHook::CPreReadHook(TPreReadFunction func)
00375     : m_PreRead(func)
00376 {
00377 }
00378 
00379 void CPreReadHook::ReadObject(CObjectIStream& in,
00380                                const CObjectInfo& object)
00381 {
00382     m_PreRead(object.GetTypeInfo(), object.GetObjectPtr());
00383     object.GetTypeInfo()->DefaultReadData(in, object.GetObjectPtr());
00384 }
00385 
00386 class CPostReadHook : public CReadObjectHook
00387 {
00388     typedef CReadObjectHook CParent;
00389 public:
00390     typedef CClassTypeInfoBase::TPostReadFunction TPostReadFunction;
00391 
00392     CPostReadHook(TPostReadFunction func);
00393 
00394     void ReadObject(CObjectIStream& in, const CObjectInfo& object);
00395 
00396 private:
00397     TPostReadFunction m_PostRead;
00398 };
00399 
00400 CPostReadHook::CPostReadHook(TPostReadFunction func)
00401     : m_PostRead(func)
00402 {
00403 }
00404 
00405 void CPostReadHook::ReadObject(CObjectIStream& in,
00406                                const CObjectInfo& object)
00407 {
00408     object.GetTypeInfo()->DefaultReadData(in, object.GetObjectPtr());
00409     m_PostRead(object.GetTypeInfo(), object.GetObjectPtr());
00410 }
00411 
00412 class CPreWriteHook : public CWriteObjectHook
00413 {
00414     typedef CWriteObjectHook CParent;
00415 public:
00416     typedef CClassTypeInfoBase::TPreWriteFunction TPreWriteFunction;
00417 
00418     CPreWriteHook(TPreWriteFunction func);
00419 
00420     void WriteObject(CObjectOStream& out, const CConstObjectInfo& object);
00421 
00422 private:
00423     TPreWriteFunction m_PreWrite;
00424 };
00425 
00426 CPreWriteHook::CPreWriteHook(TPreWriteFunction func)
00427     : m_PreWrite(func)
00428 {
00429 }
00430 
00431 void CPreWriteHook::WriteObject(CObjectOStream& out,
00432                                 const CConstObjectInfo& object)
00433 {
00434     m_PreWrite(object.GetTypeInfo(), object.GetObjectPtr());
00435     object.GetTypeInfo()->DefaultWriteData(out, object.GetObjectPtr());
00436 }
00437 
00438 class CPostWriteHook : public CWriteObjectHook
00439 {
00440     typedef CWriteObjectHook CParent;
00441 public:
00442     typedef CClassTypeInfoBase::TPostWriteFunction TPostWriteFunction;
00443 
00444     CPostWriteHook(TPostWriteFunction func);
00445 
00446     void WriteObject(CObjectOStream& out, const CConstObjectInfo& object);
00447 
00448 private:
00449     TPostWriteFunction m_PostWrite;
00450 };
00451 
00452 CPostWriteHook::CPostWriteHook(TPostWriteFunction func)
00453     : m_PostWrite(func)
00454 {
00455 }
00456 
00457 void CPostWriteHook::WriteObject(CObjectOStream& out,
00458                                 const CConstObjectInfo& object)
00459 {
00460     object.GetTypeInfo()->DefaultWriteData(out, object.GetObjectPtr());
00461     m_PostWrite(object.GetTypeInfo(), object.GetObjectPtr());
00462 }
00463 
00464 void CClassTypeInfoBase::SetPreReadFunction(TPreReadFunction func)
00465 {
00466     SetGlobalReadHook(new CPreReadHook(func));
00467 }
00468 
00469 void CClassTypeInfoBase::SetPostReadFunction(TPostReadFunction func)
00470 {
00471     SetGlobalReadHook(new CPostReadHook(func));
00472 }
00473 
00474 void CClassTypeInfoBase::SetPreWriteFunction(TPreWriteFunction func)
00475 {
00476     SetGlobalWriteHook(new CPreWriteHook(func));
00477 }
00478 
00479 void CClassTypeInfoBase::SetPostWriteFunction(TPostWriteFunction func)
00480 {
00481     SetGlobalWriteHook(new CPostWriteHook(func));
00482 }
00483 
00484 END_NCBI_SCOPE
Modified on Wed Sep 17 18:24:19 2014 by modify_doxy.py rev. 426318