1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #ifndef ICE_OUTPUT_STREAM_H
6 #define ICE_OUTPUT_STREAM_H
7 
8 #include <Ice/CommunicatorF.h>
9 #include <Ice/InstanceF.h>
10 #include <Ice/Object.h>
11 #include <Ice/ValueF.h>
12 #include <Ice/ProxyF.h>
13 #include <Ice/Buffer.h>
14 #include <Ice/Protocol.h>
15 #include <Ice/SlicedDataF.h>
16 #include <Ice/StreamHelpers.h>
17 
18 namespace Ice
19 {
20 
21 class UserException;
22 
23 /**
24  * Interface for output streams used to create a sequence of bytes from Slice types.
25  * \headerfile Ice/Ice.h
26  */
27 class ICE_API OutputStream : public IceInternal::Buffer
28 {
29 public:
30 
31     typedef size_t size_type;
32 
33     /**
34      * Constructs an OutputStream using the latest encoding version, the default format for
35      * class encoding, and the process string converters. You can supply a communicator later
36      * by calling initialize().
37      */
38     OutputStream();
39 
40     /**
41      * Constructs a stream using the communicator's default encoding version.
42      * @param communicator The communicator to use for marshaling tasks.
43      */
44     OutputStream(const CommunicatorPtr& communicator);
45 
46     /**
47      * Constructs a stream using the given communicator and encoding version.
48      * @param communicator The communicator to use for marshaling tasks.
49      * @param version The encoding version used to encode the data.
50      */
51     OutputStream(const CommunicatorPtr& communicator, const EncodingVersion& version);
52 
53     /**
54      * Constructs a stream using the given communicator and encoding version.
55      * @param communicator The communicator to use for marshaling tasks.
56      * @param version The encoding version used to encode the data.
57      * @param bytes Application-supplied memory that the stream uses as its initial marshaling buffer. The
58      * stream will reallocate if the size of the marshaled data exceeds the application's buffer.
59      */
60     OutputStream(const CommunicatorPtr& communicator, const EncodingVersion& version,
61                  const std::pair<const Byte*, const Byte*>& bytes);
62 
~OutputStream()63     ~OutputStream()
64     {
65         // Inlined for performance reasons.
66 
67         if(_currentEncaps != &_preAllocatedEncaps)
68         {
69             clear(); // Not inlined.
70         }
71     }
72 
73     /**
74      * Initializes the stream to use the communicator's default encoding version, class
75      * encoding format and string converters. Use this method if you originally constructed
76      * the stream without a communicator.
77      * @param communicator The communicator to use for marshaling tasks.
78      */
79     void initialize(const CommunicatorPtr& communicator);
80 
81     /**
82      * Initializes the stream to use the given encoding version and the communicator's
83      * default class encoding format and string converters. Use this method if you
84      * originally constructed the stream without a communicator.
85      * @param communicator The communicator to use for marshaling tasks.
86      * @param version The encoding version used to encode the data.
87      */
88     void initialize(const CommunicatorPtr& communicator, const EncodingVersion& version);
89 
90     /**
91      * Releases any data retained by encapsulations.
92      */
93     void clear();
94 
95     /// \cond INTERNAL
96     //
97     // Must return Instance*, because we don't hold an InstancePtr for
98     // optimization reasons (see comments below).
99     //
instance()100     IceInternal::Instance* instance() const { return _instance; } // Inlined for performance reasons.
101     /// \endcond
102 
103     /**
104      * Sets the class encoding format.
105      * @param format The encoding format.
106      */
107     void setFormat(FormatType format);
108 
109     /**
110      * Obtains the closure data associated with this stream.
111      * @return The data as a void pointer.
112      */
113     void* getClosure() const;
114 
115     /**
116      * Associates closure data with this stream.
117      * @param p The data as a void pointer.
118      * @return The previous closure data, or nil.
119      */
120     void* setClosure(void* p);
121 
122     /**
123      * Swaps the contents of one stream with another.
124      *
125      * @param other The other stream.
126      */
127     void swap(OutputStream& other);
128 
129     /// \cond INTERNAL
130     void resetEncapsulation();
131     /// \endcond
132 
133     /**
134      * Resizes the stream to a new size.
135      *
136      * @param sz The new size.
137      */
resize(Container::size_type sz)138     void resize(Container::size_type sz)
139     {
140         b.resize(sz);
141     }
142 
143     /**
144      * Marks the start of a class instance.
145      * @param data Contains the marshaled form of unknown slices from this instance. If not nil,
146      * these slices will be marshaled with the instance.
147      */
startValue(const SlicedDataPtr & data)148     void startValue(const SlicedDataPtr& data)
149     {
150         assert(_currentEncaps && _currentEncaps->encoder);
151         _currentEncaps->encoder->startInstance(ValueSlice, data);
152     }
153 
154     /**
155      * Marks the end of a class instance.
156      */
endValue()157     void endValue()
158     {
159         assert(_currentEncaps && _currentEncaps->encoder);
160         _currentEncaps->encoder->endInstance();
161     }
162 
163     /**
164      * Marks the start of an exception instance.
165      * @param data Contains the marshaled form of unknown slices from this instance. If not nil,
166      * these slices will be marshaled with the instance.
167      */
startException(const SlicedDataPtr & data)168     void startException(const SlicedDataPtr& data)
169     {
170         assert(_currentEncaps && _currentEncaps->encoder);
171         _currentEncaps->encoder->startInstance(ExceptionSlice, data);
172     }
173 
174     /**
175      * Marks the end of an exception instance.
176      */
endException()177     void endException()
178     {
179         assert(_currentEncaps && _currentEncaps->encoder);
180         _currentEncaps->encoder->endInstance();
181     }
182 
183     /**
184      * Writes the start of an encapsulation using the default encoding version and
185      * class encoding format.
186      */
187     void startEncapsulation();
188 
189     /**
190      * Writes the start of an encapsulation using the given encoding version and
191      * class encoding format.
192      * @param encoding The encoding version to use for the encapsulation.
193      * @param format The class format to use for the encapsulation.
194      */
startEncapsulation(const EncodingVersion & encoding,FormatType format)195     void startEncapsulation(const EncodingVersion& encoding, FormatType format)
196     {
197         IceInternal::checkSupportedEncoding(encoding);
198 
199         Encaps* oldEncaps = _currentEncaps;
200         if(!oldEncaps) // First allocated encaps?
201         {
202             _currentEncaps = &_preAllocatedEncaps;
203         }
204         else
205         {
206             _currentEncaps = new Encaps();
207             _currentEncaps->previous = oldEncaps;
208         }
209         _currentEncaps->format = format;
210         _currentEncaps->encoding = encoding;
211         _currentEncaps->start = b.size();
212 
213         write(Int(0)); // Placeholder for the encapsulation length.
214         write(_currentEncaps->encoding);
215     }
216 
217     /**
218      * Ends the current encapsulation.
219      */
endEncapsulation()220     void endEncapsulation()
221     {
222         assert(_currentEncaps);
223 
224         // Size includes size and version.
225         const Int sz = static_cast<Int>(b.size() - _currentEncaps->start);
226         write(sz, &(*(b.begin() + _currentEncaps->start)));
227 
228         Encaps* oldEncaps = _currentEncaps;
229         _currentEncaps = _currentEncaps->previous;
230         if(oldEncaps == &_preAllocatedEncaps)
231         {
232             oldEncaps->reset();
233         }
234         else
235         {
236             delete oldEncaps;
237         }
238     }
239 
240     /**
241      * Writes an empty encapsulation using the given encoding version.
242      * @param encoding The encoding version to use for the encapsulation.
243      */
writeEmptyEncapsulation(const EncodingVersion & encoding)244     void writeEmptyEncapsulation(const EncodingVersion& encoding)
245     {
246         IceInternal::checkSupportedEncoding(encoding);
247         write(Int(6)); // Size
248         write(encoding);
249     }
250 
251     /**
252      * Copies the marshaled form of an encapsulation to the buffer.
253      * @param v The start of the buffer.
254      * @param sz The number of bytes to copy.
255      */
writeEncapsulation(const Byte * v,Int sz)256     void writeEncapsulation(const Byte* v, Int sz)
257     {
258         if(sz < 6)
259         {
260             throwEncapsulationException(__FILE__, __LINE__);
261         }
262 
263         Container::size_type position = b.size();
264         resize(position + sz);
265         memcpy(&b[position], &v[0], sz);
266     }
267 
268     /**
269      * Determines the current encoding version.
270      *
271      * @return The encoding version.
272      */
getEncoding()273     const EncodingVersion& getEncoding() const
274     {
275         return _currentEncaps ? _currentEncaps->encoding : _encoding;
276     }
277 
278     /**
279      * Writes the start of a value or exception slice.
280      *
281      * @param typeId The Slice type ID for this slice.
282      * @param compactId The compact ID corresponding to the type, or -1 if no compact ID is used.
283      * @param last True if this is the last slice, false otherwise.
284      */
startSlice(const std::string & typeId,int compactId,bool last)285     void startSlice(const std::string& typeId, int compactId, bool last)
286     {
287         assert(_currentEncaps && _currentEncaps->encoder);
288         _currentEncaps->encoder->startSlice(typeId, compactId, last);
289     }
290 
291     /**
292      * Marks the end of a value or exception slice.
293      */
endSlice()294     void endSlice()
295     {
296         assert(_currentEncaps && _currentEncaps->encoder);
297         _currentEncaps->encoder->endSlice();
298     }
299 
300     /**
301      * Encodes the state of class instances whose insertion was delayed during a previous
302      * call to write. This member function must only be called once. For backward
303      * compatibility with encoding version 1.0, this function must only be called when
304      * non-optional data members or parameters use class types.
305      */
306     void writePendingValues();
307 
308     /**
309      * Writes a size value.
310      * @param v A non-negative integer.
311      */
writeSize(Int v)312     void writeSize(Int v) // Inlined for performance reasons.
313     {
314         assert(v >= 0);
315         if(v > 254)
316         {
317             write(Byte(255));
318             write(v);
319         }
320         else
321         {
322             write(static_cast<Byte>(v));
323         }
324     }
325 
326     /**
327      * Replaces a size value at the given destination in the stream. This function
328      * does not change the stream's current position.
329      * @param v A non-negative integer representing the size.
330      * @param dest The buffer destination for the size.
331      */
rewriteSize(Int v,Container::iterator dest)332     void rewriteSize(Int v, Container::iterator dest)
333     {
334         assert(v >= 0);
335         if(v > 254)
336         {
337             *dest++ = Byte(255);
338             write(v, dest);
339         }
340         else
341         {
342             *dest = static_cast<Byte>(v);
343         }
344     }
345 
346     /**
347      * Writes a placeholder value for the size and returns the starting position of the
348      * size value; after writing the data, call endSize to patch the placeholder with
349      * the actual size at the given position.
350      * @return The starting position of the size value.
351      */
startSize()352     size_type startSize()
353     {
354         size_type position = b.size();
355         write(Int(0));
356         return position;
357     }
358 
359     /**
360      * Updates the size value at the given position to contain a size based on the
361      * stream's current position.
362      * @param position The starting position of the size value as returned by startSize.
363      */
endSize(size_type position)364     void endSize(size_type position)
365     {
366         rewrite(static_cast<Int>(b.size() - position) - 4, position);
367     }
368 
369     /**
370      * Copies the specified blob of bytes to the stream without modification.
371      * @param v The bytes to be copied.
372      */
373     void writeBlob(const std::vector<Byte>& v);
374 
375     /**
376      * Copies the specified blob of bytes to the stream without modification.
377      * @param v The start of the buffer to be copied.
378      * @param sz The number of bytes to be copied.
379      */
writeBlob(const Byte * v,Container::size_type sz)380     void writeBlob(const Byte* v, Container::size_type sz)
381     {
382         if(sz > 0)
383         {
384             Container::size_type position = b.size();
385             resize(position + sz);
386             memcpy(&b[position], &v[0], sz);
387         }
388     }
389 
390     /**
391      * Writes a data value to the stream.
392      * @param v The data value to be written.
393      */
write(const T & v)394     template<typename T> void write(const T& v)
395     {
396         StreamHelper<T, StreamableTraits<T>::helper>::write(this, v);
397     }
398 
399     /**
400      * Writes an optional data value to the stream.
401      * @param tag The tag ID.
402      * @param v The data value to be written (if any).
403      */
write(Int tag,const IceUtil::Optional<T> & v)404     template<typename T> void write(Int tag, const IceUtil::Optional<T>& v)
405     {
406         if(!v)
407         {
408             return; // Optional not set
409         }
410 
411         if(writeOptional(tag, StreamOptionalHelper<T,
412                                               StreamableTraits<T>::helper,
413                                               StreamableTraits<T>::fixedLength>::optionalFormat))
414         {
415             StreamOptionalHelper<T,
416                                  StreamableTraits<T>::helper,
417                                  StreamableTraits<T>::fixedLength>::write(this, *v);
418         }
419     }
420 
421     /**
422      * Writes a sequence of data values to the stream.
423      * @param v The sequence to be written.
424      */
write(const std::vector<T> & v)425     template<typename T> void write(const std::vector<T>& v)
426     {
427         if(v.empty())
428         {
429             writeSize(0);
430         }
431         else
432         {
433             write(&v[0], &v[0] + v.size());
434         }
435     }
436 
437     /**
438      * Writes a sequence of data values to the stream.
439      * @param begin The beginning of the sequence.
440      * @param end The end of the sequence.
441      */
write(const T * begin,const T * end)442     template<typename T> void write(const T* begin, const T* end)
443     {
444         writeSize(static_cast<Int>(end - begin));
445         for(const T* p = begin; p != end; ++p)
446         {
447             write(*p);
448         }
449     }
450 
451 #ifdef ICE_CPP11_MAPPING
452 
453     /**
454      * Writes a list of mandatory data values.
455      */
writeAll(const T & v)456     template<typename T> void writeAll(const T& v)
457     {
458         write(v);
459     }
460 
461     /**
462      * Writes a list of mandatory data values.
463      */
writeAll(const T & v,const Te &...ve)464     template<typename T, typename... Te> void writeAll(const T& v, const Te&... ve)
465     {
466         write(v);
467         writeAll(ve...);
468     }
469 
470     /**
471      * Writes a list of mandatory data values.
472      */
473     template<size_t I = 0, typename... Te>
474     typename std::enable_if<I == sizeof...(Te), void>::type
writeAll(std::tuple<Te...>)475     writeAll(std::tuple<Te...>)
476     {
477         // Do nothing. Either tuple is empty or we are at the end.
478     }
479 
480     /**
481      * Writes a list of mandatory data values.
482      */
483     template<size_t I = 0, typename... Te>
484     typename std::enable_if<I < sizeof...(Te), void>::type
485     writeAll(std::tuple<Te...> tuple)
486     {
487         write(std::get<I>(tuple));
488         writeAll<I + 1, Te...>(tuple);
489     }
490 
491     /**
492      * Writes a list of optional data values.
493      */
494     template<typename T>
writeAll(std::initializer_list<int> tags,const IceUtil::Optional<T> & v)495     void writeAll(std::initializer_list<int> tags, const IceUtil::Optional<T>& v)
496     {
497         write(*(tags.begin() + tags.size() - 1), v);
498     }
499 
500     /**
501      * Writes a list of optional data values.
502      */
503     template<typename T, typename... Te>
writeAll(std::initializer_list<int> tags,const IceUtil::Optional<T> & v,const IceUtil::Optional<Te> &...ve)504     void writeAll(std::initializer_list<int> tags, const IceUtil::Optional<T>& v, const IceUtil::Optional<Te>&... ve)
505     {
506         size_t index = tags.size() - sizeof...(ve) - 1;
507         write(*(tags.begin() + index), v);
508         writeAll(tags, ve...);
509     }
510 
511 #endif
512 
513     /**
514      * Writes the tag and format of an optional value.
515      * @param tag The optional tag ID.
516      * @param format The optional format.
517      * @return True if the current encoding version supports optional values, false otherwise.
518      * If true, the data associated with the optional value must be written next.
519      */
writeOptional(Int tag,OptionalFormat format)520     bool writeOptional(Int tag, OptionalFormat format)
521     {
522         assert(_currentEncaps);
523         if(_currentEncaps->encoder)
524         {
525             return _currentEncaps->encoder->writeOptional(tag, format);
526         }
527         else
528         {
529             return writeOptImpl(tag, format);
530         }
531     }
532 
533     /**
534      * Writes a byte to the stream.
535      * @param v The byte to write.
536      */
write(Byte v)537     void write(Byte v)
538     {
539         b.push_back(v);
540     }
541 
542     /**
543      * Writes a byte sequence to the stream.
544      * @param start The beginning of the sequence.
545      * @param end The end of the sequence.
546      */
547     void write(const Byte* start, const Byte* end);
548 
549     /**
550      * Writes a boolean to the stream.
551      * @param v The boolean to write.
552      */
write(bool v)553     void write(bool v)
554     {
555         b.push_back(static_cast<Byte>(v));
556     }
557 
558     /**
559      * Writes a byte sequence to the stream.
560      * @param v The sequence to be written.
561      */
562     void write(const std::vector<bool>& v);
563 
564     /**
565      * Writes a byte sequence to the stream.
566      * @param begin The beginning of the sequence.
567      * @param end The end of the sequence.
568      */
569     void write(const bool* begin, const bool* end);
570 
571     /**
572      * Writes a short to the stream.
573      * @param v The short to write.
574      */
575     void write(Short v);
576 
577     /**
578      * Writes a short sequence to the stream.
579      * @param begin The beginning of the sequence.
580      * @param end The end of the sequence.
581      */
582     void write(const Short* begin, const Short* end);
583 
584     /**
585      * Writes an int to the stream.
586      * @param v The int to write.
587      */
write(Int v)588     void write(Int v) // Inlined for performance reasons.
589     {
590         Container::size_type position = b.size();
591         resize(position + sizeof(Int));
592         write(v, &b[position]);
593     }
594 
595     /**
596      * Overwrites a 32-bit integer value at the given destination in the stream.
597      * This function does not change the stream's current position.
598      * @param v The integer value to be written.
599      * @param dest The buffer destination for the integer value.
600      */
write(Int v,Container::iterator dest)601     void write(Int v, Container::iterator dest)
602     {
603 #ifdef ICE_BIG_ENDIAN
604         const Byte* src = reinterpret_cast<const Byte*>(&v) + sizeof(Int) - 1;
605         *dest++ = *src--;
606         *dest++ = *src--;
607         *dest++ = *src--;
608         *dest = *src;
609 #else
610         const Byte* src = reinterpret_cast<const Byte*>(&v);
611         *dest++ = *src++;
612         *dest++ = *src++;
613         *dest++ = *src++;
614         *dest = *src;
615 #endif
616     }
617 
618     /**
619      * Writes an int sequence to the stream.
620      * @param begin The beginning of the sequence.
621      * @param end The end of the sequence.
622      */
623     void write(const Int* begin, const Int* end);
624 
625     /**
626      * Writes a long to the stream.
627      * @param v The long to write.
628      */
629     void write(Long v);
630 
631     /**
632      * Writes a long sequence to the stream.
633      * @param begin The beginning of the sequence.
634      * @param end The end of the sequence.
635      */
636     void write(const Long* begin, const Long* end);
637 
638     /**
639      * Writes a float to the stream.
640      * @param v The float to write.
641      */
642     void write(Float v);
643 
644     /**
645      * Writes a float sequence to the stream.
646      * @param begin The beginning of the sequence.
647      * @param end The end of the sequence.
648      */
649     void write(const Float* begin, const Float* end);
650 
651     /**
652      * Writes a double to the stream.
653      * @param v The double to write.
654      */
655     void write(Double v);
656 
657     /**
658      * Writes a double sequence to the stream.
659      * @param begin The beginning of the sequence.
660      * @param end The end of the sequence.
661      */
662     void write(const Double* begin, const Double* end);
663 
664     /**
665      * Writes a string to the stream.
666      * @param v The string to write.
667      * @param convert Determines whether the string is processed by the narrow string converter,
668      * if one has been configured. The default behavior is to convert the strings.
669      */
670     void write(const std::string& v, bool convert = true)
671     {
672         Int sz = static_cast<Int>(v.size());
673         if(convert && sz > 0)
674         {
675             writeConverted(v.data(), static_cast<size_t>(sz));
676         }
677         else
678         {
679             writeSize(sz);
680             if(sz > 0)
681             {
682                 Container::size_type position = b.size();
683                 resize(position + sz);
684                 memcpy(&b[position], v.data(), sz);
685             }
686         }
687     }
688 
689     /**
690      * Writes a string to the stream.
691      * @param vdata The string to write.
692      * @param vsize The size of the string.
693      * @param convert Determines whether the string is processed by the narrow string converter,
694      * if one has been configured. The default behavior is to convert the strings.
695      */
696     void write(const char* vdata, size_t vsize, bool convert = true)
697     {
698         Int sz = static_cast<Int>(vsize);
699         if(convert && sz > 0)
700         {
701             writeConverted(vdata, vsize);
702         }
703         else
704         {
705             writeSize(sz);
706             if(sz > 0)
707             {
708                 Container::size_type position = b.size();
709                 resize(position + sz);
710                 memcpy(&b[position], vdata, vsize);
711             }
712         }
713     }
714 
715     /**
716      * Writes a string to the stream.
717      * @param vdata The null-terminated string to write.
718      * @param convert Determines whether the string is processed by the narrow string converter,
719      * if one has been configured. The default behavior is to convert the strings.
720      */
721     void write(const char* vdata, bool convert = true)
722     {
723         write(vdata, strlen(vdata), convert);
724     }
725 
726     /**
727      * Writes a string sequence to the stream.
728      * @param begin The beginning of the sequence.
729      * @param end The end of the sequence.
730      * @param convert Determines whether the string is processed by the narrow string converter,
731      * if one has been configured. The default behavior is to convert the strings.
732      */
733     void write(const std::string* begin, const std::string* end, bool convert = true);
734 
735     /**
736      * Writes a wide string to the stream.
737      * @param v The wide string to write.
738      */
739     void write(const std::wstring& v);
740 
741     /**
742      * Writes a wide string sequence to the stream.
743      * @param begin The beginning of the sequence.
744      * @param end The end of the sequence.
745      */
746     void write(const std::wstring* begin, const std::wstring* end);
747 
748 #ifdef ICE_CPP11_MAPPING
749     /**
750      * Writes a proxy to the stream.
751      * @param v The proxy to be written.
752      */
753     void writeProxy(const ::std::shared_ptr<ObjectPrx>& v);
754 
755     /**
756      * Writes a proxy to the stream.
757      * @param v The proxy to be written.
758      */
759     template<typename T, typename ::std::enable_if<::std::is_base_of<ObjectPrx, T>::value>::type* = nullptr>
write(const::std::shared_ptr<T> & v)760     void write(const ::std::shared_ptr<T>& v)
761     {
762         writeProxy(::std::static_pointer_cast<ObjectPrx>(v));
763     }
764 #else
765     /**
766      * Writes a proxy to the stream.
767      * @param v The proxy to be written.
768      */
769     void write(const ObjectPrx& v);
770 
771     /**
772      * Writes a proxy to the stream.
773      * @param v The proxy to be written.
774      */
write(const IceInternal::ProxyHandle<T> & v)775     template<typename T> void write(const IceInternal::ProxyHandle<T>& v)
776     {
777         write(ObjectPrx(upCast(v.get())));
778     }
779 #endif
780 
781 #ifdef ICE_CPP11_MAPPING // C++11 mapping
782     /**
783      * Writes a value instance to the stream.
784      * @param v The value to be written.
785      */
786     template<typename T, typename ::std::enable_if<::std::is_base_of<Value, T>::value>::type* = nullptr>
write(const::std::shared_ptr<T> & v)787     void write(const ::std::shared_ptr<T>& v)
788     {
789         initEncaps();
790         _currentEncaps->encoder->write(v);
791     }
792 #else // C++98 mapping
793     /**
794      * Writes a value instance to the stream.
795      * @param v The value to be written.
796      */
write(const ObjectPtr & v)797     void write(const ObjectPtr& v)
798     {
799         initEncaps();
800         _currentEncaps->encoder->write(v);
801     }
802 
803     /**
804      * Writes a value instance to the stream.
805      * @param v The value to be written.
806      */
write(const IceInternal::Handle<T> & v)807     template<typename T> void write(const IceInternal::Handle<T>& v)
808     {
809         write(ObjectPtr(upCast(v.get())));
810     }
811 #endif
812 
813     /**
814      * Writes an enumerator to the stream.
815      * @param v The enumerator to be written.
816      * @param maxValue The maximum value of all enumerators in this enumeration.
817      */
818     void writeEnum(Int v, Int maxValue);
819 
820     /**
821      * Writes an exception to the stream.
822      * @param v The exception to be written.
823      */
824     void writeException(const UserException& v);
825 
826     /**
827      * Obtains the current position of the stream.
828      * @return The current position.
829      */
pos()830     size_type pos()
831     {
832         return b.size();
833     }
834 
835     /**
836      * Overwrite a 32-bit integer value at the given position in the stream.
837      * This function does not change the stream's current position.
838      * @param v The value to be written.
839      * @param pos The buffer position for the value.
840      */
rewrite(Int v,size_type pos)841     void rewrite(Int v, size_type pos)
842     {
843         write(v, b.begin() + pos);
844     }
845 
846     /**
847      * Indicates that marshaling is complete. This function must only be called once.
848      * @param v Filled with a copy of the encoded data.
849      */
850     void finished(std::vector<Byte>& v);
851 
852     /**
853      * Indicates that marshaling is complete. This function must only be called once.
854      * @return A pair of pointers into the internal marshaling buffer. These pointers are
855      * valid for the lifetime of the stream.
856      */
857     std::pair<const Byte*, const Byte*> finished();
858 
859     /// \cond INTERNAL
860     OutputStream(IceInternal::Instance*, const EncodingVersion&);
861     void initialize(IceInternal::Instance*, const EncodingVersion&);
862 
863     // Optionals
864     bool writeOptImpl(Int, OptionalFormat);
865     /// \endcond
866 
867 private:
868 
869     //
870     // String
871     //
872     void writeConverted(const char*, size_t);
873 
874     //
875     // We can't throw this exception from inline functions from within
876     // this file, because we cannot include the header with the
877     // exceptions. Doing so would screw up the whole include file
878     // ordering.
879     //
880     void throwEncapsulationException(const char*, int);
881 
882     //
883     // Optimization. The instance may not be deleted while a
884     // stack-allocated stream still holds it.
885     //
886     IceInternal::Instance* _instance;
887 
888     //
889     // The public stream API needs to attach data to a stream.
890     //
891     void* _closure;
892 
893     class Encaps;
894     enum SliceType { NoSlice, ValueSlice, ExceptionSlice };
895 
896     typedef std::vector<ValuePtr> ValueList;
897 
898     class ICE_API EncapsEncoder : private ::IceUtil::noncopyable
899     {
900     public:
901 
902         virtual ~EncapsEncoder();
903 
904         virtual void write(const ValuePtr&) = 0;
905         virtual void write(const UserException&) = 0;
906 
907         virtual void startInstance(SliceType, const SlicedDataPtr&) = 0;
908         virtual void endInstance() = 0;
909         virtual void startSlice(const std::string&, int, bool) = 0;
910         virtual void endSlice() = 0;
911 
writeOptional(Int,OptionalFormat)912         virtual bool writeOptional(Int, OptionalFormat)
913         {
914             return false;
915         }
916 
writePendingValues()917         virtual void writePendingValues()
918         {
919         }
920 
921     protected:
922 
EncapsEncoder(OutputStream * stream,Encaps * encaps)923         EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps), _typeIdIndex(0)
924         {
925         }
926 
927         Int registerTypeId(const std::string&);
928 
929         OutputStream* _stream;
930         Encaps* _encaps;
931 
932         typedef std::map<ValuePtr, Int> PtrToIndexMap;
933         typedef std::map<std::string, Int> TypeIdMap;
934 
935         // Encapsulation attributes for value marshaling.
936         PtrToIndexMap _marshaledMap;
937 
938     private:
939 
940         // Encapsulation attributes for value marshaling.
941         TypeIdMap _typeIdMap;
942         Int _typeIdIndex;
943     };
944 
945     class ICE_API EncapsEncoder10 : public EncapsEncoder
946     {
947     public:
948 
EncapsEncoder10(OutputStream * stream,Encaps * encaps)949         EncapsEncoder10(OutputStream* stream, Encaps* encaps) :
950             EncapsEncoder(stream, encaps), _sliceType(NoSlice), _valueIdIndex(0)
951         {
952         }
953 
954         virtual void write(const ValuePtr&);
955         virtual void write(const UserException&);
956 
957         virtual void startInstance(SliceType, const SlicedDataPtr&);
958         virtual void endInstance();
959         virtual void startSlice(const std::string&, int, bool);
960         virtual void endSlice();
961 
962         virtual void writePendingValues();
963 
964     private:
965 
966         Int registerValue(const ValuePtr&);
967 
968         // Instance attributes
969         SliceType _sliceType;
970 
971         // Slice attributes
972         Container::size_type _writeSlice; // Position of the slice data members
973 
974         // Encapsulation attributes for value marshaling.
975         Int _valueIdIndex;
976         PtrToIndexMap _toBeMarshaledMap;
977     };
978 
979     class ICE_API EncapsEncoder11 : public EncapsEncoder
980     {
981     public:
982 
EncapsEncoder11(OutputStream * stream,Encaps * encaps)983         EncapsEncoder11(OutputStream* stream, Encaps* encaps) :
984             EncapsEncoder(stream, encaps), _preAllocatedInstanceData(0), _current(0), _valueIdIndex(1)
985         {
986         }
987 
988         virtual void write(const ValuePtr&);
989         virtual void write(const UserException&);
990 
991         virtual void startInstance(SliceType, const SlicedDataPtr&);
992         virtual void endInstance();
993         virtual void startSlice(const std::string&, int, bool);
994         virtual void endSlice();
995 
996         virtual bool writeOptional(Int, OptionalFormat);
997 
998     private:
999 
1000         void writeSlicedData(const SlicedDataPtr&);
1001         void writeInstance(const ValuePtr&);
1002 
1003         struct InstanceData
1004         {
InstanceDataInstanceData1005             InstanceData(InstanceData* p) : previous(p), next(0)
1006             {
1007                 if(previous)
1008                 {
1009                     previous->next = this;
1010                 }
1011             }
1012 
~InstanceDataInstanceData1013             ~InstanceData()
1014             {
1015                 if(next)
1016                 {
1017                     delete next;
1018                 }
1019             }
1020 
1021             // Instance attributes
1022             SliceType sliceType;
1023             bool firstSlice;
1024 
1025             // Slice attributes
1026             Byte sliceFlags;
1027             Container::size_type writeSlice;    // Position of the slice data members
1028             Container::size_type sliceFlagsPos; // Position of the slice flags
1029             PtrToIndexMap indirectionMap;
1030             ValueList indirectionTable;
1031 
1032             InstanceData* previous;
1033             InstanceData* next;
1034         };
1035         InstanceData _preAllocatedInstanceData;
1036         InstanceData* _current;
1037 
1038         Int _valueIdIndex; // The ID of the next value to marhsal
1039     };
1040 
1041     class Encaps : private ::IceUtil::noncopyable
1042     {
1043 
1044     public:
1045 
Encaps()1046         Encaps() : format(ICE_ENUM(FormatType, DefaultFormat)), encoder(0), previous(0)
1047         {
1048             // Inlined for performance reasons.
1049         }
~Encaps()1050         ~Encaps()
1051         {
1052             // Inlined for performance reasons.
1053             delete encoder;
1054         }
reset()1055         void reset()
1056         {
1057             // Inlined for performance reasons.
1058             delete encoder;
1059             encoder = 0;
1060 
1061             previous = 0;
1062         }
1063 
1064         Container::size_type start;
1065         EncodingVersion encoding;
1066         FormatType format;
1067 
1068         EncapsEncoder* encoder;
1069 
1070         Encaps* previous;
1071     };
1072 
1073     //
1074     // The encoding version to use when there's no encapsulation to
1075     // read from or write to. This is for example used to read message
1076     // headers or when the user is using the streaming API with no
1077     // encapsulation.
1078     //
1079     EncodingVersion _encoding;
1080 
1081     FormatType _format;
1082 
1083     Encaps* _currentEncaps;
1084 
1085     void initEncaps();
1086 
1087     Encaps _preAllocatedEncaps;
1088 };
1089 
1090 } // End namespace Ice
1091 
1092 #endif
1093