1 #ifndef OBJOSTR__HPP
2 #define OBJOSTR__HPP
3 
4 /*  $Id: objostr.hpp 574303 2018-11-08 19:59:04Z gouriano $
5 * ===========================================================================
6 *
7 *                            PUBLIC DOMAIN NOTICE
8 *               National Center for Biotechnology Information
9 *
10 *  This software/database is a "United States Government Work" under the
11 *  terms of the United States Copyright Act.  It was written as part of
12 *  the author's official duties as a United States Government employee and
13 *  thus cannot be copyrighted.  This software/database is freely available
14 *  to the public for use. The National Library of Medicine and the U.S.
15 *  Government have not placed any restriction on its use or reproduction.
16 *
17 *  Although all reasonable efforts have been taken to ensure the accuracy
18 *  and reliability of the software and data, the NLM and the U.S.
19 *  Government do not and cannot warrant the performance or results that
20 *  may be obtained by using this software or data. The NLM and the U.S.
21 *  Government disclaim all warranties, express or implied, including
22 *  warranties of performance, merchantability or fitness for any particular
23 *  purpose.
24 *
25 *  Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Eugene Vasilchenko
30 *
31 * File Description:
32 *   Base class of object output stream classes
33 *   Having a data object, it encodes it and saves in an output stream
34 */
35 
36 #include <corelib/ncbistd.hpp>
37 #include <corelib/ncbifloat.h>
38 #include <corelib/ncbiobj.hpp>
39 #include <corelib/ncbiutil.hpp>
40 #include <util/strbuffer.hpp>
41 #include <serial/impl/objlist.hpp>
42 #include <serial/impl/hookdatakey.hpp>
43 #include <serial/objhook.hpp>
44 #include <serial/impl/pathhook.hpp>
45 #include <serial/error_codes.hpp>
46 
47 
48 /** @addtogroup ObjStreamSupport
49  *
50  * @{
51  */
52 
53 
54 struct asnio;
55 
56 BEGIN_NCBI_SCOPE
57 
58 class CMemberId;
59 class CDelayBuffer;
60 
61 class CConstObjectInfo;
62 class CConstObjectInfoMI;
63 
64 class CWriteObjectHook;
65 class CWriteClassMembersHook;
66 class CWriteChoiceVariantHook;
67 
68 class CContainerTypeInfo;
69 class CClassTypeInfo;
70 class CChoiceTypeInfo;
71 class CObjectStreamCopier;
72 class CAliasTypeInfo;
73 
74 class CWriteObjectInfo;
75 class CWriteObjectList;
76 
77 /////////////////////////////////////////////////////////////////////////////
78 ///
79 /// CObjectOStream --
80 ///
81 /// Base class of serial object stream encoders
82 class NCBI_XSERIAL_EXPORT CObjectOStream : public CObjectStack
83 {
84 public:
85     /// Destructor.
86     ///
87     /// Constructors are protected;
88     /// use any one of 'Create' methods to construct the stream
89     virtual ~CObjectOStream(void);
90 
91 //---------------------------------------------------------------------------
92 // Create methods
93     // CObjectOStream will be created on heap, and must be deleted later on
94 
95     /// Create serial object writer and attach it to an output stream.
96     ///
97     /// @param format
98     ///   Format of the output data
99     /// @param outStream
100     ///   Output stream
101     /// @param deleteOutStream
102     ///   When TRUE, the output stream will be deleted automatically
103     ///   when the writer is deleted
104     /// @return
105     ///   Writer (created on heap)
106     /// @deprecated
107     ///   Use one with EOwnership enum instead
108     static NCBI_DEPRECATED CObjectOStream* Open(ESerialDataFormat format,
109                                 CNcbiOstream& outStream,
110                                 bool deleteOutStream);
111 
112     /// Create serial object writer and attach it to an output stream.
113     ///
114     /// @param format
115     ///   Format of the output data
116     /// @param outStream
117     ///   Output stream
118     /// @param deleteOutStream
119     ///   When eTakeOwnership, the output stream will be deleted automatically
120     ///   when the writer is deleted
121     /// @param formatFlags
122     ///   Formatting flags (see ESerial_xxx_Flags)
123     /// @return
124     ///   Writer (created on heap)
125     /// @sa ESerial_AsnText_Flags, ESerial_Xml_Flags, ESerial_Json_Flags
126     static CObjectOStream* Open(ESerialDataFormat format,
127                                 CNcbiOstream& outStream,
128                                 EOwnership deleteOutStream = eNoOwnership,
129                                 TSerial_Format_Flags formatFlags = 0);
130 
131     /// Create serial object writer and attach it to a file stream.
132     ///
133     /// @param format
134     ///   Format of the output data
135     /// @param fileName
136     ///   Output file name
137     /// @param openFlags
138     ///   File open flags
139     /// @param formatFlags
140     ///   Formatting flags (see ESerial_xxx_Flags)
141     /// @return
142     ///   Writer (created on heap)
143     /// @sa ESerialOpenFlags, ESerial_AsnText_Flags, ESerial_Xml_Flags, ESerial_Json_Flags
144     static CObjectOStream* Open(ESerialDataFormat format,
145                                 const string& fileName,
146                                 TSerialOpenFlags openFlags = 0,
147                                 TSerial_Format_Flags formatFlags = 0);
148 
149     /// Create serial object writer and attach it to a file stream.
150     ///
151     /// @param fileName
152     ///   Output file name
153     /// @param format
154     ///   Format of the output data
155     /// @param formatFlags
156     ///   Formatting flags (see ESerial_xxx_Flags)
157     /// @return
158     ///   Writer (created on heap)
159     /// @sa ESerial_AsnText_Flags, ESerial_Xml_Flags, ESerial_Json_Flags
160     static CObjectOStream* Open(const string& fileName,
161                                 ESerialDataFormat format,
162                                 TSerial_Format_Flags formatFlags = 0);
163 
164     /// Get data format
165     ///
166     /// @return
167     ///   Output data format
168     ESerialDataFormat GetDataFormat(void) const;
169 
170 //---------------------------------------------------------------------------
171 // Data verification setup
172 
173     // for this particular stream
174     /// Set up output data verification for this particular stream
175     ///
176     /// @param verify
177     ///   Data verification parameter
178     void SetVerifyData(ESerialVerifyData verify);
179 
180     /// Get output data verification parameter.
181     ///
182     /// When verification is enabled, stream verifies data on output
183     /// and throws CUnassignedMember exception
184     ///
185     /// @return
186     ///   Data verification parameter
187     ESerialVerifyData GetVerifyData(void) const;
188 
189     /// Set up default output data verification for streams
190     /// created by the current thread
191     ///
192     /// @param verify
193     ///   Data verification parameter
194     static  void SetVerifyDataThread(ESerialVerifyData verify);
195 
196     /// Set up default output data verification for streams
197     /// created by the current process
198     ///
199     /// @param verify
200     ///   Data verification parameter
201     static  void SetVerifyDataGlobal(ESerialVerifyData verify);
202 
FixNonPrint(EFixNonPrint how)203     EFixNonPrint FixNonPrint(EFixNonPrint how)
204     {
205         EFixNonPrint tmp = m_FixMethod;
206         m_FixMethod = how == eFNP_Default ? x_GetFixCharsMethodDefault() : how;
207         return tmp;
208     }
FixNonPrintSubst(char subst)209     void FixNonPrintSubst(char subst) {
210         m_NonPrintSubst = subst;
211     }
212 
213     // Enforce explicit writing of values with default,
214     // even when they were never set
215     //
216     // This is dangerous, and contradicts specification
217     // but might be useful to make sure defaults are properly reported to recipient
218     // Use at your own risk
219     void EnforceWritingDefaultValues(bool enforce = true);
220 
221     // Is explicit writing of values with default enforced
222     bool IsWritingDefaultValuesEnforced() const;
223 
224 //---------------------------------------------------------------------------
225 // Formatting of the output
226 
227     /// Set up indentation usage in text streams.
228     ///
229     /// @param set
230     ///   When TRUE, the writer puts white space chars in the beginning
231     ///   of each line of text
232     void SetUseIndentation(bool set);
233 
234     /// Get indentation usage in text streams.
235     ///
236     /// @return
237     ///   TRUE or FALSE
238     bool GetUseIndentation(void) const;
239 
240     /// Set up end-of-line symbol usage in text streams.
241     ///
242     /// @param set
243     ///   When TRUE, the writer puts end-of-line symbol where needed,
244     ///   otherwise, the output is a single line.
245     void SetUseEol(bool set);
246 
247     /// Get end-of-line symbol usage in text streams.
248     ///
249     /// @return
250     ///   TRUE or FALSE
251     bool GetUseEol(void) const;
252 
253     /// Set up writing named integers (in ANS.1 sense) by value only.
254     ///
255     /// The setting affects text streams only and is provided
256     /// for convenience: so that legacy applications can read data files
257     /// generated by newer ones.
258     ///
259     /// @param set
260     ///   When TRUE, the writer does not write the name of the value,
261     ///   but only its numeric value instead
262     void SetWriteNamedIntegersByValue(bool set);
263 
264     /// Get writing named integers by value parameter
265     ///
266     /// @return
267     ///   TRUE or FALSE
268     bool GetWriteNamedIntegersByValue(void) const;
269 
270     /// Get separator.
271     ///
272     /// @return
273     ///   Separator string
274     string GetSeparator(void) const;
275 
276     /// Set separator.
277     ///
278     /// Separator string is written into text stream after each object
279     ///
280     /// @param sep
281     ///   Separator string
282     void SetSeparator(const string sep);
283 
284     /// Get separator auto-output paramater
285     ///
286     /// Controls auto-output of the separator after each object. By default
287     /// this flag is true for text ASN.1 streams only.
288     ///
289     /// @return
290     ///   TRUE or FALSE
291     bool GetAutoSeparator(void);
292 
293     /// Set separator auto-output paramater.
294     ///
295     /// When TRUE, writer puts separator string after each object. By default
296     /// this flag is TRUE for text ASN.1 streams only.
297     ///
298     /// @param value
299     ///   TRUE or FALSE
300     void SetAutoSeparator(bool value);
301 
302     /// Set output formatting flags
303     ///
304     /// @param flags
305     ///   Formatting flag
306     virtual void SetFormattingFlags(TSerial_Format_Flags flags);
307 
308 //---------------------------------------------------------------------------
309 // Stream state
310 
311     /// Fail flags
312     enum EFailFlags {
313         /// No error
314         fNoError       = 0,             eNoError     = fNoError,
315 //        fEOF           = 1 << 0,        eEOF         = fEOF,
316         /// An unknown error when writing into output file
317         fWriteError    = 1 << 1,        eWriteError  = fWriteError,
318 //        fFormatError   = 1 << 2,        eFormatError = fFormatError,
319         /// Internal buffer overflow
320         fOverflow      = 1 << 3,        eOverflow    = fOverflow,
321         /// Output data is incorrect
322         fInvalidData   = 1 << 4,        eInvalidData = fInvalidData,
323         /// Illegal in a given context function call
324         fIllegalCall   = 1 << 5,        eIllegalCall = fIllegalCall,
325         /// Internal error, the real reason is unclear
326         fFail          = 1 << 6,        eFail        = fFail,
327         /// No output file
328         fNotOpen       = 1 << 7,        eNotOpen     = fNotOpen,
329         /// Method is not implemented
330         fNotImplemented= 1 << 8,        eNotImplemented = fNotImplemented,
331         /// Mandatory object member is unassigned
332         /// Normally this results in throwing CUnassignedMember exception
333         fUnassigned    = 1 << 9,        eUnassigned  = fUnassigned
334     };
335     typedef int TFailFlags;
336 
337     /// Check if any of fail flags is set.
338     ///
339     /// @return
340     ///   TRUE or FALSE
341     bool fail(void) const;
342 
343     /// Get fail flags.
344     ///
345     /// @return
346     ///   Fail flags
347     TFailFlags GetFailFlags(void) const;
348 
349     /// Set fail flags, but do not ERR_POST any messages
350     ///
351     /// @param flags
352     ///   Fail flags
353     TFailFlags SetFailFlagsNoError(TFailFlags flags);
354 
355     /// Set fail flags
356     ///
357     /// @param flags
358     ///   Fail flags
359     /// @param message
360     ///   Text message
361     TFailFlags SetFailFlags(TFailFlags flags, const char* message);
362 
363     /// Reset fail flags
364     ///
365     /// @param flags
366     ///   Flags to reset
367     TFailFlags ClearFailFlags(TFailFlags flags);
368 
369     /// Check fail flags and also the state of output stream
370     ///
371     /// @return
372     ///   TRUE is there is no errors
373     bool InGoodState(void);
374 
375     /// Set cancellation check callback.
376     /// The stream will periodically check for a cancellation request and
377     /// throw an exception when requested.
378     void SetCanceledCallback(const ICanceled* callback);
379 
380     /// @deprecated
381     ///   Use GetStreamPos() instead
382     /// @sa GetStreamPos()
383     NCBI_DEPRECATED CNcbiStreampos GetStreamOffset(void) const;
384 
385     /// Get the current stream position
386     ///
387     /// NOTE:
388     ///   This is not the same as ostream::tellp();
389     ///   rather, this is an offset in the current output
390     ///
391     /// @return
392     ///   stream position
393     CNcbiStreampos GetStreamPos(void) const;
394 
395     /// Get current stack trace as string.
396     /// Useful for diagnostic and information messages.
397     ///
398     /// @return
399     ///   string
400     virtual string GetStackTrace(void) const override;
401 
402     /// Get current stream position as string.
403     /// Useful for diagnostic and information messages.
404     ///
405     /// @return
406     ///   string
407     virtual string GetPosition(void) const override;
408 
409 //---------------------------------------------------------------------------
410 // Local write hooks
411     void SetPathWriteObjectHook( const string& path, CWriteObjectHook*        hook);
412     void SetPathWriteMemberHook( const string& path, CWriteClassMemberHook*   hook);
413     void SetPathWriteVariantHook(const string& path, CWriteChoiceVariantHook* hook);
414 
415     /// DelayBuffer parsing policy
416     enum EDelayBufferParsing {
417         /// Parse only if local hook are present
418         eDelayBufferPolicyNotSet,
419         /// Parse always
420         eDelayBufferPolicyAlwaysParse,
421         /// Never parse
422         eDelayBufferPolicyNeverParse
423     };
424     void SetDelayBufferParsingPolicy(EDelayBufferParsing policy);
425     EDelayBufferParsing GetDelayBufferParsingPolicy(void) const;
426     bool ShouldParseDelayBuffer(void) const;
427 
428 //---------------------------------------------------------------------------
429 // User interface
430     // flush buffer
431     void FlushBuffer(void);
432     // flush buffer and underlying stream
433     void Flush(void);
434     // perform default flush defined by flags
435     void DefaultFlush(void);
436 
437     // root writer
438     void Write(const CConstObjectInfo& object);
439     void Write(TConstObjectPtr object, TTypeInfo type);
440     void Write(TConstObjectPtr object, const CTypeRef& type);
441 
442     // file header
443     virtual void WriteFileHeader(TTypeInfo type);
444 
445     // subtree writer
446     void WriteObject(const CConstObjectInfo& object);
447     void WriteObject(TConstObjectPtr object, TTypeInfo typeInfo);
448 
449     void CopyObject(TTypeInfo objectType,
450                     CObjectStreamCopier& copier);
451 
452     void WriteSeparateObject(const CConstObjectInfo& object);
453 
454     // internal writer
455     void WriteExternalObject(TConstObjectPtr object, TTypeInfo typeInfo);
456 
457     // member interface
458     void WriteClassMember(const CConstObjectInfoMI& member);
459 
460     // choice variant interface
461     void WriteChoiceVariant(const CConstObjectInfoCV& member);
462 
463 
464     CObjectOStream& operator<< (CObjectOStream& (*mod)(CObjectOStream& os));
465     friend CObjectOStream& Separator(CObjectOStream& os);
466 
467 //---------------------------------------------------------------------------
468 // Standard types
469     // bool
470     void WriteStd(const bool& data);
471 
472     // char
473     void WriteStd(const char& data);
474 
475     // integer number
476     void WriteStd(const signed char& data);
477     void WriteStd(const unsigned char& data);
478     void WriteStd(const short& data);
479     void WriteStd(const unsigned short& data);
480     void WriteStd(const int& data);
481     void WriteStd(const unsigned int& data);
482 #ifndef NCBI_INT8_IS_LONG
483     void WriteStd(const long& data);
484     void WriteStd(const unsigned long& data);
485 #endif
486     void WriteStd(const Int8& data);
487     void WriteStd(const Uint8& data);
488 
489     // float number
490     void WriteStd(const float& data);
491     void WriteStd(const double& data);
492 #if SIZEOF_LONG_DOUBLE != 0
493     void WriteStd(const long double& data);
494 #endif
495 
496     // string
497     void WriteStd(const string& data);
498 
499     // C string; VisualAge can't cope with refs here.
500     void WriteStd(const char* const data);
501     void WriteStd(char* const data);
502 
503     void WriteStd(const CBitString& data);
504 
505     // primitive writers
506     // bool
507     virtual void WriteBool(bool data) = 0;
508 
509     // char
510     virtual void WriteChar(char data) = 0;
511 
512     // integer numbers
513     virtual void WriteInt4(Int4 data) = 0;
514     virtual void WriteUint4(Uint4 data) = 0;
515     virtual void WriteInt8(Int8 data) = 0;
516     virtual void WriteUint8(Uint8 data) = 0;
517 
518     // float numbers
519     virtual void WriteFloat(float data);
520     virtual void WriteDouble(double data) = 0;
521 #if SIZEOF_LONG_DOUBLE != 0
522     virtual void WriteLDouble(long double data);
523 #endif
524 
525     // string
526     virtual void WriteString(const string& str,
527                              EStringType type = eStringTypeVisible) = 0;
528     virtual void CopyString(CObjectIStream& in,
529                             EStringType type = eStringTypeVisible) = 0;
530 
531     // StringStore
532     virtual void WriteStringStore(const string& data) = 0;
533     virtual void CopyStringStore(CObjectIStream& in) = 0;
534 
535     // C string
536     virtual void WriteCString(const char* str) = 0;
537 
538     // NULL
539     virtual void WriteNull(void) = 0;
540 
541     // enum
542     virtual void WriteEnum(const CEnumeratedTypeValues& values,
543                            TEnumValueType value) = 0;
544     virtual void CopyEnum(const CEnumeratedTypeValues& values,
545                           CObjectIStream& in) = 0;
546 
547     // any content object
548     virtual void WriteAnyContentObject(const CAnyContentObject& obj) = 0;
549     virtual void CopyAnyContentObject(CObjectIStream& in) = 0;
550 
551     virtual void WriteBitString(const CBitString& obj) = 0;
552     virtual void CopyBitString(CObjectIStream& in) = 0;
553 
554     // delayed buffer
555     virtual bool Write(CByteSource& source);
556     void Write(const char* data, size_t size);
557 
558 #ifdef NCBI_STRICT_GI
559     void WriteStd(const TGi& data);
560 
561     virtual void WriteGi(const TGi& obj);
562     virtual void CopyGi(CObjectIStream& in);
563 #endif
564 
565 //---------------------------------------------------------------------------
566 // Internals
567     void Close(void);
568     virtual void EndOfWrite(void);
569     void ResetLocalHooks(void);
570     void HandleEOF(CEofException&);
571 
572     void ThrowError1(const CDiagCompileInfo& diag_info,
573                      TFailFlags fail, const char* message,
574                      CException* exc = 0);
575     void ThrowError1(const CDiagCompileInfo& diag_info,
576                      TFailFlags fail, const string& message,
577                      CException* exc = 0);
578 #define RethrowError(flag,mess,exc) \
579     ThrowError1(DIAG_COMPILE_INFO,flag,mess,&exc)
580 
581     // report error about unended block
582     void Unended(const string& msg);
583     // report error about unended object stack frame
584     virtual void UnendedFrame(void) override;
585 
586     enum EFlags {
587         fFlagNone                = 0,
588         eFlagNone                = fFlagNone,
589         fFlagAllowNonAsciiChars  = 1 << 0,
590         eFlagAllowNonAsciiChars  = fFlagAllowNonAsciiChars,
591         fFlagNoAutoFlush         = 1 << 1
592     };
593     typedef int TFlags;
594     TFlags GetFlags(void) const;
595     TFlags SetFlags(TFlags flags);
596     TFlags ClearFlags(TFlags flags);
597 
598     class ByteBlock;
599     friend class ByteBlock;
600     class NCBI_XSERIAL_EXPORT ByteBlock
601     {
602     public:
603         ByteBlock(CObjectOStream& out, size_t length);
604         ~ByteBlock(void);
605 
606         CObjectOStream& GetStream(void) const;
607 
608         size_t GetLength(void) const;
609 
610         void Write(const void* bytes, size_t length);
611 
612         void End(void);
613 
614     private:
615         CObjectOStream& m_Stream;
616         size_t m_Length;
617         bool m_Ended;
618     };
619     class CharBlock;
620     friend class CharBlock;
621     class NCBI_XSERIAL_EXPORT CharBlock
622     {
623     public:
624         CharBlock(CObjectOStream& out, size_t length);
625         ~CharBlock(void);
626 
627         CObjectOStream& GetStream(void) const;
628 
629         size_t GetLength(void) const;
630 
631         void Write(const char* chars, size_t length);
632 
633         void End(void);
634 
635     private:
636         CObjectOStream& m_Stream;
637         size_t m_Length;
638         bool m_Ended;
639     };
640 
641 #if HAVE_NCBI_C
642     class NCBI_XSERIAL_EXPORT AsnIo
643     {
644     public:
645         AsnIo(CObjectOStream& out, const string& rootTypeName);
646         ~AsnIo(void);
647 
648         CObjectOStream& GetStream(void) const;
649 
650         void Write(const char* data, size_t length);
651 
652         void End(void);
653 
654         operator asnio*(void);
655         asnio* operator->(void);
656         const string& GetRootTypeName(void) const;
657 
658     private:
659         CObjectOStream& m_Stream;
660         string m_RootTypeName;
661         asnio* m_AsnIo;
662         bool m_Ended;
663 
664     public:
665         size_t m_Count;
666     };
667     friend class AsnIo;
668 public:
669 #endif
670 
671 //---------------------------------------------------------------------------
672 // mid level I/O
673     // named type (alias)
674     MLIOVIR void WriteNamedType(TTypeInfo namedTypeInfo,
675                                 TTypeInfo typeInfo, TConstObjectPtr object);
676     // container
677     MLIOVIR void WriteContainer(const CContainerTypeInfo* containerType,
678                                 TConstObjectPtr containerPtr);
679     void WriteContainerElement(const CConstObjectInfo& element);
680     // class
681     void WriteClassRandom(const CClassTypeInfo* classType,
682                           TConstObjectPtr classPtr);
683     void WriteClassSequential(const CClassTypeInfo* classType,
684                               TConstObjectPtr classPtr);
685     MLIOVIR void WriteClass(const CClassTypeInfo* objectType,
686                             TConstObjectPtr objectPtr);
687     MLIOVIR void WriteClassMember(const CMemberId& memberId,
688                                   TTypeInfo memberType,
689                                   TConstObjectPtr memberPtr);
690     MLIOVIR bool WriteClassMember(const CMemberId& memberId,
691                                   const CDelayBuffer& buffer);
692     // alias
693     MLIOVIR void WriteAlias(const CAliasTypeInfo* aliasType,
694                             TConstObjectPtr aliasPtr);
695 
696 //---------------------------------------------------------------------------
697 // Copying
698     // named type (alias)
699     MLIOVIR void CopyNamedType(TTypeInfo namedTypeInfo,
700                                TTypeInfo typeInfo,
701                                CObjectStreamCopier& copier);
702     // container
703     MLIOVIR void CopyContainer(const CContainerTypeInfo* containerType,
704                                CObjectStreamCopier& copier);
705     // class
706     MLIOVIR void CopyClassRandom(const CClassTypeInfo* objectType,
707                                  CObjectStreamCopier& copier);
708     MLIOVIR void CopyClassSequential(const CClassTypeInfo* objectType,
709                                      CObjectStreamCopier& copier);
710     // choice
711     MLIOVIR void CopyChoice(const CChoiceTypeInfo* choiceType,
712                             CObjectStreamCopier& copier);
713     // alias
714     MLIOVIR void CopyAlias(const CAliasTypeInfo* AliasType,
715                             CObjectStreamCopier& copier);
716 
717 //---------------------------------------------------------------------------
718 // low level I/O
719     // named type
720     virtual void BeginNamedType(TTypeInfo namedTypeInfo);
721     virtual void EndNamedType(void);
722 
723     // container
724     virtual void BeginContainer(const CContainerTypeInfo* containerType) = 0;
725     virtual void EndContainer(void);
726     virtual void BeginContainerElement(TTypeInfo elementType);
727     virtual void EndContainerElement(void);
728 
729     // class
730     virtual void BeginClass(const CClassTypeInfo* classInfo) = 0;
731     virtual void EndClass(void);
732 
733     virtual void BeginClassMember(const CMemberId& id) = 0;
734     virtual void EndClassMember(void);
735 
736     // choice
737     virtual void BeginChoice(const CChoiceTypeInfo* choiceType);
738     virtual void EndChoice(void);
739     virtual void BeginChoiceVariant(const CChoiceTypeInfo* choiceType,
740                                     const CMemberId& id) = 0;
741     virtual void EndChoiceVariant(void);
742 
743     // write byte blocks
744     virtual void BeginBytes(const ByteBlock& block);
745     virtual void WriteBytes(const ByteBlock& block,
746                             const char* bytes, size_t length) = 0;
747     virtual void EndBytes(const ByteBlock& block);
748 
749     // write char blocks
750     virtual void BeginChars(const CharBlock& block);
751     virtual void WriteChars(const CharBlock& block,
752                             const char* chars, size_t length) = 0;
753     virtual void EndChars(const CharBlock& block);
754 
755     void WritePointer(TConstObjectPtr object, TTypeInfo typeInfo);
756 
757     enum ESpecialCaseWrite {
758         eWriteAsNormal  = 0,
759         eWriteAsDefault = 1,
760         eWriteAsNil     = 2,
761         eWriteAsBigInt  = 3
762     };
SetSpecialCaseWrite(ESpecialCaseWrite how)763     void  SetSpecialCaseWrite( ESpecialCaseWrite how) {
764         m_SpecialCaseWrite = how;
765     }
766     MLIOVIR void WriteClassMemberSpecialCase(
767         const CMemberId& memberId, TTypeInfo memberType,
768         TConstObjectPtr memberPtr, ESpecialCaseWrite how);
769 
770 protected:
771     CObjectOStream(ESerialDataFormat format,
772                    CNcbiOstream& out, EOwnership deleteOut = eNoOwnership);
773 
774     // low level writers
775     typedef size_t TObjectIndex;
776     virtual void WriteNullPointer(void) = 0;
777     virtual void WriteObjectReference(TObjectIndex index) = 0;
778     virtual void WriteThis(TConstObjectPtr object,
779                            TTypeInfo typeInfo);
780     virtual void WriteOtherBegin(TTypeInfo typeInfo) = 0;
781     virtual void WriteOtherEnd(TTypeInfo typeInfo);
782     virtual void WriteOther(TConstObjectPtr object, TTypeInfo typeInfo);
783 
784     void RegisterObject(TTypeInfo typeInfo);
785     void RegisterObject(TConstObjectPtr object, TTypeInfo typeInfo);
786 
787     virtual void x_SetPathHooks(bool set) override;
788     EFixNonPrint x_GetFixCharsMethodDefault(void) const;
x_FixCharsMethod(void) const789     EFixNonPrint x_FixCharsMethod(void) const {
790         return m_FixMethod;
791     }
x_FixCharsSubst(void) const792     char x_FixCharsSubst(void) const {
793         return m_NonPrintSubst;
794     }
795     // Write current separator to the stream
796     virtual void WriteSeparator(void);
797 
798     COStreamBuffer m_Output;
799     TFailFlags m_Fail;
800     TFlags m_Flags;
801     AutoPtr<CWriteObjectList> m_Objects;
802     string m_Separator;
803     ESerialDataFormat   m_DataFormat;
804     EDelayBufferParsing  m_ParseDelayBuffers;
805     ESpecialCaseWrite m_SpecialCaseWrite;
806     bool  m_AutoSeparator;
807     bool  m_WriteNamedIntegersByValue;
808     bool  m_FastWriteDouble;
809     bool  m_EnforceWritingDefaults;
810     TTypeInfo m_TypeAlias;
811 
812 private:
813     static CObjectOStream* OpenObjectOStreamAsn(CNcbiOstream& out,
814                                                 EOwnership deleteOut);
815     static CObjectOStream* OpenObjectOStreamAsnBinary(CNcbiOstream& out,
816                                                       EOwnership deleteOut);
817     static CObjectOStream* OpenObjectOStreamXml(CNcbiOstream& out,
818                                                 EOwnership deleteOut);
819     static CObjectOStream* OpenObjectOStreamJson(CNcbiOstream& out,
820                                                 EOwnership deleteOut);
821     static ESerialVerifyData x_GetVerifyDataDefault(void);
822 
823     char m_NonPrintSubst;
824     EFixNonPrint m_FixMethod; // method of fixing wrong (eg, non-printable) chars
825     ESerialVerifyData   m_VerifyData;
826     CStreamObjectPathHook<CWriteObjectHook*>                m_PathWriteObjectHooks;
827     CStreamPathHook<CMemberInfo*, CWriteClassMemberHook*>   m_PathWriteMemberHooks;
828     CStreamPathHook<CVariantInfo*,CWriteChoiceVariantHook*> m_PathWriteVariantHooks;
829 
830 public:
831     // hook support
832     CLocalHookSet<CWriteObjectHook> m_ObjectHookKey;
833     CLocalHookSet<CWriteClassMemberHook> m_ClassMemberHookKey;
834     CLocalHookSet<CWriteChoiceVariantHook> m_ChoiceVariantHookKey;
835 
836     friend class CObjectStreamCopier;
837 };
838 
839 inline void
EnforceWritingDefaultValues(bool enforce)840 CObjectOStream::EnforceWritingDefaultValues(bool enforce) {
841     m_EnforceWritingDefaults = enforce;
842 }
843 inline bool
IsWritingDefaultValuesEnforced() const844 CObjectOStream::IsWritingDefaultValuesEnforced() const {
845     return m_EnforceWritingDefaults;
846 }
847 
848 
849 /* @} */
850 
851 
852 #include <serial/impl/objostr.inl>
853 
854 END_NCBI_SCOPE
855 
856 #endif  /* OBJOSTR__HPP */
857