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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: asntypes.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:39:44  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.65
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: asntypes.cpp,v 1000.2 2004/06/01 19:39:44 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: asntypes.cpp,v $
  41. * Revision 1000.2  2004/06/01 19:39:44  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.65
  43. *
  44. * Revision 1.65  2004/05/17 21:03:02  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.64  2004/03/25 15:57:08  gouriano
  48. * Added possibility to copy and compare serial object non-recursively
  49. *
  50. * Revision 1.63  2003/10/24 15:54:28  grichenk
  51. * Removed or blocked exceptions in destructors
  52. *
  53. * Revision 1.62  2003/08/14 20:03:58  vasilche
  54. * Avoid memory reallocation when reading over preallocated object.
  55. * Simplified CContainerTypeInfo iterators interface.
  56. *
  57. * Revision 1.61  2003/05/16 18:02:17  gouriano
  58. * revised exception error messages
  59. *
  60. * Revision 1.60  2003/03/26 16:14:22  vasilche
  61. * Removed TAB symbols. Some formatting.
  62. *
  63. * Revision 1.59  2003/03/10 18:54:24  gouriano
  64. * use new structured exceptions (based on CException)
  65. *
  66. * Revision 1.58  2002/10/25 15:23:16  vasilche
  67. * Fixed warning about name hiding.
  68. *
  69. * Revision 1.57  2002/10/25 15:15:45  vasilche
  70. * Fixed check for NCBI C toolkit.
  71. *
  72. * Revision 1.56  2002/10/25 14:49:27  vasilche
  73. * NCBI C Toolkit compatibility code extracted to libxcser library.
  74. * Serial streams flags names were renamed to fXxx.
  75. *
  76. * Names of flags
  77. *
  78. * Revision 1.55  2002/08/30 16:22:21  vasilche
  79. * Removed excessive _TRACEs
  80. *
  81. * Revision 1.54  2001/05/17 15:07:04  lavr
  82. * Typos corrected
  83. *
  84. * Revision 1.53  2000/12/12 14:28:01  vasilche
  85. * Changed the way arguments are processed.
  86. *
  87. * Revision 1.52  2000/11/07 17:25:39  vasilche
  88. * Fixed encoding of XML:
  89. *     removed unnecessary apostrophes in OCTET STRING
  90. *     removed unnecessary content in NULL
  91. * Added module names to CTypeInfo and CEnumeratedTypeValues
  92. *
  93. * Revision 1.51  2000/10/20 15:51:36  vasilche
  94. * Fixed data error processing.
  95. * Added interface for constructing container objects directly into output stream.
  96. * object.hpp, object.inl and object.cpp were split to
  97. * objectinfo.*, objecttype.*, objectiter.* and objectio.*.
  98. *
  99. * Revision 1.50  2000/10/17 18:45:32  vasilche
  100. * Added possibility to turn off object cross reference detection in
  101. * CObjectIStream and CObjectOStream.
  102. *
  103. * Revision 1.49  2000/10/13 20:22:52  vasilche
  104. * Fixed warnings on 64 bit compilers.
  105. * Fixed missing typename in templates.
  106. *
  107. * Revision 1.48  2000/10/13 16:28:37  vasilche
  108. * Reduced header dependency.
  109. * Avoid use of templates with virtual methods.
  110. * Reduced amount of different maps used.
  111. * All this lead to smaller compiled code size (libraries and programs).
  112. *
  113. * Revision 1.47  2000/10/03 17:22:41  vasilche
  114. * Reduced header dependency.
  115. * Reduced size of debug libraries on WorkShop by 3 times.
  116. * Fixed tag allocation for parent classes.
  117. * Fixed CObject allocation/deallocation in streams.
  118. * Moved instantiation of several templates in separate source file.
  119. *
  120. * Revision 1.46  2000/09/18 20:00:20  vasilche
  121. * Separated CVariantInfo and CMemberInfo.
  122. * Implemented copy hooks.
  123. * All hooks now are stored in CTypeInfo/CMemberInfo/CVariantInfo.
  124. * Most type specific functions now are implemented via function pointers instead of virtual functions.
  125. *
  126. * Revision 1.45  2000/09/01 13:16:13  vasilche
  127. * Implemented class/container/choice iterators.
  128. * Implemented CObjectStreamCopier for copying data without loading into memory.
  129. *
  130. * Revision 1.44  2000/08/15 19:44:46  vasilche
  131. * Added Read/Write hooks:
  132. * CReadObjectHook/CWriteObjectHook for objects of specified type.
  133. * CReadClassMemberHook/CWriteClassMemberHook for specified members.
  134. * CReadChoiceVariantHook/CWriteChoiceVariant for specified choice variants.
  135. * CReadContainerElementHook/CWriteContainerElementsHook for containers.
  136. *
  137. * Revision 1.43  2000/07/03 18:42:41  vasilche
  138. * Added interface to typeinfo via CObjectInfo and CConstObjectInfo.
  139. * Reduced header dependency.
  140. *
  141. * Revision 1.42  2000/06/16 20:01:25  vasilche
  142. * Avoid use of unexpected_exception() which is unimplemented on Mac.
  143. *
  144. * Revision 1.41  2000/06/16 16:31:17  vasilche
  145. * Changed implementation of choices and classes info to allow use of the same classes in generated and user written classes.
  146. *
  147. * Revision 1.40  2000/06/07 19:45:57  vasilche
  148. * Some code cleaning.
  149. * Macros renaming in more clear way.
  150. * BEGIN_NAMED_*_INFO, ADD_*_MEMBER, ADD_NAMED_*_MEMBER.
  151. *
  152. * Revision 1.39  2000/05/24 20:08:45  vasilche
  153. * Implemented XML dump.
  154. *
  155. * Revision 1.38  2000/05/09 16:38:37  vasilche
  156. * CObject::GetTypeInfo now moved to CObjectGetTypeInfo::GetTypeInfo to reduce possible errors.
  157. * Added write context to CObjectOStream.
  158. * Inlined most of methods of helping class Member, Block, ByteBlock etc.
  159. *
  160. * Revision 1.37  2000/03/31 21:38:20  vasilche
  161. * Renamed First() -> FirstNode(), Next() -> NextNode() to avoid name conflict.
  162. *
  163. * Revision 1.36  2000/03/29 15:55:26  vasilche
  164. * Added two versions of object info - CObjectInfo and CConstObjectInfo.
  165. * Added generic iterators by class -
  166. *  CTypeIterator<class>, CTypeConstIterator<class>,
  167. *  CStdTypeIterator<type>, CStdTypeConstIterator<type>,
  168. *  CObjectsIterator and CObjectsConstIterator.
  169. *
  170. * Revision 1.35  2000/03/14 14:42:29  vasilche
  171. * Fixed error reporting.
  172. *
  173. * Revision 1.34  2000/03/07 14:06:20  vasilche
  174. * Added stream buffering to ASN.1 binary input.
  175. * Optimized class loading/storing.
  176. * Fixed bugs in processing OPTIONAL fields.
  177. * Added generation of reference counted objects.
  178. *
  179. * Revision 1.33  2000/02/17 20:02:42  vasilche
  180. * Added some standard serialization exceptions.
  181. * Optimized text/binary ASN.1 reading.
  182. * Fixed wrong encoding of StringStore in ASN.1 binary format.
  183. * Optimized logic of object collection.
  184. *
  185. * Revision 1.32  2000/02/01 21:47:21  vasilche
  186. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  187. * Added buffering to CObjectIStreamAsn.
  188. * Removed CMemberInfo subclasses.
  189. * Added support for DEFAULT/OPTIONAL members.
  190. *
  191. * Revision 1.31  1999/12/28 18:55:49  vasilche
  192. * Reduced size of compiled object files:
  193. * 1. avoid inline or implicit virtual methods (especially destructors).
  194. * 2. avoid std::string's methods usage in inline methods.
  195. * 3. avoid string literals ("xxx") in inline methods.
  196. *
  197. * Revision 1.30  1999/12/17 19:05:01  vasilche
  198. * Simplified generation of GetTypeInfo methods.
  199. *
  200. * Revision 1.29  1999/10/04 19:39:45  vasilche
  201. * Fixed bug in CObjectOStreamBinary.
  202. * Start using of BSRead/BSWrite.
  203. * Added ASNCALL macro for prototypes of old ASN.1 functions.
  204. *
  205. * Revision 1.28  1999/10/04 16:22:15  vasilche
  206. * Fixed bug with old ASN.1 structures.
  207. *
  208. * Revision 1.27  1999/09/29 22:36:33  vakatov
  209. * Dont forget to #include ncbistd.hpp before #ifdef HAVE_NCBI_C...
  210. *
  211. * Revision 1.26  1999/09/24 18:55:58  vasilche
  212. * ASN.1 types will not be compiled is we don't have NCBI toolkit.
  213. *
  214. * Revision 1.25  1999/09/24 18:19:17  vasilche
  215. * Removed dependency on NCBI toolkit.
  216. *
  217. * Revision 1.24  1999/09/23 21:16:07  vasilche
  218. * Removed dependence on asn.h
  219. *
  220. * Revision 1.23  1999/09/23 20:25:03  vasilche
  221. * Added support HAVE_NCBI_C
  222. *
  223. * Revision 1.22  1999/09/23 18:56:57  vasilche
  224. * Fixed bugs with overloaded methods in objistr*.hpp & objostr*.hpp
  225. *
  226. * Revision 1.21  1999/09/22 20:11:54  vasilche
  227. * Modified for compilation on IRIX native c++ compiler.
  228. *
  229. * Revision 1.20  1999/09/14 18:54:14  vasilche
  230. * Fixed bugs detected by gcc & egcs.
  231. * Removed unneeded includes.
  232. *
  233. * Revision 1.19  1999/08/31 17:50:08  vasilche
  234. * Implemented several macros for specific data types.
  235. * Added implicit members.
  236. * Added multimap and set.
  237. *
  238. * Revision 1.18  1999/08/16 16:08:30  vasilche
  239. * Added ENUMERATED type.
  240. *
  241. * Revision 1.17  1999/08/13 20:22:57  vasilche
  242. * Fixed lot of bugs in datatool
  243. *
  244. * Revision 1.16  1999/08/13 15:53:49  vasilche
  245. * C++ analog of asntool: datatool
  246. *
  247. * Revision 1.15  1999/07/21 20:02:53  vasilche
  248. * Added embedding of ASN.1 binary output from ToolKit to our binary format.
  249. * Fixed bugs with storing pointers into binary ASN.1
  250. *
  251. * Revision 1.14  1999/07/21 18:05:09  vasilche
  252. * Fixed OPTIONAL attribute for ASN.1 structures.
  253. *
  254. * Revision 1.13  1999/07/20 18:23:08  vasilche
  255. * Added interface to old ASN.1 routines.
  256. * Added fixed choice of subclasses to use for pointers.
  257. *
  258. * Revision 1.12  1999/07/19 15:50:30  vasilche
  259. * Added interface to old ASN.1 routines.
  260. * Added naming of key/value in STL map.
  261. *
  262. * Revision 1.11  1999/07/15 16:54:48  vasilche
  263. * Implemented vector<X> & vector<char> as special case.
  264. *
  265. * Revision 1.10  1999/07/13 20:54:05  vasilche
  266. * Fixed minor bugs.
  267. *
  268. * Revision 1.9  1999/07/13 20:18:15  vasilche
  269. * Changed types naming.
  270. *
  271. * Revision 1.8  1999/07/09 20:27:05  vasilche
  272. * Fixed some bugs
  273. *
  274. * Revision 1.7  1999/07/09 16:32:54  vasilche
  275. * Added OCTET STRING write/read.
  276. *
  277. * Revision 1.6  1999/07/07 19:59:03  vasilche
  278. * Reduced amount of data allocated on heap
  279. * Cleaned ASN.1 structures info
  280. *
  281. * Revision 1.5  1999/07/07 18:18:32  vasilche
  282. * Fixed some bugs found by MS VC++
  283. *
  284. * Revision 1.4  1999/07/02 21:31:51  vasilche
  285. * Implemented reading from ASN.1 binary format.
  286. *
  287. * Revision 1.3  1999/07/01 17:55:25  vasilche
  288. * Implemented ASN.1 binary write.
  289. *
  290. * Revision 1.2  1999/06/30 18:54:58  vasilche
  291. * Fixed some errors under MSVS
  292. *
  293. * Revision 1.1  1999/06/30 16:04:46  vasilche
  294. * Added support for old ASN.1 structures.
  295. *
  296. * ===========================================================================
  297. */
  298. #include <ncbi_pch.hpp>
  299. #include <corelib/ncbistd.hpp>
  300. #if HAVE_NCBI_C
  301. #include <corelib/ncbiutil.hpp>
  302. #include <serial/asntypes.hpp>
  303. #include <serial/autoptrinfo.hpp>
  304. #include <serial/classinfo.hpp>
  305. #include <serial/objistr.hpp>
  306. #include <serial/objostr.hpp>
  307. #include <serial/objistrasnb.hpp>
  308. #include <serial/objostrasnb.hpp>
  309. #include <serial/objcopy.hpp>
  310. #include <serial/classinfob.hpp>
  311. #include <serial/typemap.hpp>
  312. #include <asn.h>
  313. BEGIN_NCBI_SCOPE
  314. static inline
  315. void* Alloc(size_t size)
  316. {
  317.     return NotNull(calloc(size, 1));
  318. }
  319. template<class T>
  320. static inline
  321. T* Alloc(T*& ptr)
  322. {
  323.     return ptr = static_cast<T*>(Alloc(sizeof(T)));
  324. }
  325. static CTypeInfoMap s_SequenceOfTypeInfo_map;
  326. TTypeInfo CSequenceOfTypeInfo::GetTypeInfo(TTypeInfo base)
  327. {
  328.     return s_SequenceOfTypeInfo_map.GetTypeInfo(base, &CreateTypeInfo);
  329. }
  330. CTypeInfo* CSequenceOfTypeInfo::CreateTypeInfo(TTypeInfo base)
  331. {
  332.     return new CSequenceOfTypeInfo(base);
  333. }
  334. CSequenceOfTypeInfo::CSequenceOfTypeInfo(TTypeInfo type, bool randomOrder)
  335.     : CParent(sizeof(TObjectType), type, randomOrder)
  336. {
  337.     InitSequenceOfTypeInfo();
  338. }
  339. CSequenceOfTypeInfo::CSequenceOfTypeInfo(const char* name,
  340.                                          TTypeInfo type, bool randomOrder)
  341.     : CParent(sizeof(TObjectType), name, type, randomOrder)
  342. {
  343.     InitSequenceOfTypeInfo();
  344. }
  345. CSequenceOfTypeInfo::CSequenceOfTypeInfo(const string& name,
  346.                                          TTypeInfo type, bool randomOrder)
  347.     : CParent(sizeof(TObjectType), name, type, randomOrder)
  348. {
  349.     InitSequenceOfTypeInfo();
  350. }
  351. static
  352. size_t GetFirstItemOffset(const CItemsInfo& items)
  353. {
  354.     TPointerOffsetType offset = INT_MAX;
  355.     for ( CItemsInfo::CIterator i(items); i.Valid(); ++i ) {
  356.         const CItemInfo* itemInfo = items.GetItemInfo(i);
  357.         offset = min(offset, itemInfo->GetOffset());
  358.     }
  359.     return offset;
  360. }
  361. class CSequenceOfTypeInfoFunctionsCI
  362. {
  363. public:
  364.     typedef CContainerTypeInfo::CConstIterator TIterator; 
  365.     static const CSequenceOfTypeInfo* GetType(const TIterator& iter)
  366.         {
  367.             return CTypeConverter<CSequenceOfTypeInfo>::SafeCast(iter.GetContainerType());
  368.         }
  369.     static bool InitIterator(TIterator& iter)
  370.         {
  371.             TObjectPtr nodePtr =
  372.                 GetType(iter)->FirstNode(iter.GetContainerPtr());
  373.             iter.m_IteratorData = nodePtr;
  374.             return nodePtr != 0;
  375.         }
  376.     static void ReleaseIterator(TIterator& )
  377.         {
  378.         }
  379.     static void CopyIterator(TIterator& dst,
  380.                              const TIterator& src)
  381.         {
  382.             dst.m_IteratorData = src.m_IteratorData;
  383.         }
  384.     static bool NextElement(TIterator& iter)
  385.         {
  386.             TObjectPtr nodePtr = GetType(iter)->NextNode(iter.m_IteratorData);
  387.             iter.m_IteratorData = nodePtr;
  388.             return nodePtr != 0;
  389.         }
  390.     static TConstObjectPtr GetElementPtr(const TIterator& iter)
  391.         {
  392.             return GetType(iter)->Data(iter.m_IteratorData);
  393.         }
  394. };
  395. class CSequenceOfTypeInfoFunctionsI
  396. {
  397. public:
  398.     typedef CContainerTypeInfo::CIterator TIterator; 
  399.     static const CSequenceOfTypeInfo* GetType(const TIterator& iter)
  400.         {
  401.             return CTypeConverter<CSequenceOfTypeInfo>::SafeCast(iter.GetContainerType());
  402.         }
  403.     static bool InitIterator(TIterator& iter)
  404.         {
  405.             TObjectPtr* nodePtrPtr =
  406.                 &GetType(iter)->FirstNode(iter.GetContainerPtr());
  407.             iter.m_IteratorData = nodePtrPtr;
  408.             return *nodePtrPtr != 0;
  409.         }
  410.     static void ReleaseIterator(TIterator& )
  411.         {
  412.         }
  413.     static void CopyIterator(TIterator& dst, const TIterator& src)
  414.         {
  415.             dst.m_IteratorData = src.m_IteratorData;
  416.         }
  417.     static bool NextElement(TIterator& iter)
  418.         {
  419.             TObjectPtr* nodePtrPtr =
  420.                 &GetType(iter)->NextNode(*(TObjectPtr*)iter.m_IteratorData);
  421.             iter.m_IteratorData = nodePtrPtr;
  422.             return *nodePtrPtr != 0;
  423.         }
  424.     static TObjectPtr GetElementPtr(const TIterator& iter)
  425.         {
  426.             return GetType(iter)->Data(*(TObjectPtr*)iter.m_IteratorData);
  427.         }
  428.     static bool EraseElement(TIterator& iter)
  429.         {
  430.             const CSequenceOfTypeInfo* type = GetType(iter);
  431.             TObjectPtr* nodePtrPtr = (TObjectPtr*)iter.m_IteratorData;
  432.             TObjectPtr nodePtr = *nodePtrPtr;
  433.             TObjectPtr nextNodePtr = type->NextNode(nodePtr);
  434.             *nodePtrPtr = nextNodePtr;
  435.             type->DeleteNode(nodePtr);
  436.             return nextNodePtr != 0;
  437.         }
  438.     static void EraseAllElements(TIterator& iter)
  439.         {
  440.             const CSequenceOfTypeInfo* type = GetType(iter);
  441.             TObjectPtr* nodePtrPtr = (TObjectPtr*)iter.m_IteratorData;
  442.             TObjectPtr nodePtr = *nodePtrPtr;
  443.             *nodePtrPtr = 0;
  444.             while ( nodePtr ) {
  445.                 TObjectPtr nextNodePtr = type->NextNode(nodePtr);
  446.                 type->DeleteNode(nodePtr);
  447.                 nodePtr = nextNodePtr;
  448.             }
  449.         }
  450. };
  451. class CSequenceOfTypeInfoFunctions
  452. {
  453. public:
  454.     static void ReadSequence(CObjectIStream& in,
  455.                              TTypeInfo containerType,
  456.                              TObjectPtr containerPtr)
  457.         {
  458.             const CSequenceOfTypeInfo* seqType =
  459.                 CTypeConverter<CSequenceOfTypeInfo>::SafeCast(containerType);
  460.             BEGIN_OBJECT_FRAME_OF2(in, eFrameArray, seqType);
  461.             in.BeginContainer(seqType);
  462.             TTypeInfo elementType = seqType->GetElementType();
  463.             BEGIN_OBJECT_FRAME_OF2(in, eFrameArrayElement, elementType);
  464.             TObjectPtr* nextNodePtr = &seqType->FirstNode(containerPtr);
  465.             while ( in.BeginContainerElement(elementType) ) {
  466.                 // get current node pointer
  467.                 TObjectPtr node = *nextNodePtr;
  468.         
  469.                 // create node
  470.                 _ASSERT(!node);
  471.                 node = *nextNodePtr = seqType->CreateNode();
  472.                 // read node data
  473.                 in.ReadObject(seqType->Data(node), elementType);
  474.                 // save next node for next read
  475.                 nextNodePtr = &seqType->NextNode(node);
  476.         
  477.                 in.EndContainerElement();
  478.             }
  479.             END_OBJECT_FRAME_OF(in);
  480.             in.EndContainer();
  481.             END_OBJECT_FRAME_OF(in);
  482.         }
  483. };
  484. void CSequenceOfTypeInfo::InitSequenceOfTypeInfo(void)
  485. {
  486.     TTypeInfo type = GetElementType();
  487.     const CAutoPointerTypeInfo* ptrInfo =
  488.         dynamic_cast<const CAutoPointerTypeInfo*>(type);
  489.     if ( ptrInfo != 0 ) {
  490.         // data type is auto_ptr
  491.         TTypeInfo asnType = ptrInfo->GetPointedType();
  492.         if ( asnType->GetTypeFamily() == eTypeFamilyChoice ) {
  493.             // CHOICE
  494.             SetChoiceNext();
  495.             m_ElementType = asnType;
  496.         }
  497.         else if ( asnType->GetTypeFamily() == eTypeFamilyClass ) {
  498.             // user types
  499.             const CClassTypeInfo* classType =
  500.                 CTypeConverter<CClassTypeInfo>::SafeCast(asnType);
  501.             if ( GetFirstItemOffset(classType->GetItems()) < sizeof(void*) ) {
  502.                 CNcbiOstrstream msg;
  503.                 msg << "CSequenceOfTypeInfo: incompatible type: " <<
  504.                     type->GetName() << ": " << typeid(*type).name() <<
  505.                     " size: " << type->GetSize();
  506.                 NCBI_THROW(CSerialException,eInvalidData, CNcbiOstrstreamToString(msg));
  507.             }
  508.             m_NextOffset = 0;
  509.             m_DataOffset = 0;
  510.             m_ElementType = asnType;
  511.         }
  512.         else if ( asnType->GetSize() <= sizeof(dataval) ) {
  513.             // standard types and SET/SEQUENCE OF
  514.             SetValNodeNext();
  515.             m_ElementType = asnType;
  516.         }
  517.         else {
  518. /*
  519.             _ASSERT(type->GetSize() <= sizeof(dataval));
  520.             SetValNodeNext();
  521. */
  522.             CNcbiOstrstream msg;
  523.             msg << "CSequenceOfTypeInfo: incompatible type: " <<
  524.                 type->GetName() << ": " << typeid(*type).name() <<
  525.                 " size: " << type->GetSize();
  526.             NCBI_THROW(CSerialException,eInvalidData, CNcbiOstrstreamToString(msg));
  527.         }
  528.     }
  529.     else if ( type->GetSize() <= sizeof(dataval) ) {
  530.         // SEQUENCE OF, SET OF or primitive types
  531.         SetValNodeNext();
  532.     }
  533.     else {
  534.         CNcbiOstrstream msg;
  535.         msg << "CSequenceOfTypeInfo: incompatible type: " <<
  536.             type->GetName() << ": " << typeid(*type).name() <<
  537.             " size: " << type->GetSize();
  538.         NCBI_THROW(CSerialException,eInvalidData, CNcbiOstrstreamToString(msg));
  539.     }
  540.     {
  541.         typedef CSequenceOfTypeInfoFunctions TFunc;
  542.         SetReadFunction(&TFunc::ReadSequence);
  543.     }
  544.     {
  545.         typedef CSequenceOfTypeInfoFunctionsCI TFunc;
  546.         SetConstIteratorFunctions(&TFunc::InitIterator, &TFunc::ReleaseIterator,
  547.                                   &TFunc::CopyIterator, &TFunc::NextElement,
  548.                                   &TFunc::GetElementPtr);
  549.     }
  550.     {
  551.         typedef CSequenceOfTypeInfoFunctionsI TFunc;
  552.         SetIteratorFunctions(&TFunc::InitIterator, &TFunc::ReleaseIterator,
  553.                              &TFunc::CopyIterator, &TFunc::NextElement,
  554.                              &TFunc::GetElementPtr,
  555.                              &TFunc::EraseElement, &TFunc::EraseAllElements);
  556.     }
  557. }
  558. void CSequenceOfTypeInfo::SetChoiceNext(void)
  559. {
  560.     m_NextOffset = offsetof(valnode, next);
  561.     m_DataOffset = 0;
  562. }
  563. void CSequenceOfTypeInfo::SetValNodeNext(void)
  564. {
  565.     m_NextOffset = offsetof(valnode, next);
  566.     m_DataOffset = offsetof(valnode, data);
  567. }
  568. TObjectPtr CSequenceOfTypeInfo::CreateNode(void) const
  569. {
  570.     if ( m_DataOffset == 0 ) {
  571.         _ASSERT(m_NextOffset == 0 || m_NextOffset == offsetof(valnode, next));
  572.         return GetElementType()->Create();
  573.     }
  574.     else {
  575.         _ASSERT(m_NextOffset == offsetof(valnode, next));
  576.         _ASSERT(m_DataOffset == offsetof(valnode, data));
  577.         return Alloc(sizeof(valnode));
  578.     }
  579. }
  580. void CSequenceOfTypeInfo::DeleteNode(TObjectPtr node) const
  581. {
  582.     if ( m_DataOffset == 0 ) {
  583.         _ASSERT(m_NextOffset == 0 || m_NextOffset == offsetof(valnode, next));
  584.         GetElementType()->Delete(node);
  585.     }
  586.     else {
  587.         _ASSERT(m_NextOffset == offsetof(valnode, next));
  588.         _ASSERT(m_DataOffset == offsetof(valnode, data));
  589.         Free(node);
  590.     }
  591. }
  592. bool CSequenceOfTypeInfo::IsDefault(TConstObjectPtr object) const
  593. {
  594.     return FirstNode(object) == 0;
  595. }
  596. void CSequenceOfTypeInfo::SetDefault(TObjectPtr dst) const
  597. {
  598.     FirstNode(dst) = 0;
  599. }
  600. void CSequenceOfTypeInfo::Assign(TObjectPtr dst, TConstObjectPtr src,
  601.                                  ESerialRecursionMode how) const
  602. {
  603.     src = FirstNode(src);
  604.     if ( src == 0 ) {
  605.         FirstNode(dst) = 0;
  606.         return;
  607.     }
  608.     TTypeInfo dataType = GetElementType();
  609.     dst = FirstNode(dst) = CreateNode();
  610.     dataType->Assign(Data(dst), Data(src), how);
  611.     while ( (src = NextNode(src)) != 0 ) {
  612.         dst = NextNode(dst) = CreateNode();
  613.         dataType->Assign(Data(dst), Data(src), how);
  614.     }
  615. }
  616. static CTypeInfoMap s_SetOfTypeInfo_map;
  617. TTypeInfo CSetOfTypeInfo::GetTypeInfo(TTypeInfo base)
  618. {
  619.     return s_SetOfTypeInfo_map.GetTypeInfo(base, &CreateTypeInfo);
  620. }
  621. CTypeInfo* CSetOfTypeInfo::CreateTypeInfo(TTypeInfo base)
  622. {
  623.     return new CSetOfTypeInfo(base);
  624. }
  625. CSetOfTypeInfo::CSetOfTypeInfo(TTypeInfo type)
  626.     : CParent(type, true)
  627. {
  628. }
  629. CSetOfTypeInfo::CSetOfTypeInfo(const char* name, TTypeInfo type)
  630.     : CParent(name, type, true)
  631. {
  632. }
  633. CSetOfTypeInfo::CSetOfTypeInfo(const string& name, TTypeInfo type)
  634.     : CParent(name, type, true)
  635. {
  636. }
  637. COctetStringTypeInfo::COctetStringTypeInfo(void)
  638.     : CParent(sizeof(TObjectType), ePrimitiveValueOctetString)
  639. {
  640.     SetReadFunction(&ReadOctetString);
  641.     SetWriteFunction(&WriteOctetString);
  642.     SetCopyFunction(&CopyOctetString);
  643.     SetSkipFunction(&SkipOctetString);
  644. }
  645. bool COctetStringTypeInfo::IsDefault(TConstObjectPtr object) const
  646. {
  647.     return Get(object)->totlen == 0;
  648. }
  649. bool COctetStringTypeInfo::Equals(TConstObjectPtr obj1, TConstObjectPtr obj2,
  650.                                   ESerialRecursionMode) const
  651. {
  652.     bytestore* bs1 = Get(obj1);
  653.     bytestore* bs2 = Get(obj2);
  654.     if ( bs1 == 0 || bs2 == 0 )
  655.         return bs1 == bs2;
  656.     Int4 len = BSLen(bs1);
  657.     if ( len != BSLen(bs2) )
  658.         return false;
  659.     
  660.     BSSeek(bs1, 0, SEEK_SET);
  661.     BSSeek(bs2, 0, SEEK_SET);
  662.     char buff1[1024], buff2[1024];
  663.     while ( len > 0 ) {
  664.         Int4 chunk = Int4(sizeof(buff1));
  665.         if ( chunk > len )
  666.             chunk = len;
  667.         BSRead(bs1, buff1, chunk);
  668.         BSRead(bs2, buff2, chunk);
  669.         if ( memcmp(buff1, buff2, chunk) != 0 )
  670.             return false;
  671.         len -= chunk;
  672.     }
  673.     return true;
  674. }
  675. void COctetStringTypeInfo::SetDefault(TObjectPtr dst) const
  676. {
  677.     BSFree(Get(dst));
  678.     Get(dst) = BSNew(0);
  679. }
  680. void COctetStringTypeInfo::Assign(TObjectPtr dst, TConstObjectPtr src,
  681.                                   ESerialRecursionMode) const
  682. {
  683.     if ( Get(src) == 0 ) {
  684.         NCBI_THROW(CSerialException,eInvalidData, "null bytestore pointer");
  685.     }
  686.     BSFree(Get(dst));
  687.     Get(dst) = BSDup(Get(src));
  688. }
  689. void COctetStringTypeInfo::ReadOctetString(CObjectIStream& in,
  690.                                            TTypeInfo /*objectType*/,
  691.                                            TObjectPtr objectPtr)
  692. {
  693.     CObjectIStream::ByteBlock block(in);
  694.     BSFree(Get(objectPtr));
  695.     char buffer[1024];
  696.     Int4 count = Int4(block.Read(buffer, sizeof(buffer)));
  697.     bytestore* bs = Get(objectPtr) = BSNew(count);
  698.     BSWrite(bs, buffer, count);
  699.     while ( (count = Int4(block.Read(buffer, sizeof(buffer)))) != 0 ) {
  700.         BSWrite(bs, buffer, count);
  701.     }
  702.     block.End();
  703. }
  704. void COctetStringTypeInfo::WriteOctetString(CObjectOStream& out,
  705.                                             TTypeInfo /*objectType*/,
  706.                                             TConstObjectPtr objectPtr)
  707. {
  708.     bytestore* bs = const_cast<bytestore*>(Get(objectPtr));
  709.     if ( bs == 0 )
  710.         out.ThrowError(out.fIllegalCall, "null bytestore pointer");
  711.     Int4 len = BSLen(bs);
  712.     CObjectOStream::ByteBlock block(out, len);
  713.     BSSeek(bs, 0, SEEK_SET);
  714.     char buff[1024];
  715.     while ( len > 0 ) {
  716.         Int4 chunk = Int4(sizeof(buff));
  717.         if ( chunk > len )
  718.             chunk = len;
  719.         BSRead(bs, buff, chunk);
  720.         block.Write(buff, chunk);
  721.         len -= chunk;
  722.     }
  723.     block.End();
  724. }
  725. void COctetStringTypeInfo::CopyOctetString(CObjectStreamCopier& copier,
  726.                                            TTypeInfo /*objectType*/)
  727. {
  728.     copier.CopyByteBlock();
  729. }
  730. void COctetStringTypeInfo::SkipOctetString(CObjectIStream& in,
  731.                                            TTypeInfo /*objectType*/)
  732. {
  733.     in.SkipByteBlock();
  734. }
  735. void COctetStringTypeInfo::GetValueOctetString(TConstObjectPtr objectPtr,
  736.                                                vector<char>& value) const
  737. {
  738.     bytestore* bs = const_cast<bytestore*>(Get(objectPtr));
  739.     if ( bs == 0 ) {
  740.         NCBI_THROW(CSerialException,eInvalidData, "null bytestore pointer");
  741.     }
  742.     Int4 len = BSLen(bs);
  743.     value.resize(len);
  744.     BSSeek(bs, 0, SEEK_SET);
  745.     BSRead(bs, &value.front(), len);
  746. }
  747. void COctetStringTypeInfo::SetValueOctetString(TObjectPtr objectPtr,
  748.                                                const vector<char>& value) const
  749. {
  750.     Int4 count = Int4(value.size());
  751.     bytestore* bs = Get(objectPtr) = BSNew(count);
  752.     BSWrite(bs, const_cast<char*>(&value.front()), count);
  753. }
  754. TTypeInfo COctetStringTypeInfo::GetTypeInfo(void)
  755. {
  756.     static TTypeInfo typeInfo = 0;
  757.     if ( !typeInfo )
  758.         typeInfo = new COctetStringTypeInfo();
  759.     return typeInfo;
  760. }
  761. COldAsnTypeInfo::COldAsnTypeInfo(const char* name,
  762.                                  TAsnNewProc newProc,
  763.                                  TAsnFreeProc freeProc,
  764.                                  TAsnReadProc readProc,
  765.                                  TAsnWriteProc writeProc)
  766.     : CParent(sizeof(TObjectType), name, ePrimitiveValueSpecial),
  767.       m_NewProc(newProc), m_FreeProc(freeProc),
  768.       m_ReadProc(readProc), m_WriteProc(writeProc)
  769. {
  770.     SetReadFunction(&ReadOldAsnStruct);
  771.     SetWriteFunction(&WriteOldAsnStruct);
  772. }
  773. COldAsnTypeInfo::COldAsnTypeInfo(const string& name,
  774.                                  TAsnNewProc newProc,
  775.                                  TAsnFreeProc freeProc,
  776.                                  TAsnReadProc readProc,
  777.                                  TAsnWriteProc writeProc)
  778.     : CParent(sizeof(TObjectType), name, ePrimitiveValueSpecial),
  779.       m_NewProc(newProc), m_FreeProc(freeProc),
  780.       m_ReadProc(readProc), m_WriteProc(writeProc)
  781. {
  782.     SetReadFunction(&ReadOldAsnStruct);
  783.     SetWriteFunction(&WriteOldAsnStruct);
  784. }
  785. bool COldAsnTypeInfo::IsDefault(TConstObjectPtr object) const
  786. {
  787.     return Get(object) == 0;
  788. }
  789. bool COldAsnTypeInfo::Equals(TConstObjectPtr object1, TConstObjectPtr object2,
  790.                              ESerialRecursionMode) const
  791. {
  792.     return Get(object1) == 0 && Get(object2) == 0;
  793. }
  794. void COldAsnTypeInfo::SetDefault(TObjectPtr dst) const
  795. {
  796.     Get(dst) = 0;
  797. }
  798. void COldAsnTypeInfo::Assign(TObjectPtr , TConstObjectPtr,
  799.                              ESerialRecursionMode ) const
  800. {
  801.     NCBI_THROW(CSerialException,eInvalidData, "cannot assign non default value");
  802. }
  803. void COldAsnTypeInfo::ReadOldAsnStruct(CObjectIStream& in,
  804.                                        TTypeInfo objectType,
  805.                                        TObjectPtr objectPtr)
  806. {
  807.     const COldAsnTypeInfo* oldAsnType =
  808.         CTypeConverter<COldAsnTypeInfo>::SafeCast(objectType);
  809.     CObjectIStream::AsnIo io(in, oldAsnType->GetName());
  810.     if ( (Get(objectPtr) = oldAsnType->m_ReadProc(io, 0)) == 0 )
  811.         in.ThrowError(in.fFail, "read fault");
  812.     io.End();
  813. }
  814. void COldAsnTypeInfo::WriteOldAsnStruct(CObjectOStream& out,
  815.                                         TTypeInfo objectType,
  816.                                         TConstObjectPtr objectPtr)
  817. {
  818.     const COldAsnTypeInfo* oldAsnType =
  819.         CTypeConverter<COldAsnTypeInfo>::SafeCast(objectType);
  820.     CObjectOStream::AsnIo io(out, oldAsnType->GetName());
  821.     if ( !oldAsnType->m_WriteProc(Get(objectPtr), io, 0) )
  822.         out.ThrowError(out.fFail, "write fault");
  823.     io.End();
  824. }
  825. // CObjectOStream, CObjectIStream, and corresponding AsnIo
  826. extern "C" {
  827.     Int2 LIBCALLBACK WriteAsn(Pointer object, CharPtr data, Uint2 length)
  828.     {
  829.         if ( !object || !data )
  830.             return -1;
  831.     
  832.         static_cast<CObjectOStream::AsnIo*>(object)->Write(data, length);
  833.         return length;
  834.     }
  835.     Int2 LIBCALLBACK ReadAsn(Pointer object, CharPtr data, Uint2 length)
  836.     {
  837.         if ( !object || !data )
  838.             return -1;
  839.         CObjectIStream::AsnIo* asnio =
  840.             static_cast<CObjectIStream::AsnIo*>(object);
  841.         return Uint2(asnio->Read(data, length));
  842.     }
  843. }
  844. CObjectOStream::AsnIo::AsnIo(CObjectOStream& out, const string& rootTypeName)
  845.     : m_Stream(out), m_RootTypeName(rootTypeName), m_Ended(false), m_Count(0)
  846. {
  847.     Int1 flags = ASNIO_OUT;
  848.     ESerialDataFormat format = out.GetDataFormat();
  849.     if ( format == eSerial_AsnText )
  850.         flags |= ASNIO_TEXT;
  851.     else if ( format == eSerial_AsnBinary )
  852.         flags |= ASNIO_BIN;
  853.     else
  854.         out.ThrowError(out.fIllegalCall,
  855.                        "incompatible stream format - must be ASN.1 (text or binary)");
  856.     m_AsnIo = AsnIoNew(flags, 0, this, 0, WriteAsn);
  857.     if ( format == eSerial_AsnText ) {
  858.         // adjust indent level and buffer
  859.         size_t indent = out.m_Output.GetIndentLevel();
  860.         m_AsnIo->indent_level = Int1(indent);
  861.         size_t max_indent = m_AsnIo->max_indent;
  862.         if ( indent >= max_indent ) {
  863.             Boolean* tmp = m_AsnIo->first;
  864.             m_AsnIo->first = (BoolPtr) MemNew((sizeof(Boolean) * (indent + 10)));
  865.             MemCopy(m_AsnIo->first, tmp, (size_t)(sizeof(Boolean) * max_indent));
  866.             MemFree(tmp);
  867.             m_AsnIo->max_indent = Int1(indent);
  868.         }
  869.     }
  870. }
  871. void CObjectOStream::AsnIo::End(void)
  872. {
  873.     _ASSERT(!m_Ended);
  874.     if ( GetStream().InGoodState() ) {
  875.         AsnIoClose(*this);
  876.         m_Ended = true;
  877.     }
  878. }
  879. CObjectOStream::AsnIo::~AsnIo(void)
  880. {
  881.     if ( !m_Ended ) {
  882.         try {
  883.             GetStream().Unended("AsnIo write error");
  884.         }
  885.         catch (...) {
  886.             ERR_POST("AsnIo write error");
  887.         }
  888.     }
  889. }
  890. CObjectOStream& CObjectOStream::AsnIo::GetStream(void) const
  891. {
  892.     return m_Stream;
  893. }
  894. CObjectOStream::AsnIo::operator asnio*(void)
  895. {
  896.     return m_AsnIo;
  897. }
  898. asnio* CObjectOStream::AsnIo::operator->(void)
  899. {
  900.     return m_AsnIo;
  901. }
  902. const string& CObjectOStream::AsnIo::GetRootTypeName(void) const
  903. {
  904.     return m_RootTypeName;
  905. }
  906. void CObjectOStream::AsnIo::Write(const char* data, size_t length)
  907. {
  908.     if ( GetStream().GetDataFormat() == eSerial_AsnText ) {
  909.         if ( m_Count == 0 ) {
  910.             // dirty hack to skip structure name with '::='
  911.             const char* p = (const char*)memchr(data, ':', length);
  912.             if ( p && p[1] == ':' && p[2] == '=' ) {
  913.                 // check type name
  914.                 const char* beg = data;
  915.                 const char* end = p;
  916.                 while ( beg < end && isspace(beg[0]) )
  917.                     beg++;
  918.                 while ( end > beg && isspace(end[-1]) )
  919.                     end--;
  920.                 if ( string(beg, end) != GetRootTypeName() ) {
  921.                     ERR_POST("AsnWrite: wrong ASN.1 type name: is ""
  922.                              << string(beg, end) << "", must be ""
  923.                              << GetRootTypeName() << """);
  924.                 }
  925.                 // skip header
  926.                 size_t skip = p + 3 - data;
  927.                 _TRACE(Warning <<
  928.                        "AsnWrite: skipping "" << string(data, skip) << """);
  929.                 data += skip;
  930.                 length -= skip;
  931.             }
  932.             else {
  933.                 ERR_POST("AsnWrite: no "Asn-Type ::=" header  (data=""
  934.                          << data << "")");
  935.             }
  936.             m_Count = 1;
  937.         }
  938.         GetStream().m_Output.PutString(data, length);
  939.     }
  940.     else {
  941.         if ( length == 0 )
  942.             return;
  943.         CObjectOStreamAsnBinary& out =
  944.             static_cast<CObjectOStreamAsnBinary&>(GetStream());
  945. #if CHECK_STREAM_INTEGRITY
  946.         _TRACE("WriteBytes: " << length);
  947.         if ( out.m_CurrentTagState != out.eTagStart )
  948.             out.ThrowError(out.fIllegalCall,
  949.                 string("AsnWrite only allowed at tag start: data= ")+data);
  950.         if ( out.m_CurrentPosition + length > out.m_CurrentTagLimit )
  951.             out.ThrowError(out.fIllegalCall,
  952.                 string("tag DATA overflow: data= ")+data);
  953.         out.m_CurrentPosition += length;
  954. #endif
  955.         out.m_Output.PutString(data, length);
  956.     }
  957. }
  958. CObjectIStream::AsnIo::AsnIo(CObjectIStream& in, const string& rootTypeName)
  959.     : m_Stream(in), m_Ended(false),
  960.       m_RootTypeName(rootTypeName), m_Count(0)
  961. {
  962.     Int1 flags = ASNIO_IN;
  963.     ESerialDataFormat format = in.GetDataFormat();
  964.     if ( format == eSerial_AsnText )
  965.         flags |= ASNIO_TEXT;
  966.     else if ( format == eSerial_AsnBinary )
  967.         flags |= ASNIO_BIN;
  968.     else
  969.         in.ThrowError(in.fIllegalCall,
  970.             "incompatible stream format - must be ASN.1 (text or binary)");
  971.     m_AsnIo = AsnIoNew(flags, 0, this, ReadAsn, 0);
  972.     if ( format == eSerial_AsnBinary ) {
  973. #if CHECK_STREAM_INTEGRITY
  974.         CObjectIStreamAsnBinary& sin =
  975.             static_cast<CObjectIStreamAsnBinary&>(in);
  976.         if ( sin.m_CurrentTagState != sin.eTagStart ) {
  977.             in.ThrowError(in.fIllegalCall,
  978.                 string("double tag read: rootTypeName= ")+ rootTypeName);
  979.         }
  980. #endif
  981.     }
  982. }
  983. void CObjectIStream::AsnIo::End(void)
  984. {
  985.     _ASSERT(!m_Ended);
  986.     if ( GetStream().InGoodState() ) {
  987.         AsnIoClose(*this);
  988.         m_Ended = true;
  989.     }
  990. }
  991. CObjectIStream::AsnIo::~AsnIo(void)
  992. {
  993.     if ( !m_Ended )
  994.         GetStream().Unended("AsnIo read error");
  995. }
  996. CObjectIStream& CObjectIStream::AsnIo::GetStream(void) const
  997. {
  998.     return m_Stream;
  999. }
  1000. CObjectIStream::AsnIo::operator asnio*(void)
  1001. {
  1002.     return m_AsnIo;
  1003. }
  1004. asnio* CObjectIStream::AsnIo::operator->(void)
  1005. {
  1006.     return m_AsnIo;
  1007. }
  1008. const string& CObjectIStream::AsnIo::GetRootTypeName(void) const
  1009. {
  1010.     return m_RootTypeName;
  1011. }
  1012. size_t CObjectIStream::AsnIo::Read(char* data, size_t length)
  1013. {
  1014.     if ( GetStream().GetDataFormat() == eSerial_AsnText ) {
  1015.         size_t count = 0;
  1016.         if ( m_Count == 0 ) {
  1017.             // dirty hack to add structure name with '::='
  1018.             const string& name = GetRootTypeName();
  1019.             SIZE_TYPE nameLength = name.size();
  1020.             count = nameLength + 3;
  1021.             if ( length < count ) {
  1022.                 GetStream().ThrowError(GetStream().fFail,
  1023.                     string("buffer too small to put structure name in: name= ")
  1024.                     + name);
  1025.             }
  1026.             memcpy(data, name.data(), nameLength);
  1027.             data[nameLength] = ':';
  1028.             data[nameLength + 1] = ':';
  1029.             data[nameLength + 2] = '=';
  1030.             data += count;
  1031.             length -= count;
  1032.             m_Count = 1;
  1033.         }
  1034.         return count + GetStream().m_Input.ReadLine(data, length);
  1035.     }
  1036.     else {
  1037.         *data = GetStream().m_Input.GetChar();
  1038.         return 1;
  1039.     }
  1040. }
  1041. END_NCBI_SCOPE
  1042. #endif