src/serial/classinfob.cpp

Search Toolkit Book for infob_8cpp-source

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

Generated on Sun Dec 6 22:43:10 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:21:14 2009 by modify_doxy.py rev. 173732