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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: objostrasn.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:41:12  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.85
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: objostrasn.cpp,v 1000.3 2004/06/01 19:41:12 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: objostrasn.cpp,v $
  41. * Revision 1000.3  2004/06/01 19:41:12  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.85
  43. *
  44. * Revision 1.85  2004/05/17 21:03:03  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.84  2004/05/04 17:04:43  gouriano
  48. * Check double for being finite
  49. *
  50. * Revision 1.83  2004/01/05 14:25:21  gouriano
  51. * Added possibility to set serialization hooks by stack path
  52. *
  53. * Revision 1.82  2003/11/26 19:59:41  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.81  2003/08/19 18:32:38  vasilche
  59. * Optimized reading and writing strings.
  60. * Avoid string reallocation when checking char values.
  61. * Try to reuse old string data when string reference counting is not working.
  62. *
  63. * Revision 1.80  2003/08/13 15:47:45  gouriano
  64. * implemented serialization of AnyContent objects
  65. *
  66. * Revision 1.79  2003/05/22 20:10:02  gouriano
  67. * added UTF8 strings
  68. *
  69. * Revision 1.78  2003/05/16 18:02:18  gouriano
  70. * revised exception error messages
  71. *
  72. * Revision 1.77  2003/03/26 16:14:23  vasilche
  73. * Removed TAB symbols. Some formatting.
  74. *
  75. * Revision 1.76  2003/02/04 17:06:26  gouriano
  76. * added check for NaN in WriteDouble
  77. *
  78. * Revision 1.75  2003/01/22 18:53:26  gouriano
  79. * corrected stream destruction
  80. *
  81. * Revision 1.74  2002/12/13 21:50:42  gouriano
  82. * corrected reading of choices
  83. *
  84. * Revision 1.73  2002/11/14 20:59:48  gouriano
  85. * added BeginChoice/EndChoice methods
  86. *
  87. * Revision 1.72  2002/10/25 14:49:27  vasilche
  88. * NCBI C Toolkit compatibility code extracted to libxcser library.
  89. * Serial streams flags names were renamed to fXxx.
  90. *
  91. * Names of flags
  92. *
  93. * Revision 1.71  2002/10/08 18:59:38  grichenk
  94. * Check for null pointers in containers (assert in debug mode,
  95. * warning in release).
  96. *
  97. * Revision 1.70  2002/08/26 18:32:30  grichenk
  98. * Added Get/SetAutoSeparator() to CObjectOStream to control
  99. * output of separators.
  100. *
  101. * Revision 1.69  2002/08/23 16:52:37  grichenk
  102. * Set separator to line-break by default
  103. *
  104. * Revision 1.68  2002/03/07 22:02:02  grichenk
  105. * Added "Separator" modifier for CObjectOStream
  106. *
  107. * Revision 1.67  2001/10/17 20:41:25  grichenk
  108. * Added CObjectOStream::CharBlock class
  109. *
  110. * Revision 1.66  2001/07/27 18:25:32  grichenk
  111. * Removed commented code
  112. *
  113. * Revision 1.65  2001/06/11 14:35:00  grichenk
  114. * Added support for numeric tags in ASN.1 specifications and data streams.
  115. *
  116. * Revision 1.64  2001/06/07 17:12:51  grichenk
  117. * Redesigned checking and substitution of non-printable characters
  118. * in VisibleString
  119. *
  120. * Revision 1.63  2001/05/17 15:07:08  lavr
  121. * Typos corrected
  122. *
  123. * Revision 1.62  2001/04/25 20:41:53  vakatov
  124. * <limits.h>, <float.h>  --->  <corelib/ncbi_limits.h>
  125. *
  126. * Revision 1.61  2001/01/03 15:22:27  vasilche
  127. * Fixed limited buffer size for REAL data in ASN.1 binary format.
  128. * Fixed processing non ASCII symbols in ASN.1 text format.
  129. *
  130. * Revision 1.60  2000/12/26 22:24:13  vasilche
  131. * Fixed errors of compilation on Mac.
  132. *
  133. * Revision 1.59  2000/12/15 21:29:02  vasilche
  134. * Moved some typedefs/enums from corelib/ncbistd.hpp.
  135. * Added flags to CObjectIStream/CObjectOStream: eFlagAllowNonAsciiChars.
  136. * TByte typedef replaced by Uint1.
  137. *
  138. * Revision 1.58  2000/12/15 15:38:45  vasilche
  139. * Added support of Int8 and long double.
  140. * Enum values now have type Int4 instead of long.
  141. *
  142. * Revision 1.57  2000/12/04 19:02:41  beloslyu
  143. * changes for FreeBSD
  144. *
  145. * Revision 1.56  2000/11/07 17:25:40  vasilche
  146. * Fixed encoding of XML:
  147. *     removed unnecessary apostrophes in OCTET STRING
  148. *     removed unnecessary content in NULL
  149. * Added module names to CTypeInfo and CEnumeratedTypeValues
  150. *
  151. * Revision 1.55  2000/10/20 15:51:42  vasilche
  152. * Fixed data error processing.
  153. * Added interface for constructing container objects directly into output stream.
  154. * object.hpp, object.inl and object.cpp were split to
  155. * objectinfo.*, objecttype.*, objectiter.* and objectio.*.
  156. *
  157. * Revision 1.54  2000/10/17 18:45:35  vasilche
  158. * Added possibility to turn off object cross reference detection in
  159. * CObjectIStream and CObjectOStream.
  160. *
  161. * Revision 1.53  2000/10/13 20:22:55  vasilche
  162. * Fixed warnings on 64 bit compilers.
  163. * Fixed missing typename in templates.
  164. *
  165. * Revision 1.52  2000/10/13 16:28:39  vasilche
  166. * Reduced header dependency.
  167. * Avoid use of templates with virtual methods.
  168. * Reduced amount of different maps used.
  169. * All this lead to smaller compiled code size (libraries and programs).
  170. *
  171. * Revision 1.51  2000/10/05 15:52:50  vasilche
  172. * Avoid using snprintf because it's missing on osf1_gcc
  173. *
  174. * Revision 1.50  2000/10/05 13:17:17  vasilche
  175. * Added missing #include <stdio.h>
  176. *
  177. * Revision 1.49  2000/10/04 19:18:59  vasilche
  178. * Fixed processing floating point data.
  179. *
  180. * Revision 1.48  2000/10/03 17:22:44  vasilche
  181. * Reduced header dependency.
  182. * Reduced size of debug libraries on WorkShop by 3 times.
  183. * Fixed tag allocation for parent classes.
  184. * Fixed CObject allocation/deallocation in streams.
  185. * Moved instantiation of several templates in separate source file.
  186. *
  187. * Revision 1.47  2000/09/29 16:18:24  vasilche
  188. * Fixed binary format encoding/decoding on 64 bit compulers.
  189. * Implemented CWeakMap<> for automatic cleaning map entries.
  190. * Added cleaning local hooks via CWeakMap<>.
  191. * Renamed ReadTypeName -> ReadFileHeader, ENoTypeName -> ENoFileHeader.
  192. * Added some user interface methods to CObjectIStream, CObjectOStream and
  193. * CObjectStreamCopier.
  194. *
  195. * Revision 1.46  2000/09/26 17:38:22  vasilche
  196. * Fixed incomplete choiceptr implementation.
  197. * Removed temporary comments.
  198. *
  199. * Revision 1.45  2000/09/18 20:00:24  vasilche
  200. * Separated CVariantInfo and CMemberInfo.
  201. * Implemented copy hooks.
  202. * All hooks now are stored in CTypeInfo/CMemberInfo/CVariantInfo.
  203. * Most type specific functions now are implemented via function pointers instead of virtual functions.
  204. *
  205. * Revision 1.44  2000/09/01 13:16:19  vasilche
  206. * Implemented class/container/choice iterators.
  207. * Implemented CObjectStreamCopier for copying data without loading into memory.
  208. *
  209. * Revision 1.43  2000/08/15 19:44:50  vasilche
  210. * Added Read/Write hooks:
  211. * CReadObjectHook/CWriteObjectHook for objects of specified type.
  212. * CReadClassMemberHook/CWriteClassMemberHook for specified members.
  213. * CReadChoiceVariantHook/CWriteChoiceVariant for specified choice variants.
  214. * CReadContainerElementHook/CWriteContainerElementsHook for containers.
  215. *
  216. * Revision 1.42  2000/07/03 18:42:46  vasilche
  217. * Added interface to typeinfo via CObjectInfo and CConstObjectInfo.
  218. * Reduced header dependency.
  219. *
  220. * Revision 1.41  2000/06/16 16:31:21  vasilche
  221. * Changed implementation of choices and classes info to allow use of the same classes in generated and user written classes.
  222. *
  223. * Revision 1.40  2000/06/07 19:46:00  vasilche
  224. * Some code cleaning.
  225. * Macros renaming in more clear way.
  226. * BEGIN_NAMED_*_INFO, ADD_*_MEMBER, ADD_NAMED_*_MEMBER.
  227. *
  228. * Revision 1.39  2000/06/01 19:07:05  vasilche
  229. * Added parsing of XML data.
  230. *
  231. * Revision 1.38  2000/05/24 20:08:48  vasilche
  232. * Implemented XML dump.
  233. *
  234. * Revision 1.37  2000/05/09 19:04:56  vasilche
  235. * Fixed bug in storing float point number to text ASN.1 format.
  236. *
  237. * Revision 1.36  2000/04/28 16:58:13  vasilche
  238. * Added classes CByteSource and CByteSourceReader for generic reading.
  239. * Added delayed reading of choice variants.
  240. *
  241. * Revision 1.35  2000/04/13 14:50:27  vasilche
  242. * Added CObjectIStream::Open() and CObjectOStream::Open() for easier use.
  243. *
  244. * Revision 1.34  2000/04/06 16:11:00  vasilche
  245. * Fixed bug with iterators in choices.
  246. * Removed unneeded calls to ReadExternalObject/WriteExternalObject.
  247. * Added output buffering to text ASN.1 data.
  248. *
  249. * Revision 1.33  2000/02/17 20:02:45  vasilche
  250. * Added some standard serialization exceptions.
  251. * Optimized text/binary ASN.1 reading.
  252. * Fixed wrong encoding of StringStore in ASN.1 binary format.
  253. * Optimized logic of object collection.
  254. *
  255. * Revision 1.32  2000/02/01 21:47:23  vasilche
  256. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  257. * Added buffering to CObjectIStreamAsn.
  258. * Removed CMemberInfo subclasses.
  259. * Added support for DEFAULT/OPTIONAL members.
  260. *
  261. * Revision 1.31  2000/01/11 14:16:46  vasilche
  262. * Fixed pow ambiguity.
  263. *
  264. * Revision 1.30  2000/01/10 19:46:41  vasilche
  265. * Fixed encoding/decoding of REAL type.
  266. * Fixed encoding/decoding of StringStore.
  267. * Fixed encoding/decoding of NULL type.
  268. * Fixed error reporting.
  269. * Reduced object map (only classes).
  270. *
  271. * Revision 1.29  1999/12/17 19:05:04  vasilche
  272. * Simplified generation of GetTypeInfo methods.
  273. *
  274. * Revision 1.28  1999/10/25 20:19:51  vasilche
  275. * Fixed strings representation in text ASN.1 files.
  276. *
  277. * Revision 1.27  1999/10/04 16:22:18  vasilche
  278. * Fixed bug with old ASN.1 structures.
  279. *
  280. * Revision 1.26  1999/09/24 18:19:19  vasilche
  281. * Removed dependency on NCBI toolkit.
  282. *
  283. * Revision 1.25  1999/09/23 21:16:08  vasilche
  284. * Removed dependence on asn.h
  285. *
  286. * Revision 1.24  1999/09/23 20:25:04  vasilche
  287. * Added support HAVE_NCBI_C
  288. *
  289. * Revision 1.23  1999/09/23 18:57:01  vasilche
  290. * Fixed bugs with overloaded methods in objistr*.hpp & objostr*.hpp
  291. *
  292. * Revision 1.22  1999/08/13 20:22:58  vasilche
  293. * Fixed lot of bugs in datatool
  294. *
  295. * Revision 1.21  1999/08/13 15:53:52  vasilche
  296. * C++ analog of asntool: datatool
  297. *
  298. * Revision 1.20  1999/07/22 19:48:57  vasilche
  299. * Reversed hack with embedding old ASN.1 output to new.
  300. *
  301. * Revision 1.19  1999/07/22 19:40:57  vasilche
  302. * Fixed bug with complex object graphs (pointers to members of other objects).
  303. *
  304. * Revision 1.18  1999/07/22 17:33:56  vasilche
  305. * Unified reading/writing of objects in all three formats.
  306. *
  307. * Revision 1.17  1999/07/21 14:20:07  vasilche
  308. * Added serialization of bool.
  309. *
  310. * Revision 1.16  1999/07/20 18:23:12  vasilche
  311. * Added interface to old ASN.1 routines.
  312. * Added fixed choice of subclasses to use for pointers.
  313. *
  314. * Revision 1.15  1999/07/19 15:50:36  vasilche
  315. * Added interface to old ASN.1 routines.
  316. * Added naming of key/value in STL map.
  317. *
  318. * Revision 1.14  1999/07/15 19:35:30  vasilche
  319. * Implemented map<K, V>.
  320. * Changed ASN.1 text formatting.
  321. *
  322. * Revision 1.13  1999/07/15 16:54:49  vasilche
  323. * Implemented vector<X> & vector<char> as special case.
  324. *
  325. * Revision 1.12  1999/07/14 18:58:10  vasilche
  326. * Fixed ASN.1 types/field naming.
  327. *
  328. * Revision 1.11  1999/07/13 20:18:20  vasilche
  329. * Changed types naming.
  330. *
  331. * Revision 1.10  1999/07/09 16:32:54  vasilche
  332. * Added OCTET STRING write/read.
  333. *
  334. * Revision 1.9  1999/07/07 21:15:03  vasilche
  335. * Cleaned processing of string types (string, char*, const char*).
  336. *
  337. * Revision 1.8  1999/07/02 21:31:59  vasilche
  338. * Implemented reading from ASN.1 binary format.
  339. *
  340. * Revision 1.7  1999/07/01 17:55:34  vasilche
  341. * Implemented ASN.1 binary write.
  342. *
  343. * Revision 1.6  1999/06/30 16:05:00  vasilche
  344. * Added support for old ASN.1 structures.
  345. *
  346. * Revision 1.5  1999/06/24 14:44:58  vasilche
  347. * Added binary ASN.1 output.
  348. *
  349. * Revision 1.4  1999/06/18 16:26:49  vasilche
  350. * Fixed bug with unget() in MSVS
  351. *
  352. * Revision 1.3  1999/06/17 20:42:07  vasilche
  353. * Fixed storing/loading of pointers.
  354. *
  355. * Revision 1.2  1999/06/16 20:35:34  vasilche
  356. * Cleaned processing of blocks of data.
  357. * Added input from ASN.1 text format.
  358. *
  359. * Revision 1.1  1999/06/15 16:19:51  vasilche
  360. * Added ASN.1 object output stream.
  361. *
  362. * Revision 1.5  1999/06/10 21:06:49  vasilche
  363. * Working binary output and almost working binary input.
  364. *
  365. * Revision 1.4  1999/06/07 20:10:03  vasilche
  366. * Avoid using of numeric_limits.
  367. *
  368. * Revision 1.3  1999/06/07 19:30:27  vasilche
  369. * More bug fixes
  370. *
  371. * Revision 1.2  1999/06/04 20:51:47  vasilche
  372. * First compilable version of serialization.
  373. *
  374. * Revision 1.1  1999/05/19 19:56:55  vasilche
  375. * Commit just in case.
  376. *
  377. * ===========================================================================
  378. */
  379. #include <ncbi_pch.hpp>
  380. #include <corelib/ncbistd.hpp>
  381. #include <corelib/ncbi_limits.h>
  382. #include <serial/objostrasn.hpp>
  383. #include <serial/objistr.hpp>
  384. #include <serial/objcopy.hpp>
  385. #include <serial/memberid.hpp>
  386. #include <serial/enumvalues.hpp>
  387. #include <serial/memberlist.hpp>
  388. #include <serial/objhook.hpp>
  389. #include <serial/classinfo.hpp>
  390. #include <serial/choice.hpp>
  391. #include <serial/continfo.hpp>
  392. #include <serial/delaybuf.hpp>
  393. #include <stdio.h>
  394. #include <math.h>
  395. BEGIN_NCBI_SCOPE
  396. CObjectOStream* CObjectOStream::OpenObjectOStreamAsn(CNcbiOstream& out,
  397.                                                      bool deleteOut)
  398. {
  399.     return new CObjectOStreamAsn(out, deleteOut);
  400. }
  401. CObjectOStreamAsn::CObjectOStreamAsn(CNcbiOstream& out,
  402.                                      EFixNonPrint how)
  403.     : CObjectOStream(eSerial_AsnText, out), m_FixMethod(how)
  404. {
  405.     m_Output.SetBackLimit(80);
  406.     SetSeparator("n");
  407.     SetAutoSeparator(true);
  408. }
  409. CObjectOStreamAsn::CObjectOStreamAsn(CNcbiOstream& out,
  410.                                      bool deleteOut,
  411.                                      EFixNonPrint how)
  412.     : CObjectOStream(eSerial_AsnText, out, deleteOut), m_FixMethod(how)
  413. {
  414.     m_Output.SetBackLimit(80);
  415.     SetSeparator("n");
  416.     SetAutoSeparator(true);
  417. }
  418. CObjectOStreamAsn::~CObjectOStreamAsn(void)
  419. {
  420. }
  421. string CObjectOStreamAsn::GetPosition(void) const
  422. {
  423.     return "line "+NStr::UIntToString(m_Output.GetLine());
  424. }
  425. void CObjectOStreamAsn::WriteFileHeader(TTypeInfo type)
  426. {
  427.     if ( true || m_Output.ZeroIndentLevel() ) {
  428.         WriteId(type->GetName());
  429.         m_Output.PutString(" ::= ");
  430.     }
  431. }
  432. inline
  433. void CObjectOStreamAsn::WriteEnum(TEnumValueType value,
  434.                                   const string& valueName)
  435. {
  436.     if ( !valueName.empty() )
  437.         m_Output.PutString(valueName);
  438.     else
  439.         m_Output.PutInt4(value);
  440. }
  441. void CObjectOStreamAsn::WriteEnum(const CEnumeratedTypeValues& values,
  442.                                   TEnumValueType value)
  443. {
  444.     WriteEnum(value, values.FindName(value, values.IsInteger()));
  445. }
  446. void CObjectOStreamAsn::CopyEnum(const CEnumeratedTypeValues& values,
  447.                                  CObjectIStream& in)
  448. {
  449.     TEnumValueType value = in.ReadEnum(values);
  450.     WriteEnum(value, values.FindName(value, values.IsInteger()));
  451. }
  452. void CObjectOStreamAsn::WriteBool(bool data)
  453. {
  454.     if ( data )
  455.         m_Output.PutString("TRUE");
  456.     else
  457.         m_Output.PutString("FALSE");
  458. }
  459. void CObjectOStreamAsn::WriteChar(char data)
  460. {
  461.     m_Output.PutChar(''');
  462.     m_Output.PutChar(data);
  463.     m_Output.PutChar(''');
  464. }
  465. void CObjectOStreamAsn::WriteInt4(Int4 data)
  466. {
  467.     m_Output.PutInt4(data);
  468. }
  469. void CObjectOStreamAsn::WriteUint4(Uint4 data)
  470. {
  471.     m_Output.PutUint4(data);
  472. }
  473. void CObjectOStreamAsn::WriteInt8(Int8 data)
  474. {
  475.     m_Output.PutInt8(data);
  476. }
  477. void CObjectOStreamAsn::WriteUint8(Uint8 data)
  478. {
  479.     m_Output.PutUint8(data);
  480. }
  481. void CObjectOStreamAsn::WriteDouble2(double data, size_t digits)
  482. {
  483.     if (isnan(data)) {
  484.         ThrowError(fInvalidData, "invalid double: not a number");
  485.     }
  486.     if (!finite(data)) {
  487.         ThrowError(fInvalidData, "invalid double: infinite");
  488.     }
  489.     if ( data == 0.0 ) {
  490.         m_Output.PutString("{ 0, 10, 0 }");
  491.         return;
  492.     }
  493.     char buffer[128];
  494.     // ensure buffer is large enough to fit result
  495.     // (additional bytes are for sign, dot and exponent)
  496.     _ASSERT(sizeof(buffer) > digits + 16);
  497.     int width = sprintf(buffer, "%.*e", int(digits-1), data);
  498.     if ( width <= 0 || width >= int(sizeof(buffer) - 1) )
  499.         ThrowError(fOverflow, "buffer overflow");
  500.     _ASSERT(int(strlen(buffer)) == width);
  501.     char* dotPos = strchr(buffer, '.');
  502.     _ASSERT(dotPos);
  503.     char* ePos = strchr(dotPos, 'e');
  504.     _ASSERT(ePos);
  505.     // now we have:
  506.     // mantissa with dot - buffer:ePos
  507.     // exponent - (ePos+1):
  508.     int exp;
  509.     // calculate exponent
  510.     if ( sscanf(ePos + 1, "%d", &exp) != 1 )
  511.         ThrowError(fFail, "double value conversion error");
  512.     // remove trailing zeroes
  513.     int fractDigits = int(ePos - dotPos - 1);
  514.     while ( fractDigits > 0 && ePos[-1] == '0' ) {
  515.         --ePos;
  516.         --fractDigits;
  517.     }
  518.     // now we have:
  519.     // mantissa with dot without trailing zeroes - buffer:ePos
  520.     m_Output.PutString("{ ");
  521.     m_Output.PutString(buffer, dotPos - buffer);
  522.     m_Output.PutString(dotPos + 1, fractDigits);
  523.     m_Output.PutString(", 10, ");
  524.     m_Output.PutInt4(exp - fractDigits);
  525.     m_Output.PutString(" }");
  526. }
  527. void CObjectOStreamAsn::WriteDouble(double data)
  528. {
  529.     WriteDouble2(data, DBL_DIG);
  530. }
  531. void CObjectOStreamAsn::WriteFloat(float data)
  532. {
  533.     WriteDouble2(data, FLT_DIG);
  534. }
  535. void CObjectOStreamAsn::WriteNull(void)
  536. {
  537.     m_Output.PutString("NULL");
  538. }
  539. void CObjectOStreamAsn::WriteAnyContentObject(const CAnyContentObject& )
  540. {
  541.     NCBI_THROW(CSerialException,eNotImplemented,
  542.         "CObjectOStreamAsn::WriteAnyContentObject: "
  543.         "unable to write AnyContent object in ASN");
  544. }
  545. void CObjectOStreamAsn::CopyAnyContentObject(CObjectIStream& )
  546. {
  547.     NCBI_THROW(CSerialException,eNotImplemented,
  548.         "CObjectOStreamAsn::CopyAnyContentObject: "
  549.         "unable to copy AnyContent object in ASN");
  550. }
  551. void CObjectOStreamAsn::WriteString(const char* ptr, size_t length)
  552. {
  553.     size_t startLine = m_Output.GetLine();
  554.     m_Output.PutChar('"');
  555.     while ( length > 0 ) {
  556.         char c = *ptr++;
  557.         FixVisibleChar(c, m_FixMethod, startLine);
  558.         --length;
  559.         m_Output.WrapAt(78, true);
  560.         m_Output.PutChar(c);
  561.         if ( c == '"' )
  562.             m_Output.PutChar('"');
  563.     }
  564.     m_Output.PutChar('"');
  565. }
  566. void CObjectOStreamAsn::WriteCString(const char* str)
  567. {
  568.     if ( str == 0 ) {
  569.         WriteNull();
  570.     }
  571.     else {
  572.         WriteString(str, strlen(str));
  573.     }
  574. }
  575. void CObjectOStreamAsn::WriteString(const string& str, EStringType type)
  576. {
  577.     EFixNonPrint fix = m_FixMethod;
  578.     if (type == eStringTypeUTF8) {
  579.         m_FixMethod = eFNP_Allow;
  580.     }
  581.     WriteString(str.data(), str.size());
  582.     m_FixMethod = fix;
  583. }
  584. void CObjectOStreamAsn::WriteStringStore(const string& str)
  585. {
  586.     WriteString(str.data(), str.size());
  587. }
  588. void CObjectOStreamAsn::CopyString(CObjectIStream& in)
  589. {
  590.     string s;
  591.     in.ReadStd(s);
  592.     WriteString(s.data(), s.size());
  593. }
  594. void CObjectOStreamAsn::CopyStringStore(CObjectIStream& in)
  595. {
  596.     string s;
  597.     in.ReadStringStore(s);
  598.     WriteString(s.data(), s.size());
  599. }
  600. void CObjectOStreamAsn::WriteId(const string& str)
  601. {
  602.     if ( str.find(' ') != NPOS || str.find('<') != NPOS ||
  603.          str.find(':') != NPOS ) {
  604.         m_Output.PutChar('[');
  605.         m_Output.PutString(str);
  606.         m_Output.PutChar(']');
  607.     }
  608.     else {
  609.         m_Output.PutString(str);
  610.     }
  611. }
  612. void CObjectOStreamAsn::WriteNullPointer(void)
  613. {
  614.     m_Output.PutString("NULL");
  615. }
  616. void CObjectOStreamAsn::WriteObjectReference(TObjectIndex index)
  617. {
  618.     m_Output.PutChar('@');
  619.     if ( sizeof(TObjectIndex) == sizeof(Int4) )
  620.         m_Output.PutInt4(Int4(index));
  621.     else if ( sizeof(TObjectIndex) == sizeof(Int8) )
  622.         m_Output.PutInt8(index);
  623.     else
  624.         ThrowError(fIllegalCall, "invalid size of TObjectIndex: "
  625.             "must be either sizeof(Int4) or sizeof(Int8)");
  626. }
  627. void CObjectOStreamAsn::WriteOtherBegin(TTypeInfo typeInfo)
  628. {
  629.     m_Output.PutString(": ");
  630.     WriteId(typeInfo->GetName());
  631.     m_Output.PutChar(' ');
  632. }
  633. void CObjectOStreamAsn::WriteOther(TConstObjectPtr object,
  634.                                    TTypeInfo typeInfo)
  635. {
  636.     m_Output.PutString(": ");
  637.     WriteId(typeInfo->GetName());
  638.     m_Output.PutChar(' ');
  639.     WriteObject(object, typeInfo);
  640. }
  641. void CObjectOStreamAsn::StartBlock(void)
  642. {
  643.     m_Output.PutChar('{');
  644.     m_Output.IncIndentLevel();
  645.     m_BlockStart = true;
  646. }
  647. void CObjectOStreamAsn::EndBlock(void)
  648. {
  649.     m_Output.DecIndentLevel();
  650.     m_Output.PutEol();
  651.     m_Output.PutChar('}');
  652.     m_BlockStart = false;
  653. }
  654. void CObjectOStreamAsn::NextElement(void)
  655. {
  656.     if ( m_BlockStart )
  657.         m_BlockStart = false;
  658.     else
  659.         m_Output.PutChar(',');
  660.     m_Output.PutEol();
  661. }
  662. void CObjectOStreamAsn::BeginContainer(const CContainerTypeInfo* /*cType*/)
  663. {
  664.     StartBlock();
  665. }
  666. void CObjectOStreamAsn::EndContainer(void)
  667. {
  668.     EndBlock();
  669. }
  670. void CObjectOStreamAsn::BeginContainerElement(TTypeInfo /*elementType*/)
  671. {
  672.     NextElement();
  673. }
  674. #ifdef VIRTUAL_MID_LEVEL_IO
  675. void CObjectOStreamAsn::WriteContainer(const CContainerTypeInfo* cType,
  676.                                        TConstObjectPtr containerPtr)
  677. {
  678.     BEGIN_OBJECT_FRAME2(eFrameArray, cType);
  679.     StartBlock();
  680.     
  681.     CContainerTypeInfo::CConstIterator i;
  682.     if ( cType->InitIterator(i, containerPtr) ) {
  683.         TTypeInfo elementType = cType->GetElementType();
  684.         BEGIN_OBJECT_FRAME2(eFrameArrayElement, elementType);
  685.         do {
  686.             if (elementType->GetTypeFamily() == eTypeFamilyPointer) {
  687.                 const CPointerTypeInfo* pointerType =
  688.                     CTypeConverter<CPointerTypeInfo>::SafeCast(elementType);
  689.                 _ASSERT(pointerType->GetObjectPointer(cType->GetElementPtr(i)));
  690.                 if ( !pointerType->GetObjectPointer(cType->GetElementPtr(i)) ) {
  691.                     ERR_POST(Warning << " NULL pointer found in container: skipping");
  692.                     continue;
  693.                 }
  694.             }
  695.             NextElement();
  696.             WriteObject(cType->GetElementPtr(i), elementType);
  697.         } while ( cType->NextElement(i) );
  698.         
  699.         END_OBJECT_FRAME();
  700.     }
  701.     EndBlock();
  702.     END_OBJECT_FRAME();
  703. }
  704. void CObjectOStreamAsn::CopyContainer(const CContainerTypeInfo* cType,
  705.                                       CObjectStreamCopier& copier)
  706. {
  707.     BEGIN_OBJECT_FRAME_OF2(copier.In(), eFrameArray, cType);
  708.     copier.In().BeginContainer(cType);
  709.     StartBlock();
  710.     TTypeInfo elementType = cType->GetElementType();
  711.     BEGIN_OBJECT_2FRAMES_OF2(copier, eFrameArrayElement, elementType);
  712.     while ( copier.In().BeginContainerElement(elementType) ) {
  713.         NextElement();
  714.         CopyObject(elementType, copier);
  715.         copier.In().EndContainerElement();
  716.     }
  717.     END_OBJECT_2FRAMES_OF(copier);
  718.     
  719.     EndBlock();
  720.     copier.In().EndContainer();
  721.     END_OBJECT_FRAME_OF(copier.In());
  722. }
  723. #endif
  724. void CObjectOStreamAsn::WriteMemberId(const CMemberId& id)
  725. {
  726.     if ( !id.GetName().empty() ) {
  727.         m_Output.PutString(id.GetName());
  728.         m_Output.PutChar(' ');
  729.     }
  730.     else if ( id.HaveExplicitTag() ) {
  731.         m_Output.PutString("[" + NStr::IntToString(id.GetTag()) + "] ");
  732.     }
  733. }
  734. void CObjectOStreamAsn::BeginClass(const CClassTypeInfo* /*classInfo*/)
  735. {
  736.     StartBlock();
  737. }
  738. void CObjectOStreamAsn::EndClass(void)
  739. {
  740.     EndBlock();
  741. }
  742. void CObjectOStreamAsn::BeginClassMember(const CMemberId& id)
  743. {
  744.     NextElement();
  745.     WriteMemberId(id);
  746. }
  747. #ifdef VIRTUAL_MID_LEVEL_IO
  748. void CObjectOStreamAsn::WriteClass(const CClassTypeInfo* classType,
  749.                                    TConstObjectPtr classPtr)
  750. {
  751.     StartBlock();
  752.     
  753.     for ( CClassTypeInfo::CIterator i(classType); i.Valid(); ++i ) {
  754.         classType->GetMemberInfo(*i)->WriteMember(*this, classPtr);
  755.     }
  756.     
  757.     EndBlock();
  758. }
  759. void CObjectOStreamAsn::WriteClassMember(const CMemberId& memberId,
  760.                                          TTypeInfo memberType,
  761.                                          TConstObjectPtr memberPtr)
  762. {
  763.     NextElement();
  764.     BEGIN_OBJECT_FRAME2(eFrameClassMember, memberId);
  765.     
  766.     WriteMemberId(memberId);
  767.     
  768.     WriteObject(memberPtr, memberType);
  769.     END_OBJECT_FRAME();
  770. }
  771. bool CObjectOStreamAsn::WriteClassMember(const CMemberId& memberId,
  772.                                          const CDelayBuffer& buffer)
  773. {
  774.     if ( !buffer.HaveFormat(eSerial_AsnText) )
  775.         return false;
  776.     NextElement();
  777.     BEGIN_OBJECT_FRAME2(eFrameClassMember, memberId);
  778.     
  779.     WriteMemberId(memberId);
  780.     
  781.     Write(buffer.GetSource());
  782.     END_OBJECT_FRAME();
  783.     return true;
  784. }
  785. void CObjectOStreamAsn::CopyClassRandom(const CClassTypeInfo* classType,
  786.                                         CObjectStreamCopier& copier)
  787. {
  788.     BEGIN_OBJECT_FRAME_OF2(copier.In(), eFrameClass, classType);
  789.     copier.In().BeginClass(classType);
  790.     StartBlock();
  791.     vector<bool> read(classType->GetMembers().LastIndex() + 1);
  792.     BEGIN_OBJECT_2FRAMES_OF(copier, eFrameClassMember);
  793.     TMemberIndex index;
  794.     while ( (index = copier.In().BeginClassMember(classType)) !=
  795.             kInvalidMember ) {
  796.         const CMemberInfo* memberInfo = classType->GetMemberInfo(index);
  797.         copier.In().SetTopMemberId(memberInfo->GetId());
  798.         SetTopMemberId(memberInfo->GetId());
  799.         if ( read[index] ) {
  800.             copier.DuplicatedMember(memberInfo);
  801.         }
  802.         else {
  803.             read[index] = true;
  804.             NextElement();
  805.             WriteMemberId(memberInfo->GetId());
  806.             memberInfo->CopyMember(copier);
  807.         }
  808.         
  809.         copier.In().EndClassMember();
  810.     }
  811.     END_OBJECT_2FRAMES_OF(copier);
  812.     // init all absent members
  813.     for ( CClassTypeInfo::CIterator i(classType); i.Valid(); ++i ) {
  814.         if ( !read[*i] ) {
  815.             classType->GetMemberInfo(*i)->CopyMissingMember(copier);
  816.         }
  817.     }
  818.     EndBlock();
  819.     copier.In().EndClass();
  820.     END_OBJECT_FRAME_OF(copier.In());
  821. }
  822. void CObjectOStreamAsn::CopyClassSequential(const CClassTypeInfo* classType,
  823.                                             CObjectStreamCopier& copier)
  824. {
  825.     BEGIN_OBJECT_FRAME_OF2(copier.In(), eFrameClass, classType);
  826.     copier.In().BeginClass(classType);
  827.     StartBlock();
  828.     CClassTypeInfo::CIterator pos(classType);
  829.     BEGIN_OBJECT_2FRAMES_OF(copier, eFrameClassMember);
  830.     TMemberIndex index;
  831.     while ( (index = copier.In().BeginClassMember(classType, *pos)) !=
  832.             kInvalidMember ) {
  833.         const CMemberInfo* memberInfo = classType->GetMemberInfo(index);
  834.         copier.In().SetTopMemberId(memberInfo->GetId());
  835.         SetTopMemberId(memberInfo->GetId());
  836.         for ( TMemberIndex i = *pos; i < index; ++i ) {
  837.             // init missing member
  838.             classType->GetMemberInfo(i)->CopyMissingMember(copier);
  839.         }
  840.         NextElement();
  841.         WriteMemberId(memberInfo->GetId());
  842.         
  843.         memberInfo->CopyMember(copier);
  844.         
  845.         pos.SetIndex(index + 1);
  846.         copier.In().EndClassMember();
  847.     }
  848.     END_OBJECT_2FRAMES_OF(copier);
  849.     // init all absent members
  850.     for ( ; pos.Valid(); ++pos ) {
  851.         classType->GetMemberInfo(*pos)->CopyMissingMember(copier);
  852.     }
  853.     EndBlock();
  854.     copier.In().EndClass();
  855.     END_OBJECT_FRAME_OF(copier.In());
  856. }
  857. #endif
  858. void CObjectOStreamAsn::BeginChoiceVariant(const CChoiceTypeInfo* ,
  859.                                            const CMemberId& id)
  860. {
  861.     WriteMemberId(id);
  862. }
  863. #ifdef VIRTUAL_MID_LEVEL_IO
  864. void CObjectOStreamAsn::WriteChoice(const CChoiceTypeInfo* choiceType,
  865.                                     TConstObjectPtr choicePtr)
  866. {
  867.     TMemberIndex index = choiceType->GetIndex(choicePtr);
  868.     const CVariantInfo* variantInfo = choiceType->GetVariantInfo(index);
  869.     BEGIN_OBJECT_FRAME2(eFrameChoiceVariant, variantInfo->GetId());
  870.     WriteMemberId(variantInfo->GetId());
  871.     
  872.     variantInfo->WriteVariant(*this, choicePtr);
  873.     END_OBJECT_FRAME();
  874. }
  875. void CObjectOStreamAsn::CopyChoice(const CChoiceTypeInfo* choiceType,
  876.                                    CObjectStreamCopier& copier)
  877. {
  878.     BEGIN_OBJECT_FRAME_OF2(copier.In(), eFrameChoice, choiceType);
  879.     copier.In().BeginChoice(choiceType);
  880.     BEGIN_OBJECT_2FRAMES_OF(copier, eFrameChoiceVariant);
  881.     TMemberIndex index = copier.In().BeginChoiceVariant(choiceType);
  882.     if ( index == kInvalidMember ) {
  883.         copier.ThrowError(CObjectIStream::fFormatError,
  884.                           "choice variant id expected");
  885.     }
  886.     const CVariantInfo* variantInfo = choiceType->GetVariantInfo(index);
  887.     copier.In().SetTopMemberId(variantInfo->GetId());
  888.     copier.Out().SetTopMemberId(variantInfo->GetId());
  889.     WriteMemberId(variantInfo->GetId());
  890.     variantInfo->CopyVariant(copier);
  891.     copier.In().EndChoiceVariant();
  892.     END_OBJECT_2FRAMES_OF(copier);
  893.     copier.In().EndChoice();
  894.     END_OBJECT_FRAME_OF(copier.In());
  895. }
  896. #endif
  897. void CObjectOStreamAsn::BeginBytes(const ByteBlock& )
  898. {
  899.     m_Output.PutChar(''');
  900. }
  901. static const char HEX[] = "0123456789ABCDEF";
  902. void CObjectOStreamAsn::WriteBytes(const ByteBlock& ,
  903.                                    const char* bytes, size_t length)
  904. {
  905.     while ( length-- > 0 ) {
  906.         char c = *bytes++;
  907.         m_Output.WrapAt(78, false);
  908.         m_Output.PutChar(HEX[(c >> 4) & 0xf]);
  909.         m_Output.PutChar(HEX[c & 0xf]);
  910.     }
  911. }
  912. void CObjectOStreamAsn::EndBytes(const ByteBlock& )
  913. {
  914.     m_Output.WrapAt(78, false);
  915.     m_Output.PutString("'H");
  916. }
  917. void CObjectOStreamAsn::BeginChars(const CharBlock& )
  918. {
  919.     m_Output.PutChar('"');
  920. }
  921. void CObjectOStreamAsn::WriteChars(const CharBlock& ,
  922.                                    const char* chars, size_t length)
  923. {
  924.     while ( length > 0 ) {
  925.         char c = *chars++;
  926.         FixVisibleChar(c, m_FixMethod, m_Output.GetLine());
  927.         --length;
  928.         m_Output.WrapAt(78, true);
  929.         m_Output.PutChar(c);
  930.         if ( c == '"' )
  931.             m_Output.PutChar('"');
  932.     }
  933. }
  934. void CObjectOStreamAsn::EndChars(const CharBlock& )
  935. {
  936.     m_Output.WrapAt(78, false);
  937.     m_Output.PutChar('"');
  938. }
  939. void CObjectOStreamAsn::WriteSeparator(void)
  940. {
  941.     m_Output.PutString(GetSeparator());
  942.     FlushBuffer();
  943. }
  944. END_NCBI_SCOPE