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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: objistrasnb.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:40:59  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.70
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: objistrasnb.cpp,v 1000.3 2004/06/01 19:40:59 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: objistrasnb.cpp,v $
  41. * Revision 1000.3  2004/06/01 19:40:59  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.70
  43. *
  44. * Revision 1.70  2004/05/17 21:03:03  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.69  2004/03/23 15:39:23  gouriano
  48. * Added setup options for skipping unknown data members
  49. *
  50. * Revision 1.68  2004/03/16 17:48:21  gouriano
  51. * make it possible to skip unknown data members
  52. *
  53. * Revision 1.67  2003/11/26 19:59:40  vasilche
  54. * GetPosition() and GetDataFormat() methods now are implemented
  55. * in parent classes CObjectIStream and CObjectOStream to avoid
  56. * pure virtual method call in destructors.
  57. *
  58. * Revision 1.66  2003/10/15 18:00:32  vasilche
  59. * Fixed integer overflow in asn binary input stream after 2GB.
  60. * Added constructor of CObjectIStreamAsnBinary() from CByteSourceReader.
  61. *
  62. * Revision 1.65  2003/08/25 15:59:09  gouriano
  63. * added possibility to use namespaces in XML i/o streams
  64. *
  65. * Revision 1.64  2003/08/19 18:32:38  vasilche
  66. * Optimized reading and writing strings.
  67. * Avoid string reallocation when checking char values.
  68. * Try to reuse old string data when string reference counting is not working.
  69. *
  70. * Revision 1.63  2003/08/14 20:03:58  vasilche
  71. * Avoid memory reallocation when reading over preallocated object.
  72. * Simplified CContainerTypeInfo iterators interface.
  73. *
  74. * Revision 1.62  2003/08/13 15:47:45  gouriano
  75. * implemented serialization of AnyContent objects
  76. *
  77. * Revision 1.61  2003/05/22 20:10:02  gouriano
  78. * added UTF8 strings
  79. *
  80. * Revision 1.60  2003/05/16 18:02:18  gouriano
  81. * revised exception error messages
  82. *
  83. * Revision 1.59  2003/03/26 16:14:23  vasilche
  84. * Removed TAB symbols. Some formatting.
  85. *
  86. * Revision 1.58  2002/10/25 14:49:27  vasilche
  87. * NCBI C Toolkit compatibility code extracted to libxcser library.
  88. * Serial streams flags names were renamed to fXxx.
  89. *
  90. * Names of flags
  91. *
  92. * Revision 1.57  2002/01/23 21:58:31  grichenk
  93. * Fixed minor bug in log tags reader
  94. *
  95. * Revision 1.56  2002/01/17 20:52:35  grichenk
  96. * Fixed another bug in long binary tags processing
  97. *
  98. * Revision 1.55  2002/01/14 17:58:11  grichenk
  99. * Fixed long tags processing
  100. *
  101. * Revision 1.54  2001/10/17 20:41:24  grichenk
  102. * Added CObjectOStream::CharBlock class
  103. *
  104. * Revision 1.53  2001/06/07 17:12:51  grichenk
  105. * Redesigned checking and substitution of non-printable characters
  106. * in VisibleString
  107. *
  108. * Revision 1.52  2001/05/17 15:07:08  lavr
  109. * Typos corrected
  110. *
  111. * Revision 1.51  2001/01/22 23:12:57  vakatov
  112. * CObjectIStreamAsnBinary::{Read,Skip}ClassSequential() - use cur.member "pos"
  113. *
  114. * Revision 1.50  2001/01/03 15:22:26  vasilche
  115. * Fixed limited buffer size for REAL data in ASN.1 binary format.
  116. * Fixed processing non ASCII symbols in ASN.1 text format.
  117. *
  118. * Revision 1.49  2000/12/26 22:24:11  vasilche
  119. * Fixed errors of compilation on Mac.
  120. *
  121. * Revision 1.48  2000/12/15 21:29:02  vasilche
  122. * Moved some typedefs/enums from corelib/ncbistd.hpp.
  123. * Added flags to CObjectIStream/CObjectOStream: eFlagAllowNonAsciiChars.
  124. * TByte typedef replaced by Uint1.
  125. *
  126. * Revision 1.47  2000/12/15 15:38:44  vasilche
  127. * Added support of Int8 and long double.
  128. * Enum values now have type Int4 instead of long.
  129. *
  130. * Revision 1.46  2000/10/20 15:51:41  vasilche
  131. * Fixed data error processing.
  132. * Added interface for constructing container objects directly into output stream.
  133. * object.hpp, object.inl and object.cpp were split to
  134. * objectinfo.*, objecttype.*, objectiter.* and objectio.*.
  135. *
  136. * Revision 1.45  2000/10/17 18:45:34  vasilche
  137. * Added possibility to turn off object cross reference detection in
  138. * CObjectIStream and CObjectOStream.
  139. *
  140. * Revision 1.44  2000/09/29 16:18:23  vasilche
  141. * Fixed binary format encoding/decoding on 64 bit compulers.
  142. * Implemented CWeakMap<> for automatic cleaning map entries.
  143. * Added cleaning local hooks via CWeakMap<>.
  144. * Renamed ReadTypeName -> ReadFileHeader, ENoTypeName -> ENoFileHeader.
  145. * Added some user interface methods to CObjectIStream, CObjectOStream and
  146. * CObjectStreamCopier.
  147. *
  148. * Revision 1.43  2000/09/18 20:00:23  vasilche
  149. * Separated CVariantInfo and CMemberInfo.
  150. * Implemented copy hooks.
  151. * All hooks now are stored in CTypeInfo/CMemberInfo/CVariantInfo.
  152. * Most type specific functions now are implemented via function pointers instead of virtual functions.
  153. *
  154. * Revision 1.42  2000/09/01 13:16:18  vasilche
  155. * Implemented class/container/choice iterators.
  156. * Implemented CObjectStreamCopier for copying data without loading into memory.
  157. *
  158. * Revision 1.41  2000/08/15 19:44:49  vasilche
  159. * Added Read/Write hooks:
  160. * CReadObjectHook/CWriteObjectHook for objects of specified type.
  161. * CReadClassMemberHook/CWriteClassMemberHook for specified members.
  162. * CReadChoiceVariantHook/CWriteChoiceVariant for specified choice variants.
  163. * CReadContainerElementHook/CWriteContainerElementsHook for containers.
  164. *
  165. * Revision 1.40  2000/07/03 20:47:22  vasilche
  166. * Removed unused variables/functions.
  167. *
  168. * Revision 1.39  2000/07/03 20:39:56  vasilche
  169. * Fixed comments.
  170. *
  171. * Revision 1.38  2000/07/03 18:42:45  vasilche
  172. * Added interface to typeinfo via CObjectInfo and CConstObjectInfo.
  173. * Reduced header dependency.
  174. *
  175. * Revision 1.37  2000/06/16 16:31:20  vasilche
  176. * Changed implementation of choices and classes info to allow use of the same classes in generated and user written classes.
  177. *
  178. * Revision 1.36  2000/06/07 19:45:59  vasilche
  179. * Some code cleaning.
  180. * Macros renaming in more clear way.
  181. * BEGIN_NAMED_*_INFO, ADD_*_MEMBER, ADD_NAMED_*_MEMBER.
  182. *
  183. * Revision 1.35  2000/06/01 19:07:04  vasilche
  184. * Added parsing of XML data.
  185. *
  186. * Revision 1.34  2000/05/24 20:08:47  vasilche
  187. * Implemented XML dump.
  188. *
  189. * Revision 1.33  2000/05/09 16:38:39  vasilche
  190. * CObject::GetTypeInfo now moved to CObjectGetTypeInfo::GetTypeInfo to reduce possible errors.
  191. * Added write context to CObjectOStream.
  192. * Inlined most of methods of helping class Member, Block, ByteBlock etc.
  193. *
  194. * Revision 1.32  2000/04/28 16:58:13  vasilche
  195. * Added classes CByteSource and CByteSourceReader for generic reading.
  196. * Added delayed reading of choice variants.
  197. *
  198. * Revision 1.31  2000/04/13 14:50:27  vasilche
  199. * Added CObjectIStream::Open() and CObjectOStream::Open() for easier use.
  200. *
  201. * Revision 1.30  2000/03/29 15:55:28  vasilche
  202. * Added two versions of object info - CObjectInfo and CConstObjectInfo.
  203. * Added generic iterators by class -
  204. *  CTypeIterator<class>, CTypeConstIterator<class>,
  205. *  CStdTypeIterator<type>, CStdTypeConstIterator<type>,
  206. *  CObjectsIterator and CObjectsConstIterator.
  207. *
  208. * Revision 1.29  2000/03/14 14:42:31  vasilche
  209. * Fixed error reporting.
  210. *
  211. * Revision 1.28  2000/03/10 17:59:20  vasilche
  212. * Fixed error reporting.
  213. * Added EOF bug workaround on MIPSpro compiler (not finished).
  214. *
  215. * Revision 1.27  2000/03/07 14:41:34  vasilche
  216. * Removed default argument.
  217. *
  218. * Revision 1.26  2000/03/07 14:06:23  vasilche
  219. * Added stream buffering to ASN.1 binary input.
  220. * Optimized class loading/storing.
  221. * Fixed bugs in processing OPTIONAL fields.
  222. * Added generation of reference counted objects.
  223. *
  224. * Revision 1.25  2000/02/17 20:02:44  vasilche
  225. * Added some standard serialization exceptions.
  226. * Optimized text/binary ASN.1 reading.
  227. * Fixed wrong encoding of StringStore in ASN.1 binary format.
  228. * Optimized logic of object collection.
  229. *
  230. * Revision 1.24  2000/01/10 19:46:40  vasilche
  231. * Fixed encoding/decoding of REAL type.
  232. * Fixed encoding/decoding of StringStore.
  233. * Fixed encoding/decoding of NULL type.
  234. * Fixed error reporting.
  235. * Reduced object map (only classes).
  236. *
  237. * Revision 1.23  2000/01/05 19:43:54  vasilche
  238. * Fixed error messages when reading from ASN.1 binary file.
  239. * Fixed storing of integers with enumerated values in ASN.1 binary file.
  240. * Added TAG support to key/value of map.
  241. * Added support of NULL variant in CHOICE.
  242. *
  243. * Revision 1.22  1999/12/17 19:05:03  vasilche
  244. * Simplified generation of GetTypeInfo methods.
  245. *
  246. * Revision 1.21  1999/10/19 15:41:03  vasilche
  247. * Fixed reference to IOS_BASE
  248. *
  249. * Revision 1.20  1999/10/18 20:21:41  vasilche
  250. * Enum values now have long type.
  251. * Fixed template generation for enums.
  252. *
  253. * Revision 1.19  1999/10/08 21:00:43  vasilche
  254. * Implemented automatic generation of unnamed ASN.1 types.
  255. *
  256. * Revision 1.18  1999/10/04 16:22:17  vasilche
  257. * Fixed bug with old ASN.1 structures.
  258. *
  259. * Revision 1.17  1999/09/24 18:19:18  vasilche
  260. * Removed dependency on NCBI toolkit.
  261. *
  262. * Revision 1.16  1999/09/23 21:16:08  vasilche
  263. * Removed dependence on asn.h
  264. *
  265. * Revision 1.15  1999/09/23 18:56:59  vasilche
  266. * Fixed bugs with overloaded methods in objistr*.hpp & objostr*.hpp
  267. *
  268. * Revision 1.14  1999/09/22 20:11:55  vasilche
  269. * Modified for compilation on IRIX native c++ compiler.
  270. *
  271. * Revision 1.13  1999/09/14 18:54:18  vasilche
  272. * Fixed bugs detected by gcc & egcs.
  273. * Removed unneeded includes.
  274. *
  275. * Revision 1.12  1999/08/16 16:08:31  vasilche
  276. * Added ENUMERATED type.
  277. *
  278. * Revision 1.11  1999/08/13 20:22:57  vasilche
  279. * Fixed lot of bugs in datatool
  280. *
  281. * Revision 1.10  1999/08/13 15:53:51  vasilche
  282. * C++ analog of asntool: datatool
  283. *
  284. * Revision 1.9  1999/07/26 18:31:37  vasilche
  285. * Implemented skipping of unused values.
  286. * Added more useful error report.
  287. *
  288. * Revision 1.8  1999/07/22 20:36:38  vasilche
  289. * Fixed 'using namespace' declaration for MSVC.
  290. *
  291. * Revision 1.7  1999/07/22 19:40:56  vasilche
  292. * Fixed bug with complex object graphs (pointers to members of other objects).
  293. *
  294. * Revision 1.6  1999/07/22 17:33:52  vasilche
  295. * Unified reading/writing of objects in all three formats.
  296. *
  297. * Revision 1.5  1999/07/21 20:02:54  vasilche
  298. * Added embedding of ASN.1 binary output from ToolKit to our binary format.
  299. * Fixed bugs with storing pointers into binary ASN.1
  300. *
  301. * Revision 1.4  1999/07/21 14:20:05  vasilche
  302. * Added serialization of bool.
  303. *
  304. * Revision 1.3  1999/07/09 16:32:54  vasilche
  305. * Added OCTET STRING write/read.
  306. *
  307. * Revision 1.2  1999/07/07 21:15:02  vasilche
  308. * Cleaned processing of string types (string, char*, const char*).
  309. *
  310. * Revision 1.1  1999/07/02 21:31:56  vasilche
  311. * Implemented reading from ASN.1 binary format.
  312. *
  313. * ===========================================================================
  314. */
  315. #include <ncbi_pch.hpp>
  316. #include <corelib/ncbistd.hpp>
  317. #include <corelib/ncbi_limits.hpp>
  318. #include <serial/objistrasnb.hpp>
  319. #include <serial/member.hpp>
  320. #include <serial/memberid.hpp>
  321. #include <serial/enumvalues.hpp>
  322. #include <serial/memberlist.hpp>
  323. #include <serial/objhook.hpp>
  324. #include <serial/classinfo.hpp>
  325. #include <serial/choice.hpp>
  326. #include <serial/continfo.hpp>
  327. #include <serial/objistrimpl.hpp>
  328. #include <serial/pack_string.hpp>
  329. using namespace NCBI_NS_NCBI::CObjectStreamAsnBinaryDefs;
  330. BEGIN_NCBI_SCOPE
  331. CObjectIStream* CObjectIStream::CreateObjectIStreamAsnBinary(void)
  332. {
  333.     return new CObjectIStreamAsnBinary();
  334. }
  335. CObjectIStreamAsnBinary::CObjectIStreamAsnBinary(EFixNonPrint how)
  336.     : CObjectIStream(eSerial_AsnBinary), m_FixMethod(how)
  337. {
  338. #if CHECK_STREAM_INTEGRITY
  339.     m_CurrentTagState = eTagStart;
  340.     m_CurrentTagLimit = numeric_limits<size_t>::max();
  341. #endif
  342.     m_CurrentTagLength = 0;
  343. }
  344. CObjectIStreamAsnBinary::CObjectIStreamAsnBinary(CNcbiIstream& in,
  345.                                                  EFixNonPrint how)
  346.     : CObjectIStream(eSerial_AsnBinary), m_FixMethod(how)
  347. {
  348. #if CHECK_STREAM_INTEGRITY
  349.     m_CurrentTagState = eTagStart;
  350.     m_CurrentTagLimit = numeric_limits<size_t>::max();
  351. #endif
  352.     m_CurrentTagLength = 0;
  353.     Open(in);
  354. }
  355. CObjectIStreamAsnBinary::CObjectIStreamAsnBinary(CNcbiIstream& in,
  356.                                                  bool deleteIn,
  357.                                                  EFixNonPrint how)
  358.     : CObjectIStream(eSerial_AsnBinary), m_FixMethod(how)
  359. {
  360. #if CHECK_STREAM_INTEGRITY
  361.     m_CurrentTagState = eTagStart;
  362.     m_CurrentTagLimit = numeric_limits<size_t>::max();
  363. #endif
  364.     m_CurrentTagLength = 0;
  365.     Open(in, deleteIn);
  366. }
  367. CObjectIStreamAsnBinary::CObjectIStreamAsnBinary(CByteSourceReader& reader,
  368.                                                  EFixNonPrint how)
  369.     : CObjectIStream(eSerial_AsnBinary), m_FixMethod(how)
  370. {
  371. #if CHECK_STREAM_INTEGRITY
  372.     m_CurrentTagState = eTagStart;
  373.     m_CurrentTagLimit = numeric_limits<size_t>::max();
  374. #endif
  375.     m_CurrentTagLength = 0;
  376.     Open(reader);
  377. }
  378. #if CHECK_STREAM_INTEGRITY
  379. Uint1 CObjectIStreamAsnBinary::PeekTagByte(size_t index)
  380. {
  381.     if ( m_CurrentTagState != eTagStart )
  382.         ThrowError(fIllegalCall,
  383.             "illegal PeekTagByte call: only allowed at tag start");
  384.     return m_Input.PeekChar(index);
  385. }
  386. Uint1 CObjectIStreamAsnBinary::StartTag(void)
  387. {
  388.     if ( m_CurrentTagLength != 0 )
  389.         ThrowError(fIllegalCall,
  390.             "illegal StartTag call: current tag length != 0");
  391.     return PeekTagByte();
  392. }
  393. #endif
  394. TTag CObjectIStreamAsnBinary::PeekTag(void)
  395. {
  396.     Uint1 byte = StartTag();
  397.     ETag sysTag = ExtractTag(byte);
  398.     if ( sysTag != eLongTag ) {
  399.         m_CurrentTagLength = 1;
  400. #if CHECK_STREAM_INTEGRITY
  401.         m_CurrentTagState = eTagParsed;
  402. #endif
  403.         return sysTag;
  404.     }
  405.     TTag tag = 0;
  406.     size_t i = 1;
  407.     const size_t KBitsInByte = 8; // ?
  408.     const size_t KTagBits = sizeof(tag) * KBitsInByte - 1;
  409.     do {
  410.         if ( tag >= (1 << (KTagBits - 7)) ) {
  411.             ThrowError(fOverflow, "tag number is too big: "+NStr::UIntToString(tag));
  412.         }
  413.         byte = PeekTagByte(i++);
  414.         tag = (tag << 7) | (byte & 0x7f);
  415.     } while ( (byte & 0x80) != 0 );
  416.     m_CurrentTagLength = i;
  417. #if CHECK_STREAM_INTEGRITY
  418.     m_CurrentTagState = eTagParsed;
  419. #endif
  420.     return tag;
  421. }
  422. TTag CObjectIStreamAsnBinary::PeekTag(EClass cls, bool constructed)
  423. {
  424.     if ( ExtractClassAndConstructed(PeekTagByte()) !=
  425.          MakeTagByte(cls, constructed) ) {
  426.         ThrowError(fFormatError, "unexpected tag class/constructed: #"
  427.             + NStr::UIntToString(PeekTagByte()) + ", should be #"
  428.             + NStr::UIntToString(MakeTagByte(cls, constructed)));
  429.     }
  430.     return PeekTag();
  431. }
  432. string CObjectIStreamAsnBinary::PeekClassTag(void)
  433. {
  434.     Uint1 byte = StartTag();
  435.     if ( ExtractTag(byte) != eLongTag ) {
  436.         ThrowError(fFormatError, "long tag expected");
  437.     }
  438.     string name;
  439.     size_t i = 1;
  440.     Uint1 c;
  441.     while ( ((c = PeekTagByte(i++)) & 0x80) != 0 ) {
  442.         name += char(c & 0x7f);
  443.         if ( i > 1024 ) {
  444.             ThrowError(fOverflow, "tag number is too big (greater than 1024)");
  445.         }
  446.     }
  447.     m_CurrentTagLength = i;
  448. #if CHECK_STREAM_INTEGRITY
  449.     m_CurrentTagState = eTagParsed;
  450. #endif
  451.     name += char(c & 0x7f);
  452.     return name;
  453. }
  454. Uint1 CObjectIStreamAsnBinary::PeekAnyTag(void)
  455. {
  456.     Uint1 fByte = StartTag();
  457.     if ( ExtractTag(fByte) != eLongTag ) {
  458.         m_CurrentTagLength = 1;
  459. #if CHECK_STREAM_INTEGRITY
  460.         m_CurrentTagState = eTagParsed;
  461. #endif
  462.         return fByte;
  463.     }
  464.     size_t i = 1;
  465.     Uint1 byte;
  466.     do {
  467.         if ( i > 1024 ) {
  468.             ThrowError(fOverflow, "tag number is too big (greater than 1024)");
  469.         }
  470.         byte = PeekTagByte(i++);
  471.     } while ( (byte & 0x80) != 0 );
  472.     m_CurrentTagLength = i;
  473. #if CHECK_STREAM_INTEGRITY
  474.     m_CurrentTagState = eTagParsed;
  475. #endif
  476.     return fByte;
  477. }
  478. void CObjectIStreamAsnBinary::UnexpectedTag(TTag tag)
  479. {
  480.     ThrowError(fFormatError,
  481.                "unexpected tag: " + NStr::IntToString(m_Input.PeekChar()) +
  482.                ", should be: " + NStr::IntToString(tag));
  483. }
  484. void CObjectIStreamAsnBinary::UnexpectedByte(Uint1 byte)
  485. {
  486.     ThrowError(fFormatError,
  487.                "byte " + NStr::IntToString(byte) + " expected");
  488. }
  489. #if CHECK_STREAM_INTEGRITY
  490. Uint1 CObjectIStreamAsnBinary::FlushTag(void)
  491. {
  492.     if ( m_CurrentTagState != eTagParsed || m_CurrentTagLength == 0 )
  493.         ThrowError(fIllegalCall, "illegal FlushTag call");
  494.     m_Input.SkipChars(m_CurrentTagLength);
  495.     m_CurrentTagState = eLengthValue;
  496.     return m_Input.GetChar();
  497. }
  498. bool CObjectIStreamAsnBinary::PeekIndefiniteLength(void)
  499. {
  500.     if ( m_CurrentTagState != eTagParsed )
  501.         ThrowError(fIllegalCall, "illegal PeekIndefiniteLength call");
  502.     return Uint1(m_Input.PeekChar(m_CurrentTagLength)) == 0x80;
  503. }
  504. void CObjectIStreamAsnBinary::ExpectIndefiniteLength(void)
  505. {
  506.     // indefinite length allowed only for constructed tags
  507.     if ( !ExtractConstructed(m_Input.PeekChar()) )
  508.         ThrowError(fFormatError, "illegal ExpectIndefiniteLength call");
  509.     if ( FlushTag() != 0x80 ) {
  510.         ThrowError(fFormatError, "indefinite length is expected");
  511.     }
  512.     _ASSERT(m_CurrentTagLimit == numeric_limits<size_t>::max());
  513.     // save tag limit
  514.     // tag limit is not changed
  515.     m_Limits.push(m_CurrentTagLimit);
  516.     m_CurrentTagState = eTagStart;
  517.     m_CurrentTagLength = 0;
  518. }
  519. size_t CObjectIStreamAsnBinary::StartTagData(size_t length)
  520. {
  521.     size_t cur_pos = m_Input.GetStreamOffset();
  522.     size_t newLimit = cur_pos + length;
  523.     _ASSERT(newLimit >= cur_pos);
  524.     size_t currentLimit = m_CurrentTagLimit;
  525.     _ASSERT(newLimit <= currentLimit);
  526.     m_Limits.push(currentLimit);
  527.     m_CurrentTagLimit = newLimit;
  528.     m_CurrentTagState = eData;
  529.     return length;
  530. }
  531. #endif
  532. size_t CObjectIStreamAsnBinary::ReadShortLength(void)
  533. {
  534.     Uint1 byte = FlushTag();
  535.     if ( byte >= 0x80 ) {
  536.         ThrowError(fFormatError, "short length expected");
  537.     }
  538.     return StartTagData(byte);
  539. }
  540. size_t CObjectIStreamAsnBinary::ReadLength(void)
  541. {
  542.     Uint1 byte = FlushTag();
  543.     if ( byte < 0x80 ) {
  544.         return StartTagData(byte);
  545.     }
  546.     size_t lengthLength = byte - 0x80;
  547.     if ( lengthLength == 0 ) {
  548.         ThrowError(fFormatError, "unexpected indefinite length");
  549.     }
  550.     if ( lengthLength > sizeof(size_t) ) {
  551.         ThrowError(fOverflow, "length overflow");
  552.     }
  553.     byte = m_Input.GetChar();
  554.     if ( byte == 0 ) {
  555.         ThrowError(fFormatError, "illegal length start");
  556.     }
  557.     if ( size_t(-1) < size_t(0) ) {        // size_t is signed
  558.         // check for sign overflow
  559.         if ( lengthLength == sizeof(size_t) && (byte & 0x80) != 0 ) {
  560.             ThrowError(fOverflow, "length overflow");
  561.         }
  562.     }
  563.     lengthLength--;
  564.     size_t length = byte;
  565.     while ( lengthLength-- > 0 )
  566.         length = (length << 8) | Uint1(m_Input.GetChar());
  567.     return StartTagData(length);
  568. }
  569. void CObjectIStreamAsnBinary::ExpectShortLength(size_t length)
  570. {
  571.     if ( ReadShortLength() != length ) {
  572.         ThrowError(fFormatError, "length expected: "+NStr::UIntToString(length));
  573.     }
  574. }
  575. #if CHECK_STREAM_INTEGRITY
  576. void CObjectIStreamAsnBinary::EndOfTag(void)
  577. {
  578.     if ( m_CurrentTagState != eData )
  579.         ThrowError(fIllegalCall, "illegal EndOfTag call");
  580.     // check for all bytes read
  581.     if ( m_CurrentTagLimit != numeric_limits<size_t>::max() ) {
  582.         if ( m_Input.GetStreamOffset() != m_CurrentTagLimit )
  583.             ThrowError(fIllegalCall,
  584.                        "illegal EndOfTag call: not all data bytes read");
  585.     }
  586.     m_CurrentTagState = eTagStart;
  587.     m_CurrentTagLength = 0;
  588.     // restore tag limit from stack
  589.     m_CurrentTagLimit = m_Limits.top();
  590.     m_Limits.pop();
  591.     _ASSERT(m_CurrentTagLimit == numeric_limits<size_t>::max());
  592. }
  593. void CObjectIStreamAsnBinary::ExpectEndOfContent(void)
  594. {
  595.     if ( m_CurrentTagState != eTagStart )
  596.         ThrowError(fFormatError, "illegal ExpectEndOfContent call");
  597.     ExpectSysTag(eNone);
  598.     if ( FlushTag() != 0 ) {
  599.         ThrowError(fFormatError, "zero length expected");
  600.     }
  601.     _ASSERT(m_CurrentTagLimit == numeric_limits<size_t>::max());
  602.     // restore tag limit from stack
  603.     m_CurrentTagLimit = m_Limits.top();
  604.     m_Limits.pop();
  605.     _ASSERT(m_CurrentTagLimit == numeric_limits<size_t>::max());
  606.     m_CurrentTagState = eTagStart;
  607.     m_CurrentTagLength = 0;
  608. }
  609. Uint1 CObjectIStreamAsnBinary::ReadByte(void)
  610. {
  611.     if ( m_CurrentTagState != eData )
  612.         ThrowError(fIllegalCall, "illegal ReadByte call");
  613.     if ( m_Input.GetStreamOffset() >= m_CurrentTagLimit )
  614.         ThrowError(fOverflow, "tag size overflow");
  615.     return m_Input.GetChar();
  616. }
  617. #endif
  618. void CObjectIStreamAsnBinary::ReadBytes(char* buffer, size_t count)
  619. {
  620. #if CHECK_STREAM_INTEGRITY
  621.     if ( m_CurrentTagState != eData ) {
  622.         ThrowError(fIllegalCall, "illegal ReadBytes call");
  623.     }
  624. #endif
  625.     if ( count == 0 )
  626.         return;
  627. #if CHECK_STREAM_INTEGRITY
  628.     size_t cur_pos = m_Input.GetStreamOffset();
  629.     size_t end_pos = cur_pos + count;
  630.     if ( end_pos < cur_pos || end_pos > m_CurrentTagLimit )
  631.         ThrowError(fOverflow, "tag size overflow");
  632. #endif
  633.     m_Input.GetChars(buffer, count);
  634. }
  635. void CObjectIStreamAsnBinary::SkipBytes(size_t count)
  636. {
  637. #if CHECK_STREAM_INTEGRITY
  638.     if ( m_CurrentTagState != eData ) {
  639.         ThrowError(fIllegalCall, "illegal ReadBytes call");
  640.     }
  641. #endif
  642.     if ( count == 0 )
  643.         return;
  644. #if CHECK_STREAM_INTEGRITY
  645.     size_t cur_pos = m_Input.GetStreamOffset();
  646.     size_t end_pos = cur_pos + count;
  647.     if ( end_pos < cur_pos || end_pos > m_CurrentTagLimit )
  648.         ThrowError(fOverflow, "tag size overflow");
  649. #endif
  650.     m_Input.GetChars(count);
  651. }
  652. template<typename T>
  653. void ReadStdSigned(CObjectIStreamAsnBinary& in, T& data)
  654. {
  655.     size_t length = in.ReadShortLength();
  656.     if ( length == 0 ) {
  657.         in.ThrowError(in.fFormatError, "zero length of number");
  658.     }
  659.     T n;
  660.     if ( length > sizeof(data) ) {
  661.         // skip
  662.         --length;
  663.         Int1 c = in.ReadSByte();
  664.         if ( c != 0 && c != -1 ) {
  665.             in.ThrowError(in.fOverflow, "overflow error");
  666.         }
  667.         while ( length > sizeof(data) ) {
  668.             --length;
  669.             if ( in.ReadSByte() != c ) {
  670.                 in.ThrowError(in.fOverflow, "overflow error");
  671.             }
  672.         }
  673.         --length;
  674.         n = in.ReadSByte();
  675.         if ( ((n ^ c) & 0x80) != 0 ) {
  676.             in.ThrowError(in.fOverflow, "overflow error");
  677.         }
  678.     }
  679.     else {
  680.         --length;
  681.         n = in.ReadSByte();
  682.     }
  683.     while ( length > 0 ) {
  684.         --length;
  685.         n = (n << 8) | in.ReadByte();
  686.     }
  687.     data = n;
  688.     in.EndOfTag();
  689. }
  690. template<typename T>
  691. void ReadStdUnsigned(CObjectIStreamAsnBinary& in, T& data)
  692. {
  693.     size_t length = in.ReadShortLength();
  694.     if ( length == 0 ) {
  695.         in.ThrowError(in.fFormatError, "zero length of number");
  696.     }
  697.     T n;
  698.     if ( length > sizeof(data) ) {
  699.         // skip
  700.         while ( length > sizeof(data) ) {
  701.             --length;
  702.             if ( in.ReadSByte() != 0 ) {
  703.                 in.ThrowError(in.fOverflow, "overflow error");
  704.             }
  705.         }
  706.         --length;
  707.         n = in.ReadByte();
  708.         if ( (n & 0x80) != 0 ) {
  709.             in.ThrowError(in.fOverflow, "overflow error");
  710.         }
  711.     }
  712.     else if ( length == sizeof(data) ) {
  713.         --length;
  714.         n = in.ReadByte();
  715.         if ( (n & 0x80) != 0 ) {
  716.             in.ThrowError(in.fOverflow, "overflow error");
  717.         }
  718.     }
  719.     else {
  720.         n = 0;
  721.     }
  722.     while ( length > 0 ) {
  723.         --length;
  724.         n = (n << 8) | in.ReadByte();
  725.     }
  726.     data = n;
  727.     in.EndOfTag();
  728. }
  729. bool CObjectIStreamAsnBinary::ReadBool(void)
  730. {
  731.     ExpectSysTag(eBoolean);
  732.     ExpectShortLength(1);
  733.     bool ret = ReadByte() != 0;
  734.     EndOfTag();
  735.     return ret;
  736. }
  737. char CObjectIStreamAsnBinary::ReadChar(void)
  738. {
  739.     ExpectSysTag(eGeneralString);
  740.     ExpectShortLength(1);
  741.     char ret = ReadByte();
  742.     EndOfTag();
  743.     return ret;
  744. }
  745. Int4 CObjectIStreamAsnBinary::ReadInt4(void)
  746. {
  747.     ExpectSysTag(eInteger);
  748.     Int4 data;
  749.     ReadStdSigned(*this, data);
  750.     return data;
  751. }
  752. Uint4 CObjectIStreamAsnBinary::ReadUint4(void)
  753. {
  754.     ExpectSysTag(eInteger);
  755.     Uint4 data;
  756.     ReadStdUnsigned(*this, data);
  757.     return data;
  758. }
  759. Int8 CObjectIStreamAsnBinary::ReadInt8(void)
  760. {
  761.     ExpectSysTag(eInteger);
  762.     Uint8 data;
  763.     ReadStdSigned(*this, data);
  764.     return data;
  765. }
  766. Uint8 CObjectIStreamAsnBinary::ReadUint8(void)
  767. {
  768.     ExpectSysTag(eInteger);
  769.     Uint8 data;
  770.     ReadStdUnsigned(*this, data);
  771.     return data;
  772. }
  773. static const size_t kMaxDoubleLength = 256;
  774. double CObjectIStreamAsnBinary::ReadDouble(void)
  775. {
  776.     ExpectSysTag(eReal);
  777.     size_t length = ReadLength();
  778.     if ( length < 2 ) {
  779.         ThrowError(fFormatError, "too short REAL data: length < 2");
  780.     }
  781.     if ( length > kMaxDoubleLength ) {
  782.         ThrowError(fFormatError, "too long REAL data: length > "
  783.             + NStr::UIntToString(kMaxDoubleLength));
  784.     }
  785.     ExpectByte(eDecimal);
  786.     length--;
  787.     char buffer[kMaxDoubleLength + 2];
  788.     ReadBytes(buffer, length);
  789.     EndOfTag();
  790.     buffer[length] = 0;
  791.     char* endptr;
  792.     double data = strtod(buffer, &endptr);
  793.     if ( *endptr != 0 ) {
  794.         ThrowError(fFormatError, "bad REAL data string");
  795.     }
  796.     return data;
  797. }
  798. void CObjectIStreamAsnBinary::ReadString(string& s, EStringType type)
  799. {
  800.     ExpectSysTag(eVisibleString);
  801.     ReadStringValue(ReadLength(), s,
  802.                     type == eStringTypeUTF8? eFNP_Allow: m_FixMethod);
  803. }
  804. void CObjectIStreamAsnBinary::ReadString(string& s,
  805.                                          CPackString& pack_string,
  806.                                          EStringType type)
  807. {
  808.     ExpectSysTag(eVisibleString);
  809.     size_t length = ReadLength();
  810.     char buffer[1024];
  811.     if ( length > sizeof(buffer) || length > pack_string.GetLengthLimit() ) {
  812.         pack_string.Skipped();
  813.         ReadStringValue(length, s,
  814.                         type == eStringTypeUTF8? eFNP_Allow: m_FixMethod);
  815.     }
  816.     else {
  817.         ReadBytes(buffer, length);
  818.         EndOfTag();
  819.         pair<CPackString::iterator, bool> found =
  820.             pack_string.Locate(buffer, length);
  821.         if ( found.second ) {
  822.             pack_string.AddOld(s, found.first);
  823.         }
  824.         else {
  825.             if ( type == eStringTypeVisible && m_FixMethod != eFNP_Allow ) {
  826.                 // check contents of string
  827.                 for ( size_t i = 0; i < length; ++i ) {
  828.                     if ( !GoodVisibleChar(buffer[i]) ) {
  829.                         for ( ; i < length; ++i ) {
  830.                             FixVisibleChar(buffer[i], m_FixMethod);
  831.                         }
  832.                         pack_string.Pack(s, buffer, length);
  833.                         return;
  834.                     }
  835.                 }
  836.             }
  837.             pack_string.AddNew(s, buffer, length, found.first);
  838.         }
  839.     }
  840. }
  841. void CObjectIStreamAsnBinary::ReadStringStore(string& s)
  842. {
  843.     ExpectSysTag(eApplication, false, eStringStore);
  844.     ReadStringValue(ReadLength(), s, m_FixMethod);
  845. }
  846. void CObjectIStreamAsnBinary::ReadStringValue(size_t length,
  847.                                               string& s,
  848.                                               EFixNonPrint fix_method)
  849. {
  850.     s.reserve(length);
  851.     char buffer[1024];
  852.     if ( length < sizeof(buffer) ) {
  853.         // try to reuse old value
  854.         ReadBytes(buffer, length);
  855.         if ( fix_method != eFNP_Allow ) {
  856.             for ( size_t i = 0; i < length; ++i ) {
  857.                 FixVisibleChar(buffer[i], fix_method);
  858.             }
  859.         }
  860.         if ( s.size() != length || memcmp(s.data(), buffer, length) != 0 ) {
  861.             s.assign(buffer, length);
  862.         }
  863.     }
  864.     else {
  865.         s.erase();
  866.         while ( length ) {
  867.             size_t count = min(length, sizeof(buffer));
  868.             ReadBytes(buffer, count);
  869.             if ( fix_method != eFNP_Allow ) {
  870.                 for ( size_t i = 0; i < count; ++i ) {
  871.                     FixVisibleChar(buffer[i], fix_method);
  872.                 }
  873.             }
  874.             s.append(buffer, count);
  875.             length -= count;
  876.         }
  877.     }
  878.     EndOfTag();
  879. }
  880. char* CObjectIStreamAsnBinary::ReadCString(void)
  881. {
  882.     ExpectSysTag(eVisibleString);
  883.     size_t length = ReadLength();
  884.     char* s = static_cast<char*>(malloc(length + 1));
  885.     ReadBytes(s, length);
  886.     s[length] = 0;
  887.     if ( m_FixMethod != eFNP_Allow ) {
  888.         // Check the string for non-printable characters
  889.         for ( char* ptr = s; length; ++ptr, --length ) {
  890.             FixVisibleChar(*ptr, m_FixMethod);
  891.         }
  892.     }
  893.     EndOfTag();
  894.     return s;
  895. }
  896. void CObjectIStreamAsnBinary::BeginContainer(const CContainerTypeInfo* containerType)
  897. {
  898.     if ( containerType->RandomElementsOrder() )
  899.         ExpectSysTag(eUniversal, true, eSet);
  900.     else
  901.         ExpectSysTag(eUniversal, true, eSequence);
  902.     ExpectIndefiniteLength();
  903. }
  904. void CObjectIStreamAsnBinary::EndContainer(void)
  905. {
  906.     ExpectEndOfContent();
  907. }
  908. bool CObjectIStreamAsnBinary::BeginContainerElement(TTypeInfo /*elementType*/)
  909. {
  910.     return HaveMoreElements();
  911. }
  912. #ifdef VIRTUAL_MID_LEVEL_IO
  913. void CObjectIStreamAsnBinary::ReadContainer(const CContainerTypeInfo* cType,
  914.                                             TObjectPtr containerPtr)
  915. {
  916.     if ( cType->RandomElementsOrder() )
  917.         ExpectSysTag(eUniversal, true, eSet);
  918.     else
  919.         ExpectSysTag(eUniversal, true, eSequence);
  920.     ExpectIndefiniteLength();
  921.     BEGIN_OBJECT_FRAME(eFrameArrayElement);
  922.     CContainerTypeInfo::CIterator iter;
  923.     bool old_element = cType->InitIterator(iter, containerPtr);
  924.     TTypeInfo elementType = cType->GetElementType();
  925.     while ( HaveMoreElements() ) {
  926.         if ( old_element ) {
  927.             elementType->ReadData(*this, cType->GetElementPtr(iter));
  928.             old_element = cType->NextElement(iter);
  929.         }
  930.         else {
  931.             cType->AddElement(containerPtr, *this);
  932.         }
  933.     }
  934.     if ( old_element ) {
  935.         cType->EraseAllElements(iter);
  936.     }
  937.     END_OBJECT_FRAME();
  938.     ExpectEndOfContent();
  939. }
  940. void CObjectIStreamAsnBinary::SkipContainer(const CContainerTypeInfo* cType)
  941. {
  942.     if ( cType->RandomElementsOrder() )
  943.         ExpectSysTag(eUniversal, true, eSet);
  944.     else
  945.         ExpectSysTag(eUniversal, true, eSequence);
  946.     ExpectIndefiniteLength();
  947.     TTypeInfo elementType = cType->GetElementType();
  948.     BEGIN_OBJECT_FRAME(eFrameArrayElement);
  949.     while ( HaveMoreElements() ) {
  950.         SkipObject(elementType);
  951.     }
  952.     END_OBJECT_FRAME();
  953.     ExpectEndOfContent();
  954. }
  955. #endif
  956. void CObjectIStreamAsnBinary::BeginClass(const CClassTypeInfo* classInfo)
  957. {
  958.     if ( classInfo->RandomOrder() )
  959.         ExpectSysTag(eUniversal, true, eSet);
  960.     else
  961.         ExpectSysTag(eUniversal, true, eSequence);
  962.     ExpectIndefiniteLength();
  963. }
  964. void CObjectIStreamAsnBinary::EndClass(void)
  965. {
  966.     ExpectEndOfContent();
  967. }
  968. void CObjectIStreamAsnBinary::UnexpectedMember(TTag tag)
  969. {
  970.     ThrowError(fFormatError,
  971.                "unexpected member: ["+NStr::IntToString(tag)+"]");
  972. }
  973. TMemberIndex
  974. CObjectIStreamAsnBinary::BeginClassMember(const CClassTypeInfo* classType)
  975. {
  976.     if ( !HaveMoreElements() )
  977.         return kInvalidMember;
  978.     TTag tag = PeekTag(eContextSpecific, true);
  979.     ExpectIndefiniteLength();
  980.     TMemberIndex index = classType->GetMembers().Find(tag);
  981.     if ( index == kInvalidMember )
  982.         if (GetSkipUnknownMembers() == eSerialSkipUnknown_Yes) {
  983.             ReadAnyContent();
  984.             ExpectEndOfContent();
  985.             return BeginClassMember(classType);
  986.         } else {
  987.             UnexpectedMember(tag);
  988.         }
  989.     return index;
  990. }
  991. TMemberIndex
  992. CObjectIStreamAsnBinary::BeginClassMember(const CClassTypeInfo* classType,
  993.                                           TMemberIndex pos)
  994. {
  995.     if ( !HaveMoreElements() )
  996.         return kInvalidMember;
  997.     TTag tag = PeekTag(eContextSpecific, true);
  998.     ExpectIndefiniteLength();
  999.     TMemberIndex index = classType->GetMembers().Find(tag, pos);
  1000.     if ( index == kInvalidMember )
  1001.         if (GetSkipUnknownMembers() == eSerialSkipUnknown_Yes) {
  1002.             ReadAnyContent();
  1003.             ExpectEndOfContent();
  1004.             return BeginClassMember(classType, pos);
  1005.         } else {
  1006.             UnexpectedMember(tag);
  1007.         }
  1008.     return index;
  1009. }
  1010. void CObjectIStreamAsnBinary::EndClassMember(void)
  1011. {
  1012.     ExpectEndOfContent();
  1013. }
  1014. #ifdef VIRTUAL_MID_LEVEL_IO
  1015. void CObjectIStreamAsnBinary::ReadClassRandom(const CClassTypeInfo* classType,
  1016.                                               TObjectPtr classPtr)
  1017. {
  1018.     BeginClass(classType);
  1019.     ReadClassRandomContentsBegin(classType);
  1020.     TMemberIndex index;
  1021.     while ( (index = BeginClassMember(classType)) != kInvalidMember ) {
  1022.         ReadClassRandomContentsMember(classPtr);
  1023.         EndClassMember();
  1024.     }
  1025.     ReadClassRandomContentsEnd();
  1026.     EndClass();
  1027. }
  1028. void CObjectIStreamAsnBinary::ReadClassSequential(const CClassTypeInfo* classType,
  1029.                                                   TObjectPtr classPtr)
  1030. {
  1031.     BeginClass(classType);
  1032.     ReadClassSequentialContentsBegin(classType);
  1033.     TMemberIndex index;
  1034.     while ( (index = BeginClassMember(classType,*pos)) != kInvalidMember ) {
  1035.         ReadClassSequentialContentsMember(classPtr);
  1036.         EndClassMember();
  1037.     }
  1038.     ReadClassSequentialContentsEnd(classPtr);
  1039.     EndClass();
  1040. }
  1041. void CObjectIStreamAsnBinary::SkipClassRandom(const CClassTypeInfo* classType)
  1042. {
  1043.     BeginClass(classType);
  1044.     SkipClassRandomContentsBegin(classType);
  1045.     TMemberIndex index;
  1046.     while ( (index = BeginClassMember(classType)) != kInvalidMember ) {
  1047.         SkipClassRandomContentsMember();
  1048.         EndClassMember();
  1049.     }
  1050.     SkipClassRandomContentsEnd();
  1051.     EndClass();
  1052. }
  1053. void CObjectIStreamAsnBinary::SkipClassSequential(const CClassTypeInfo* classType)
  1054. {
  1055.     BeginClass(classType);
  1056.     SkipClassSequentialContentsBegin(classType);
  1057.     TMemberIndex index;
  1058.     while ( (index = BeginClassMember(classType,*pos)) != kInvalidMember ) {
  1059.         SkipClassSequentialContentsMember();
  1060.         EndClassMember();
  1061.     }
  1062.     SkipClassSequentialContentsEnd();
  1063.     EndClass();
  1064. }
  1065. #endif
  1066. TMemberIndex CObjectIStreamAsnBinary::BeginChoiceVariant(const CChoiceTypeInfo* choiceType)
  1067. {
  1068.     TTag tag = PeekTag(eContextSpecific, true);
  1069.     ExpectIndefiniteLength();
  1070.     TMemberIndex index = choiceType->GetVariants().Find(tag);
  1071.     if ( index == kInvalidMember )
  1072.         UnexpectedMember(tag);
  1073.     return index;
  1074. }
  1075. void CObjectIStreamAsnBinary::EndChoiceVariant(void)
  1076. {
  1077.     ExpectEndOfContent();
  1078. }
  1079. #ifdef VIRTUAL_MID_LEVEL_IO
  1080. void CObjectIStreamAsnBinary::ReadChoice(const CChoiceTypeInfo* choiceType,
  1081.                                          TObjectPtr choicePtr)
  1082. {
  1083.     TMemberIndex index = BeginChoiceVariant(choiceType);
  1084.     const CVariantInfo* variantInfo = choiceType->GetVariantInfo(index);
  1085.     BEGIN_OBJECT_FRAME2(eFrameChoiceVariant, variantInfo->GetId());
  1086.     variantInfo->ReadVariant(*this, choicePtr);
  1087.     END_OBJECT_FRAME();
  1088.     EndChoiceVariant();
  1089. }
  1090. void CObjectIStreamAsnBinary::SkipChoice(const CChoiceTypeInfo* choiceType)
  1091. {
  1092.     TMemberIndex index = BeginChoiceVariant(choiceType);
  1093.     const CVariantInfo* variantInfo = choiceType->GetVariantInfo(index);
  1094.     BEGIN_OBJECT_FRAME2(eFrameChoiceVariant, variantInfo->GetId());
  1095.     variantInfo->SkipVariant(*this);
  1096.     END_OBJECT_FRAME();
  1097.     EndChoiceVariant();
  1098. }
  1099. #endif
  1100. void CObjectIStreamAsnBinary::BeginBytes(ByteBlock& block)
  1101. {
  1102.     ExpectSysTag(eOctetString);
  1103.     block.SetLength(ReadLength());
  1104. }
  1105. size_t CObjectIStreamAsnBinary::ReadBytes(ByteBlock& ,
  1106.                                           char* dst, size_t length)
  1107. {
  1108.     ReadBytes(dst, length);
  1109.     return length;
  1110. }
  1111. void CObjectIStreamAsnBinary::EndBytes(const ByteBlock& )
  1112. {
  1113.     EndOfTag();
  1114. }
  1115. void CObjectIStreamAsnBinary::BeginChars(CharBlock& block)
  1116. {
  1117.     ExpectSysTag(eVisibleString);
  1118.     block.SetLength(ReadLength());
  1119. }
  1120. size_t CObjectIStreamAsnBinary::ReadChars(CharBlock& ,
  1121.                                           char* dst, size_t length)
  1122. {
  1123.     ReadBytes(dst, length);
  1124.     return length;
  1125. }
  1126. void CObjectIStreamAsnBinary::EndChars(const CharBlock& )
  1127. {
  1128.     EndOfTag();
  1129. }
  1130. void CObjectIStreamAsnBinary::ReadNull(void)
  1131. {
  1132.     ExpectSysTag(eNull);
  1133.     ExpectShortLength(0);
  1134.     EndOfTag();
  1135. }
  1136. bool CObjectIStreamAsnBinary::ReadAnyContent()
  1137. {
  1138.     Uint1 byte = PeekAnyTag();
  1139.     if (ExtractConstructed(byte) && PeekIndefiniteLength()) {
  1140.         ExpectIndefiniteLength();
  1141.         if (ReadAnyContent()) {
  1142.             while (HaveMoreElements()) {
  1143.                 ReadAnyContent();
  1144.             }
  1145.             ExpectEndOfContent();
  1146.         }
  1147.         return true;
  1148.     }
  1149.     size_t length = ReadLength();
  1150.     if (length) {
  1151.         SkipBytes(length);
  1152.     }
  1153.     EndOfTag();
  1154.     return (length != 0);
  1155. }
  1156. void CObjectIStreamAsnBinary::ReadAnyContentObject(CAnyContentObject& )
  1157. {
  1158.     NCBI_THROW(CSerialException,eNotImplemented,
  1159.         "CObjectIStreamAsnBinary::ReadAnyContentObject: "
  1160.         "unable to read AnyContent object in ASN binary");
  1161. }
  1162. void CObjectIStreamAsnBinary::SkipAnyContentObject(void)
  1163. {
  1164.     NCBI_THROW(CSerialException,eNotImplemented,
  1165.         "CObjectIStreamAsnBinary::SkipAnyContentObject: "
  1166.         "unable to skip AnyContent object in ASN binary");
  1167. }
  1168. CObjectIStream::EPointerType CObjectIStreamAsnBinary::ReadPointerType(void)
  1169. {
  1170.     Uint1 byte = PeekTagByte();
  1171.     // variants:
  1172.     //    eUniversal,   !constructed, eNull             -> NULL
  1173.     //    eApplication,  constructed, eMemberReference  -> member reference
  1174.     //    eApplication,  constructed, eLongTag          -> other class
  1175.     //    eApplication, !constructed, eObjectReference  -> object reference
  1176.     // any other -> this class
  1177.     if ( byte == eEndOfContentsByte ) {
  1178.         ExpectShortLength(0);
  1179.         EndOfTag();
  1180.         return eNullPointer;
  1181.     }
  1182.     else if ( byte == MakeTagByte(eApplication, true, eLongTag) ) {
  1183.         return eOtherPointer;
  1184.     }
  1185.     else if ( byte == MakeTagByte(eApplication, false, eObjectReference) ) {
  1186.         return eObjectPointer;
  1187.     }
  1188.     // by default: try this class
  1189.     return eThisPointer;
  1190. }
  1191. TEnumValueType CObjectIStreamAsnBinary::ReadEnum(const CEnumeratedTypeValues& values)
  1192. {
  1193.     TEnumValueType value;
  1194.     if ( values.IsInteger() ) {
  1195.         // allow any integer
  1196.         ExpectSysTag(eInteger);
  1197.         ReadStdSigned(*this, value);
  1198.     }
  1199.     else {
  1200.         // enum element by value
  1201.         ExpectSysTag(eEnumerated);
  1202.         ReadStdSigned(*this, value);
  1203.         values.FindName(value, false); // check value
  1204.     }
  1205.     return value;
  1206. }
  1207. CObjectIStream::TObjectIndex CObjectIStreamAsnBinary::ReadObjectPointer(void)
  1208. {
  1209.     TObjectIndex data;
  1210.     ReadStdSigned(*this, data);
  1211.     return data;
  1212. }
  1213. string CObjectIStreamAsnBinary::ReadOtherPointer(void)
  1214. {
  1215.     string className = PeekClassTag();
  1216.     ExpectIndefiniteLength();
  1217.     return className;
  1218. }
  1219. void CObjectIStreamAsnBinary::ReadOtherPointerEnd(void)
  1220. {
  1221.     ExpectEndOfContent();
  1222. }
  1223. bool CObjectIStreamAsnBinary::SkipRealValue(void)
  1224. {
  1225.     if ( PeekTagByte() == 0 && PeekTagByte(1) == 0 )
  1226.         return false;
  1227.     Uint1 byte = PeekAnyTag();
  1228.     if ( ExtractConstructed(byte) ) {
  1229.         // constructed
  1230.         ExpectIndefiniteLength();
  1231.         while ( SkipRealValue() )
  1232.             ;
  1233.         ExpectEndOfContent();
  1234.     }
  1235.     else {
  1236.         SkipTagData();
  1237.     }
  1238.     return true;
  1239. }
  1240. void CObjectIStreamAsnBinary::SkipBool(void)
  1241. {
  1242.     ExpectSysTag(eBoolean);
  1243.     ExpectShortLength(1);
  1244.     ReadByte();
  1245.     EndOfTag();
  1246. }
  1247. void CObjectIStreamAsnBinary::SkipChar(void)
  1248. {
  1249.     ExpectSysTag(eGeneralString);
  1250.     ExpectShortLength(1);
  1251.     ReadByte();
  1252.     EndOfTag();
  1253. }
  1254. void CObjectIStreamAsnBinary::SkipSNumber(void)
  1255. {
  1256.     ExpectSysTag(eInteger);
  1257.     SkipTagData();
  1258. }
  1259. void CObjectIStreamAsnBinary::SkipUNumber(void)
  1260. {
  1261.     ExpectSysTag(eInteger);
  1262.     SkipTagData();
  1263. }
  1264. void CObjectIStreamAsnBinary::SkipFNumber(void)
  1265. {
  1266.     ExpectSysTag(eReal);
  1267.     size_t length = ReadLength();
  1268.     if ( length < 2 )
  1269.         ThrowError(fFormatError, "too short REAL data: length < 2");
  1270.     if ( length > kMaxDoubleLength )
  1271.         ThrowError(fFormatError, "too long REAL data: length > "
  1272.             + NStr::UIntToString(kMaxDoubleLength));
  1273.     ExpectByte(eDecimal);
  1274.     length--;
  1275.     SkipBytes(length);
  1276.     EndOfTag();
  1277. }
  1278. void CObjectIStreamAsnBinary::SkipString(EStringType /*type*/)
  1279. {
  1280.     ExpectSysTag(eVisibleString);
  1281.     SkipTagData();
  1282. }
  1283. void CObjectIStreamAsnBinary::SkipStringStore(void)
  1284. {
  1285.     ExpectSysTag(eApplication, false, eStringStore);
  1286.     SkipTagData();
  1287. }
  1288. void CObjectIStreamAsnBinary::SkipNull(void)
  1289. {
  1290.     ExpectSysTag(eNull);
  1291.     ExpectShortLength(0);
  1292.     EndOfTag();
  1293. }
  1294. void CObjectIStreamAsnBinary::SkipByteBlock(void)
  1295. {
  1296.     ExpectSysTag(eOctetString);
  1297.     SkipTagData();
  1298. }
  1299. void CObjectIStreamAsnBinary::SkipTagData(void)
  1300. {
  1301.     SkipBytes(ReadLength());
  1302.     EndOfTag();
  1303. }
  1304. END_NCBI_SCOPE