memberlist.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: memberlist.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:40:33  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: memberlist.cpp,v 1000.2 2004/06/01 19:40:33 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   !!! PUT YOUR DESCRIPTION HERE !!!
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: memberlist.cpp,v $
  41. * Revision 1000.2  2004/06/01 19:40:33  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  43. *
  44. * Revision 1.36  2004/05/17 21:03:02  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.35  2004/01/08 17:37:04  gouriano
  48. * Added possibility to search for container members, that could be empty
  49. *
  50. * Revision 1.34  2003/03/26 16:14:22  vasilche
  51. * Removed TAB symbols. Some formatting.
  52. *
  53. * Revision 1.33  2003/03/10 18:54:25  gouriano
  54. * use new structured exceptions (based on CException)
  55. *
  56. * Revision 1.32  2002/12/26 19:28:52  gouriano
  57. * elaborated FindDeep method
  58. *
  59. * Revision 1.31  2002/11/26 22:12:52  gouriano
  60. * elaborated FindDeep to handle more complex elements
  61. *
  62. * Revision 1.30  2002/11/20 21:23:56  gouriano
  63. * added FindDeep method - to search the whole class type tree
  64. *
  65. * Revision 1.29  2002/09/19 20:05:44  vasilche
  66. * Safe initialization of static mutexes
  67. *
  68. * Revision 1.28  2002/09/06 13:25:36  vasilche
  69. * Fixed cast error on Sun
  70. *
  71. * Revision 1.27  2002/09/05 21:21:44  vasilche
  72. * Added mutex for items map
  73. *
  74. * Revision 1.26  2002/01/24 23:30:01  vakatov
  75. * Note for ourselves that the bug workaround "BW_010" is not needed
  76. * anymore, and we should get rid of it in about half a year
  77. *
  78. * Revision 1.25  2001/10/15 19:48:26  vakatov
  79. * Use two #if's instead of "#if ... && ..." as KAI cannot handle #if x == y
  80. *
  81. * Revision 1.24  2001/09/04 17:04:02  vakatov
  82. * Extended workaround for the SUN Forte 6 Update 1 compiler internal bug
  83. * to all higher versions of the compiler, as Update 2 also has this the
  84. * same bug!
  85. *
  86. * Revision 1.23  2001/08/20 20:23:19  vakatov
  87. * Workaround for the SUN Forte 6 Update 1 compiler internal bug.
  88. *
  89. * Revision 1.22  2000/10/03 17:22:43  vasilche
  90. * Reduced header dependency.
  91. * Reduced size of debug libraries on WorkShop by 3 times.
  92. * Fixed tag allocation for parent classes.
  93. * Fixed CObject allocation/deallocation in streams.
  94. * Moved instantiation of several templates in separate source file.
  95. *
  96. * Revision 1.21  2000/09/28 16:29:41  vasilche
  97. * Reverted back changes in processing parent classes.
  98. * It causes exceptions with map container.
  99. *
  100. * Revision 1.20  2000/09/26 17:38:21  vasilche
  101. * Fixed incomplete choiceptr implementation.
  102. * Removed temporary comments.
  103. *
  104. * Revision 1.19  2000/09/18 20:00:22  vasilche
  105. * Separated CVariantInfo and CMemberInfo.
  106. * Implemented copy hooks.
  107. * All hooks now are stored in CTypeInfo/CMemberInfo/CVariantInfo.
  108. * Most type specific functions now are implemented via function pointers instead of virtual functions.
  109. *
  110. * Revision 1.18  2000/09/01 13:16:15  vasilche
  111. * Implemented class/container/choice iterators.
  112. * Implemented CObjectStreamCopier for copying data without loading into memory.
  113. *
  114. * Revision 1.17  2000/08/15 19:44:47  vasilche
  115. * Added Read/Write hooks:
  116. * CReadObjectHook/CWriteObjectHook for objects of specified type.
  117. * CReadClassMemberHook/CWriteClassMemberHook for specified members.
  118. * CReadChoiceVariantHook/CWriteChoiceVariant for specified choice variants.
  119. * CReadContainerElementHook/CWriteContainerElementsHook for containers.
  120. *
  121. * Revision 1.16  2000/07/03 18:42:44  vasilche
  122. * Added interface to typeinfo via CObjectInfo and CConstObjectInfo.
  123. * Reduced header dependency.
  124. *
  125. * Revision 1.15  2000/06/16 16:31:19  vasilche
  126. * Changed implementation of choices and classes info to allow use of the same classes in generated and user written classes.
  127. *
  128. * Revision 1.14  2000/06/07 19:45:58  vasilche
  129. * Some code cleaning.
  130. * Macros renaming in more clear way.
  131. * BEGIN_NAMED_*_INFO, ADD_*_MEMBER, ADD_NAMED_*_MEMBER.
  132. *
  133. * Revision 1.13  2000/06/01 19:07:03  vasilche
  134. * Added parsing of XML data.
  135. *
  136. * Revision 1.12  2000/05/24 20:08:47  vasilche
  137. * Implemented XML dump.
  138. *
  139. * Revision 1.11  2000/04/10 21:01:49  vasilche
  140. * Fixed Erase for map/set.
  141. * Added iteratorbase.hpp header for basic internal classes.
  142. *
  143. * Revision 1.10  2000/04/10 18:01:57  vasilche
  144. * Added Erase() for STL types in type iterators.
  145. *
  146. * Revision 1.9  2000/03/29 15:55:27  vasilche
  147. * Added two versions of object info - CObjectInfo and CConstObjectInfo.
  148. * Added generic iterators by class -
  149. *  CTypeIterator<class>, CTypeConstIterator<class>,
  150. *  CStdTypeIterator<type>, CStdTypeConstIterator<type>,
  151. *  CObjectsIterator and CObjectsConstIterator.
  152. *
  153. * Revision 1.8  2000/02/01 21:47:22  vasilche
  154. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  155. * Added buffering to CObjectIStreamAsn.
  156. * Removed CMemberInfo subclasses.
  157. * Added support for DEFAULT/OPTIONAL members.
  158. *
  159. * Revision 1.7  2000/01/10 19:46:39  vasilche
  160. * Fixed encoding/decoding of REAL type.
  161. * Fixed encoding/decoding of StringStore.
  162. * Fixed encoding/decoding of NULL type.
  163. * Fixed error reporting.
  164. * Reduced object map (only classes).
  165. *
  166. * Revision 1.6  1999/10/04 16:22:16  vasilche
  167. * Fixed bug with old ASN.1 structures.
  168. *
  169. * Revision 1.5  1999/07/22 19:40:55  vasilche
  170. * Fixed bug with complex object graphs (pointers to members of other objects).
  171. *
  172. * Revision 1.4  1999/07/14 18:58:08  vasilche
  173. * Fixed ASN.1 types/field naming.
  174. *
  175. * Revision 1.3  1999/07/07 18:18:32  vasilche
  176. * Fixed some bugs found by MS VC++
  177. *
  178. * Revision 1.2  1999/07/01 17:55:29  vasilche
  179. * Implemented ASN.1 binary write.
  180. *
  181. * Revision 1.1  1999/06/30 16:04:52  vasilche
  182. * Added support for old ASN.1 structures.
  183. *
  184. * ===========================================================================
  185. */
  186. #include <ncbi_pch.hpp>
  187. #include <corelib/ncbistd.hpp>
  188. #include <serial/exception.hpp>
  189. #include <serial/memberlist.hpp>
  190. #include <serial/memberid.hpp>
  191. #include <serial/member.hpp>
  192. #include <serial/classinfob.hpp>
  193. #include <serial/continfo.hpp>
  194. #include <serial/ptrinfo.hpp>
  195. #include <corelib/ncbiutil.hpp>
  196. #include <corelib/ncbithr.hpp>
  197. BEGIN_NCBI_SCOPE
  198. CItemsInfo::CItemsInfo(void)
  199.     : m_ZeroTagIndex(kInvalidMember)
  200. {
  201. }
  202. CItemsInfo::~CItemsInfo(void)
  203. {
  204. // NOTE:  This compiler bug was fixed by Jan 24 2002, test passed with:
  205. //           CC: Sun WorkShop 6 update 2 C++ 5.3 Patch 111685-03 2001/10/19
  206. //        We leave the workaround here for maybe half a year (for other guys).
  207. #if defined(NCBI_COMPILER_WORKSHOP)
  208. // We have to use two #if's here because KAI C++ cannot handle #if foo == bar
  209. #  if (NCBI_COMPILER_VERSION == 530)
  210.     // BW_010::  to workaround (already reported to SUN, CASE ID 62563729)
  211.     //           internal bug of the SUN Forte 6 Update 1 and Update 2 compiler
  212.     (void) atoi("5");
  213. #  endif
  214. #endif
  215. }
  216. void CItemsInfo::AddItem(CItemInfo* item)
  217. {
  218.     // clear cached maps (byname and bytag)
  219.     m_ItemsByName.reset(0);
  220.     m_ZeroTagIndex = kInvalidMember;
  221.     m_ItemsByTag.reset(0);
  222.     m_ItemsByOffset.reset(0);
  223.     // update item's tag
  224.     if ( !item->GetId().HaveExplicitTag() ) {
  225.         TTag tag = CMemberId::eFirstTag;
  226.         if ( !Empty() ) {
  227.             TMemberIndex lastIndex = LastIndex();
  228.             const CItemInfo* lastItem = GetItemInfo(lastIndex);
  229.             if ( lastIndex != FirstIndex() ||
  230.                  !lastItem->GetId().HaveParentTag() )
  231.                 tag = lastItem->GetId().GetTag() + 1;
  232.         }
  233.         item->GetId().SetTag(tag, false);
  234.     }
  235.     // add item
  236.     m_Items.push_back(AutoPtr<CItemInfo>(item));
  237.     item->m_Index = LastIndex();
  238. }
  239. DEFINE_STATIC_FAST_MUTEX(s_ItemsMapMutex);
  240. const CItemsInfo::TItemsByName& CItemsInfo::GetItemsByName(void) const
  241. {
  242.     TItemsByName* items = m_ItemsByName.get();
  243.     if ( !items ) {
  244.         CFastMutexGuard GUARD(s_ItemsMapMutex);
  245.         items = m_ItemsByName.get();
  246.         if ( !items ) {
  247.             auto_ptr<TItemsByName> keep(items = new TItemsByName);
  248.             for ( CIterator i(*this); i.Valid(); ++i ) {
  249.                 const CItemInfo* itemInfo = GetItemInfo(i);
  250.                 const string& name = itemInfo->GetId().GetName();
  251.                 if ( !items->insert(TItemsByName::value_type(name, *i)).second ) {
  252.                     if ( !name.empty() )
  253.                         NCBI_THROW(CSerialException,eInvalidData,
  254.                             string("duplicate member name: ")+name);
  255.                 }
  256.             }
  257.             m_ItemsByName = keep;
  258.         }
  259.     }
  260.     return *items;
  261. }
  262. const CItemsInfo::TItemsByOffset&
  263. CItemsInfo::GetItemsByOffset(void) const
  264. {
  265.     TItemsByOffset* items = m_ItemsByOffset.get();
  266.     if ( !items ) {
  267.         CFastMutexGuard GUARD(s_ItemsMapMutex);
  268.         items = m_ItemsByOffset.get();
  269.         if ( !items ) {
  270.             // create map
  271.             auto_ptr<TItemsByOffset> keep(items = new TItemsByOffset);
  272.             // fill map 
  273.             for ( CIterator i(*this); i.Valid(); ++i ) {
  274.                 const CItemInfo* itemInfo = GetItemInfo(i);
  275.                 size_t offset = itemInfo->GetOffset();
  276.                 if ( !items->insert(TItemsByOffset::value_type(offset, *i)).second ) {
  277.                     NCBI_THROW(CSerialException,eInvalidData, "conflict member offset");
  278.                 }
  279.             }
  280. /*
  281.         // check overlaps
  282.         size_t nextOffset = 0;
  283.         for ( TItemsByOffset::const_iterator m = members->begin();
  284.               m != members->end(); ++m ) {
  285.             size_t offset = m->first;
  286.             if ( offset < nextOffset ) {
  287.                 NCBI_THROW(CSerialException,eInvalidData,
  288.                              "overlapping members");
  289.             }
  290.             nextOffset = offset + m_Members[m->second]->GetSize();
  291.         }
  292. */
  293.             m_ItemsByOffset = keep;
  294.         }
  295.     }
  296.     return *items;
  297. }
  298. pair<TMemberIndex, const CItemsInfo::TItemsByTag*>
  299. CItemsInfo::GetItemsByTagInfo(void) const
  300. {
  301.     typedef pair<TMemberIndex, const TItemsByTag*> TReturn;
  302.     TReturn ret(m_ZeroTagIndex, m_ItemsByTag.get());
  303.     if ( ret.first == kInvalidMember && ret.second == 0 ) {
  304.         CFastMutexGuard GUARD(s_ItemsMapMutex);
  305.         ret = TReturn(m_ZeroTagIndex, m_ItemsByTag.get());
  306.         if ( ret.first == kInvalidMember && ret.second == 0 ) {
  307.             {
  308.                 CIterator i(*this);
  309.                 if ( i.Valid() ) {
  310.                     ret.first = *i-GetItemInfo(i)->GetId().GetTag();
  311.                     for ( ++i; i.Valid(); ++i ) {
  312.                         if ( ret.first != *i-GetItemInfo(i)->GetId().GetTag() ) {
  313.                             ret.first = kInvalidMember;
  314.                             break;
  315.                         }
  316.                     }
  317.                 }
  318.             }
  319.             if ( ret.first != kInvalidMember ) {
  320.                 m_ZeroTagIndex = ret.first;
  321.             }
  322.             else {
  323.                 auto_ptr<TItemsByTag> items(new TItemsByTag);
  324.                 for ( CIterator i(*this); i.Valid(); ++i ) {
  325.                     const CItemInfo* itemInfo = GetItemInfo(i);
  326.                     TTag tag = itemInfo->GetId().GetTag();
  327.                     if ( !items->insert(TItemsByTag::value_type(tag, *i)).second ) {
  328.                         NCBI_THROW(CSerialException,eInvalidData, "duplicate member tag");
  329.                     }
  330.                 }
  331.                 ret.second = items.get();
  332.                 m_ItemsByTag = items;
  333.             }
  334.         }
  335.     }
  336.     return ret;
  337. }
  338. TMemberIndex CItemsInfo::Find(const CLightString& name) const
  339. {
  340.     const TItemsByName& items = GetItemsByName();
  341.     TItemsByName::const_iterator i = items.find(name);
  342.     if ( i == items.end() )
  343.         return kInvalidMember;
  344.     return i->second;
  345. }
  346. TMemberIndex CItemsInfo::FindDeep(const CLightString& name) const
  347. {
  348.     TMemberIndex ind = Find(name);
  349.     if (ind != kInvalidMember) {
  350.         return ind;
  351.     }
  352.     for (CIterator item(*this); item.Valid(); ++item) {
  353.         const CItemInfo* info = GetItemInfo(item);
  354.         const CMemberId& id = info->GetId();
  355.         if (!id.IsAttlist() && id.HasNotag()) {
  356.             const CTypeInfo* type;
  357.             for (type = info->GetTypeInfo();;) {
  358.                 if (type->GetTypeFamily() == eTypeFamilyContainer) {
  359.                     const CContainerTypeInfo* cont =
  360.                         dynamic_cast<const CContainerTypeInfo*>(type);
  361.                     if (cont) {
  362.                         type = cont->GetElementType();
  363.                     }
  364.                 } else if (type->GetTypeFamily() == eTypeFamilyPointer) {
  365.                     const CPointerTypeInfo* ptr =
  366.                         dynamic_cast<const CPointerTypeInfo*>(type);
  367.                     if (ptr) {
  368.                         type = ptr->GetPointedType();
  369.                     }
  370.                 } else {
  371.                     break;
  372.                 }
  373.             }
  374.             const CClassTypeInfoBase* classType =
  375.                 dynamic_cast<const CClassTypeInfoBase*>(type);
  376.             if (classType) {
  377.                 if (classType->GetItems().FindDeep(name) != kInvalidMember) {
  378.                     return *item;
  379.                 }
  380.             }
  381.         }
  382.     }
  383.     return kInvalidMember;
  384. }
  385. TMemberIndex CItemsInfo::FindEmpty(void) const
  386. {
  387.     for (CIterator item(*this); item.Valid(); ++item) {
  388.         const CItemInfo* info = GetItemInfo(item);
  389.         if (info->GetId().IsAttlist()) {
  390.             continue;
  391.         }
  392.         const CTypeInfo* type;
  393.         for (type = info->GetTypeInfo();;) {
  394.             if (type->GetTypeFamily() == eTypeFamilyContainer) {
  395.                 // container may be empty
  396.                 return *item;
  397.             } else if (type->GetTypeFamily() == eTypeFamilyPointer) {
  398.                 const CPointerTypeInfo* ptr =
  399.                     dynamic_cast<const CPointerTypeInfo*>(type);
  400.                 if (ptr) {
  401.                     type = ptr->GetPointedType();
  402.                 }
  403.             } else {
  404.                 break;
  405.             }
  406.         }
  407.     }
  408.     return kInvalidMember;
  409. }
  410. TMemberIndex CItemsInfo::Find(const CLightString& name, TMemberIndex pos) const
  411. {
  412.     for ( CIterator i(*this, pos); i.Valid(); ++i ) {
  413.         if ( name == GetItemInfo(i)->GetId().GetName() )
  414.             return *i;
  415.     }
  416.     return kInvalidMember;
  417. }
  418. TMemberIndex CItemsInfo::Find(TTag tag) const
  419. {
  420.     pair<TMemberIndex, const TItemsByTag*> info = GetItemsByTagInfo();
  421.     if ( info.first != kInvalidMember ) {
  422.         TMemberIndex index = tag + m_ZeroTagIndex;
  423.         if ( index < FirstIndex() || index > LastIndex() )
  424.             return kInvalidMember;
  425.         return index;
  426.     }
  427.     else {
  428.         TItemsByTag::const_iterator mi = info.second->find(tag);
  429.         if ( mi == info.second->end() )
  430.             return kInvalidMember;
  431.         return mi->second;
  432.     }
  433. }
  434. TMemberIndex CItemsInfo::Find(TTag tag, TMemberIndex pos) const
  435. {
  436.     pair<TMemberIndex, const TItemsByTag*> info = GetItemsByTagInfo();
  437.     if ( info.first != kInvalidMember ) {
  438.         TMemberIndex index = tag + m_ZeroTagIndex;
  439.         if ( index < pos || index > LastIndex() )
  440.             return kInvalidMember;
  441.         return index;
  442.     }
  443.     else {
  444.         for ( CIterator i(*this, pos); i.Valid(); ++i ) {
  445.             if ( GetItemInfo(i)->GetId().GetTag() == tag )
  446.                 return *i;
  447.         }
  448.         return kInvalidMember;
  449.     }
  450. }
  451. END_NCBI_SCOPE