1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #ifndef ICE_INPUT_STREAM_H
6 #define ICE_INPUT_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/LoggerF.h>
14 #include <Ice/ValueFactory.h>
15 #include <Ice/Buffer.h>
16 #include <Ice/Protocol.h>
17 #include <Ice/SlicedDataF.h>
18 #include <Ice/UserExceptionFactory.h>
19 #include <Ice/StreamHelpers.h>
20 #include <Ice/FactoryTable.h>
21 
22 namespace Ice
23 {
24 
25 class UserException;
26 
27 /// \cond INTERNAL
28 template<typename T> inline void
patchHandle(void * addr,const ValuePtr & v)29 patchHandle(void* addr, const ValuePtr& v)
30 {
31 #ifdef ICE_CPP11_MAPPING
32     ::std::shared_ptr<T>* handle = static_cast<::std::shared_ptr<T>*>(addr);
33     *handle = ::std::dynamic_pointer_cast<T>(v);
34     if(v && !(*handle))
35     {
36         IceInternal::Ex::throwUOE(T::ice_staticId(), v);
37     }
38 #else
39     IceInternal::Handle<T>* p = static_cast<IceInternal::Handle<T>*>(addr);
40     _icePatchObjectPtr(*p, v); // Generated _icePatchObjectPtr function, necessary for forward declarations.
41 #endif
42 }
43 /// \endcond
44 
45 /**
46  * Interface for input streams used to extract Slice types from a sequence of bytes.
47  * \headerfile Ice/Ice.h
48  */
49 class ICE_API InputStream : public IceInternal::Buffer
50 {
51 public:
52 
53     typedef size_t size_type;
54 
55     /**
56      * Signature for a patch function, used to receive an unmarshaled value.
57      * @param addr The target address.
58      * @param v The unmarshaled value.
59      */
60     typedef void (*PatchFunc)(void* addr, const ValuePtr& v);
61 
62     /**
63      * Constructs a stream using the latest encoding version but without a communicator.
64      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
65      * you can provide Helpers for objects that are normally provided by a communicator.
66      * You can supply a communicator later by calling initialize().
67      */
68     InputStream();
69 
70     /**
71      * Constructs a stream using the latest encoding version but without a communicator.
72      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
73      * you can provide Helpers for objects that are normally provided by a communicator.
74      * You can supply a communicator later by calling initialize().
75      * @param bytes The encoded data.
76      */
77     InputStream(const std::vector<Byte>& bytes);
78 
79     /**
80      * Constructs a stream using the latest encoding version but without a communicator.
81      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
82      * you can provide Helpers for objects that are normally provided by a communicator.
83      * You can supply a communicator later by calling initialize().
84      * @param bytes The encoded data.
85      */
86     InputStream(const std::pair<const Byte*, const Byte*>& bytes);
87 
88     /// \cond INTERNAL
89     InputStream(IceInternal::Buffer&, bool = false);
90     /// \endcond
91 
92     /**
93      * Constructs a stream using the communicator's default encoding version.
94      * @param communicator The communicator to use for unmarshaling tasks.
95      */
96     InputStream(const CommunicatorPtr& communicator);
97 
98     /**
99      * Constructs a stream using the communicator's default encoding version.
100      * @param communicator The communicator to use for unmarshaling tasks.
101      * @param bytes The encoded data.
102      */
103     InputStream(const CommunicatorPtr& communicator, const std::vector<Byte>& bytes);
104 
105     /**
106      * Constructs a stream using the communicator's default encoding version.
107      * @param communicator The communicator to use for unmarshaling tasks.
108      * @param bytes The encoded data.
109      */
110     InputStream(const CommunicatorPtr& communicator, const std::pair<const Byte*, const Byte*>& bytes);
111 
112     /// \cond INTERNAL
113     InputStream(const CommunicatorPtr& communicator, IceInternal::Buffer&, bool = false);
114     /// \endcond
115 
116     /**
117      * Constructs a stream using the given encoding version but without a communicator.
118      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
119      * you can provide Helpers for objects that are normally provided by a communicator.
120      * You can supply a communicator later by calling initialize().
121      * @param version The encoding version used to encode the data to be unmarshaled.
122      */
123     InputStream(const EncodingVersion& version);
124 
125     /**
126      * Constructs a stream using the given encoding version but without a communicator.
127      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
128      * you can provide Helpers for objects that are normally provided by a communicator.
129      * You can supply a communicator later by calling initialize().
130      * @param version The encoding version used to encode the data to be unmarshaled.
131      * @param bytes The encoded data.
132      */
133     InputStream(const EncodingVersion& version, const std::vector<Byte>& bytes);
134 
135     /**
136      * Constructs a stream using the given encoding version but without a communicator.
137      * This stream will not be able to unmarshal a proxy. For other unmarshaling tasks,
138      * you can provide Helpers for objects that are normally provided by a communicator.
139      * You can supply a communicator later by calling initialize().
140      * @param version The encoding version used to encode the data to be unmarshaled.
141      * @param bytes The encoded data.
142      */
143     InputStream(const EncodingVersion& version, const std::pair<const Byte*, const Byte*>& bytes);
144 
145     /// \cond INTERNAL
146     InputStream(const EncodingVersion&, IceInternal::Buffer&, bool = false);
147     /// \endcond
148 
149     /**
150      * Constructs a stream using the given communicator and encoding version.
151      * @param communicator The communicator to use for unmarshaling tasks.
152      * @param version The encoding version used to encode the data to be unmarshaled.
153      */
154     InputStream(const CommunicatorPtr& communicator, const EncodingVersion& version);
155 
156     /**
157      * Constructs a stream using the given communicator and encoding version.
158      * @param communicator The communicator to use for unmarshaling tasks.
159      * @param version The encoding version used to encode the data to be unmarshaled.
160      * @param bytes The encoded data.
161      */
162     InputStream(const CommunicatorPtr& communicator, const EncodingVersion& version, const std::vector<Byte>& bytes);
163 
164     /**
165      * Constructs a stream using the given communicator and encoding version.
166      * @param communicator The communicator to use for unmarshaling tasks.
167      * @param version The encoding version used to encode the data to be unmarshaled.
168      * @param bytes The encoded data.
169      */
170     InputStream(const CommunicatorPtr& communicator, const EncodingVersion& version,
171                 const std::pair<const Byte*, const Byte*>& bytes);
172 
173     /// \cond INTERNAL
174     InputStream(const CommunicatorPtr&, const EncodingVersion&, IceInternal::Buffer&, bool = false);
175     /// \endcond
176 
~InputStream()177     ~InputStream()
178     {
179         // Inlined for performance reasons.
180 
181         if(_currentEncaps != &_preAllocatedEncaps)
182         {
183             clear(); // Not inlined.
184         }
185 
186 #ifdef ICE_CPP11_MAPPING
187 
188         for(auto d: _deleters)
189         {
190             d();
191         }
192 #endif
193     }
194 
195     /**
196      * Initializes the stream to use the communicator's default encoding version.
197      * Use initialize() if you originally constructed the stream without a communicator.
198      * @param communicator The communicator to use for unmarshaling tasks.
199      */
200     void initialize(const CommunicatorPtr& communicator);
201 
202     /**
203      * Initializes the stream to use the given communicator and encoding version.
204      * Use initialize() if you originally constructed the stream without a communicator.
205      * @param communicator The communicator to use for unmarshaling tasks.
206      * @param version The encoding version used to encode the data to be unmarshaled.
207      */
208     void initialize(const CommunicatorPtr& communicator, const EncodingVersion& version);
209 
210     /**
211      * Releases any data retained by encapsulations.
212      */
213     void clear();
214 
215     /// \cond INTERNAL
216     //
217     // Must return Instance*, because we don't hold an InstancePtr for
218     // optimization reasons (see comments below).
219     //
instance()220     IceInternal::Instance* instance() const { return _instance; } // Inlined for performance reasons.
221     /// \endcond
222 
223     /**
224      * Sets the value factory manager to use when unmarshaling value instances. If the stream
225      * was initialized with a communicator, the communicator's value factory manager will
226      * be used by default.
227      *
228      * @param vfm The value factory manager.
229      */
230     void setValueFactoryManager(const ValueFactoryManagerPtr& vfm);
231 
232     /**
233      * Sets the logger to use when logging trace messages. If the stream
234      * was initialized with a communicator, the communicator's logger will
235      * be used by default.
236      *
237      * @param logger The logger to use for logging trace messages.
238      */
239     void setLogger(const LoggerPtr& logger);
240 
241     /**
242      * Sets the compact ID resolver to use when unmarshaling value and exception
243      * instances. If the stream was initialized with a communicator, the communicator's
244      * resolver will be used by default.
245      *
246      * @param r The compact ID resolver.
247      */
248 #ifdef ICE_CPP11_MAPPING
249     void setCompactIdResolver(std::function<std::string(int)> r);
250 #else
251     void setCompactIdResolver(const CompactIdResolverPtr& r);
252 #endif
253 
254 #ifndef ICE_CPP11_MAPPING
255     /**
256      * Indicates whether to mark instances of Slice classes as collectable. If the stream is
257      * initialized with a communicator, this setting defaults to the value of the
258      * Ice.CollectObjects property, otherwise the setting defaults to false.
259      * @param b True to mark instances as collectable, false otherwise.
260      */
261     void setCollectObjects(bool b);
262 #endif
263 
264     /**
265      * Indicates whether to slice instances of Slice classes to a known Slice type when a more
266      * derived type is unknown. An instance is "sliced" when no static information is available
267      * for a Slice type ID and no factory can be found for that type, resulting in the creation
268      * of an instance of a less-derived type. If slicing is disabled in this situation, the
269      * stream raises the exception NoValueFactoryException. The default behavior is to allow slicing.
270      * @param b True to enable slicing, false otherwise.
271      */
272     void setSliceValues(bool b);
273 
274     /**
275      * Indicates whether to log messages when instances of Slice classes are sliced. If the stream
276      * is initialized with a communicator, this setting defaults to the value of the Ice.Trace.Slicing
277      * property, otherwise the setting defaults to false.
278      * @param b True to enable logging, false otherwise.
279      */
280     void setTraceSlicing(bool b);
281 
282     /**
283      * Sets an upper limit on the depth of a class graph. If this limit is exceeded during
284      * unmarshaling, the stream raises MarshalException.
285      * @param n The maximum depth.
286      */
287     void setClassGraphDepthMax(size_t n);
288 
289     /**
290      * Obtains the closure data associated with this stream.
291      * @return The data as a void pointer.
292      */
293     void* getClosure() const;
294 
295     /**
296      * Associates closure data with this stream.
297      * @param p The data as a void pointer.
298      * @return The previous closure data, or nil.
299      */
300     void* setClosure(void* p);
301 
302     /**
303      * Swaps the contents of one stream with another.
304      *
305      * @param other The other stream.
306      */
307     void swap(InputStream& other);
308 
309     /// \cond INTERNAL
310     void resetEncapsulation();
311     /// \endcond
312 
313     /**
314      * Resizes the stream to a new size.
315      *
316      * @param sz The new size.
317      */
resize(Container::size_type sz)318     void resize(Container::size_type sz)
319     {
320         b.resize(sz);
321         i = b.end();
322     }
323 
324     /**
325      * Marks the start of a class instance.
326      */
startValue()327     void startValue()
328     {
329         assert(_currentEncaps && _currentEncaps->decoder);
330         _currentEncaps->decoder->startInstance(ValueSlice);
331     }
332 
333     /**
334      * Marks the end of a class instance.
335      *
336      * @param preserve Pass true and the stream will preserve the unknown slices of the instance, or false
337      * to discard the unknown slices.
338      * @return An object that encapsulates the unknown slice data.
339      */
endValue(bool preserve)340     SlicedDataPtr endValue(bool preserve)
341     {
342         assert(_currentEncaps && _currentEncaps->decoder);
343         return _currentEncaps->decoder->endInstance(preserve);
344     }
345 
346     /**
347      * Marks the start of a user exception.
348      */
startException()349     void startException()
350     {
351         assert(_currentEncaps && _currentEncaps->decoder);
352         _currentEncaps->decoder->startInstance(ExceptionSlice);
353     }
354 
355     /**
356      * Marks the end of a user exception.
357      *
358      * @param preserve Pass true and the stream will preserve the unknown slices of the exception, or false
359      * to discard the unknown slices.
360      * @return An object that encapsulates the unknown slice data.
361      */
endException(bool preserve)362     SlicedDataPtr endException(bool preserve)
363     {
364         assert(_currentEncaps && _currentEncaps->decoder);
365         return _currentEncaps->decoder->endInstance(preserve);
366     }
367 
368     /**
369      * Reads the start of an encapsulation.
370      *
371      * @return The encoding version used by the encapsulation.
372      */
startEncapsulation()373     const EncodingVersion& startEncapsulation()
374     {
375         Encaps* oldEncaps = _currentEncaps;
376         if(!oldEncaps) // First allocated encaps?
377         {
378             _currentEncaps = &_preAllocatedEncaps;
379         }
380         else
381         {
382             _currentEncaps = new Encaps();
383             _currentEncaps->previous = oldEncaps;
384         }
385         _currentEncaps->start = i - b.begin();
386 
387         //
388         // I don't use readSize() and writeSize() for encapsulations,
389         // because when creating an encapsulation, I must know in advance
390         // how many bytes the size information will require in the data
391         // stream. If I use an Int, it is always 4 bytes. For
392         // readSize()/writeSize(), it could be 1 or 5 bytes.
393         //
394         Int sz;
395         read(sz);
396         if(sz < 6)
397         {
398             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
399         }
400         if(i - sizeof(Int) + sz > b.end())
401         {
402             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
403         }
404         _currentEncaps->sz = sz;
405 
406         read(_currentEncaps->encoding);
407         IceInternal::checkSupportedEncoding(_currentEncaps->encoding); // Make sure the encoding is supported
408 
409         return _currentEncaps->encoding;
410     }
411 
412     /**
413      * Ends the current encapsulation.
414      */
endEncapsulation()415     void endEncapsulation()
416     {
417         assert(_currentEncaps);
418 
419         if(_currentEncaps->encoding != Encoding_1_0)
420         {
421             skipOptionals();
422             if(i != b.begin() + _currentEncaps->start + _currentEncaps->sz)
423             {
424                 throwEncapsulationException(__FILE__, __LINE__);
425             }
426         }
427         else if(i != b.begin() + _currentEncaps->start + _currentEncaps->sz)
428         {
429             if(i + 1 != b.begin() + _currentEncaps->start + _currentEncaps->sz)
430             {
431                 throwEncapsulationException(__FILE__, __LINE__);
432             }
433 
434             //
435             // Ice version < 3.3 had a bug where user exceptions with
436             // class members could be encoded with a trailing byte
437             // when dispatched with AMD. So we tolerate an extra byte
438             // in the encapsulation.
439             //
440             ++i;
441         }
442 
443         Encaps* oldEncaps = _currentEncaps;
444         _currentEncaps = _currentEncaps->previous;
445         if(oldEncaps == &_preAllocatedEncaps)
446         {
447             oldEncaps->reset();
448         }
449         else
450         {
451             delete oldEncaps;
452         }
453     }
454 
455     /**
456      * Skips an empty encapsulation.
457      *
458      * @return The encapsulation's encoding version.
459      */
skipEmptyEncapsulation()460     EncodingVersion skipEmptyEncapsulation()
461     {
462         Ice::Int sz;
463         read(sz);
464         if(sz < 6)
465         {
466             throwEncapsulationException(__FILE__, __LINE__);
467         }
468         if(i - sizeof(Ice::Int) + sz > b.end())
469         {
470             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
471         }
472         Ice::EncodingVersion encoding;
473         read(encoding);
474         IceInternal::checkSupportedEncoding(encoding); // Make sure the encoding is supported
475 
476         if(encoding == Ice::Encoding_1_0)
477         {
478             if(sz != static_cast<Ice::Int>(sizeof(Ice::Int)) + 2)
479             {
480                 throwEncapsulationException(__FILE__, __LINE__);
481             }
482         }
483         else
484         {
485             // Skip the optional content of the encapsulation if we are expecting an
486             // empty encapsulation.
487             i += sz - sizeof(Ice::Int) - 2;
488         }
489         return encoding;
490     }
491 
492     /**
493      * Returns a blob of bytes representing an encapsulation.
494      *
495      * @param v A pointer into the internal marshaling buffer representing the start of the encoded encapsulation.
496      * @param sz The number of bytes in the encapsulation.
497      * @return encoding The encapsulation's encoding version.
498      */
readEncapsulation(const Byte * & v,Int & sz)499     EncodingVersion readEncapsulation(const Byte*& v, Int& sz)
500     {
501         EncodingVersion encoding;
502         v = i;
503         read(sz);
504         if(sz < 6)
505         {
506             throwEncapsulationException(__FILE__, __LINE__);
507         }
508         if(i - sizeof(Int) + sz > b.end())
509         {
510             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
511         }
512 
513         read(encoding);
514         i += sz - sizeof(Int) - 2;
515         return encoding;
516     }
517 
518     /**
519      * Determines the current encoding version.
520      *
521      * @return The encoding version.
522      */
getEncoding()523     const EncodingVersion& getEncoding() const
524     {
525         return _currentEncaps ? _currentEncaps->encoding : _encoding;
526     }
527 
528     /**
529      * Determines the size of the current encapsulation, excluding the encapsulation header.
530      *
531      * @return The size of the encapsulated data.
532      */
533     Int getEncapsulationSize();
534 
535     /**
536      * Skips over an encapsulation.
537      *
538      * @return The encoding version of the skipped encapsulation.
539      */
540     EncodingVersion skipEncapsulation();
541 
542     /**
543      * Reads the start of a value or exception slice.
544      *
545      * @return The Slice type ID for this slice.
546      */
startSlice()547     std::string startSlice()
548     {
549         assert(_currentEncaps && _currentEncaps->decoder);
550         return _currentEncaps->decoder->startSlice();
551     }
552 
553     /**
554      * Indicates that the end of a value or exception slice has been reached.
555      */
endSlice()556     void endSlice()
557     {
558         assert(_currentEncaps && _currentEncaps->decoder);
559         _currentEncaps->decoder->endSlice();
560     }
561 
562     /**
563      * Skips over a value or exception slice.
564      */
skipSlice()565     void skipSlice()
566     {
567         assert(_currentEncaps && _currentEncaps->decoder);
568         _currentEncaps->decoder->skipSlice();
569     }
570 
571     /**
572      * Indicates that unmarshaling is complete, except for any class instances. The application must call this method
573      * only if the stream actually contains class instances. Calling readPendingValues triggers the
574      * patch callbacks to inform the application that unmarshaling of an instance is complete.
575      */
576     void readPendingValues();
577 
578     /**
579      * Extracts a size from the stream.
580      *
581      * @return The extracted size.
582      */
readSize()583     Int readSize() // Inlined for performance reasons.
584     {
585         Byte byte;
586         read(byte);
587         unsigned char val = static_cast<unsigned char>(byte);
588         if(val == 255)
589         {
590             Int v;
591             read(v);
592             if(v < 0)
593             {
594                 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
595             }
596             return v;
597         }
598         else
599         {
600             return static_cast<Int>(static_cast<unsigned char>(byte));
601         }
602     }
603 
604     /**
605      * Reads and validates a sequence size.
606      *
607      * @param minSize The minimum size required by the sequence type.
608      * @return The extracted size.
609      */
610     Int readAndCheckSeqSize(int minSize);
611 
612     /**
613      * Reads a blob of bytes from the stream.
614      *
615      * @param bytes The vector to hold a copy of the bytes from the marshaling buffer.
616      * @param sz The number of bytes to read.
617      */
618     void readBlob(std::vector<Byte>& bytes, Int sz);
619 
620     /**
621      * Reads a blob of bytes from the stream.
622      *
623      * @param v A pointer into the internal marshaling buffer representing the start of the blob.
624      * @param sz The number of bytes to read.
625      */
readBlob(const Byte * & v,Container::size_type sz)626     void readBlob(const Byte*& v, Container::size_type sz)
627     {
628         if(sz > 0)
629         {
630             v = i;
631             if(static_cast<Container::size_type>(b.end() - i) < sz)
632             {
633                 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
634             }
635             i += sz;
636         }
637         else
638         {
639             v = i;
640         }
641     }
642 
643     /**
644      * Reads a data value from the stream.
645      * @param v Holds the extracted data.
646      */
read(T & v)647     template<typename T> void read(T& v)
648     {
649         StreamHelper<T, StreamableTraits<T>::helper>::read(this, v);
650     }
651 
652     /**
653      * Reads an optional data value from the stream.
654      * @param tag The tag ID.
655      * @param v Holds the extracted data (if any).
656      */
read(Int tag,IceUtil::Optional<T> & v)657     template<typename T> void read(Int tag, IceUtil::Optional<T>& v)
658     {
659         if(readOptional(tag, StreamOptionalHelper<T,
660                                              StreamableTraits<T>::helper,
661                                              StreamableTraits<T>::fixedLength>::optionalFormat))
662         {
663 #ifdef ICE_CPP11_MAPPING
664             v.emplace();
665 #else
666             v.__setIsSet();
667 #endif
668             StreamOptionalHelper<T,
669                                  StreamableTraits<T>::helper,
670                                  StreamableTraits<T>::fixedLength>::read(this, *v);
671         }
672         else
673         {
674             v = IceUtil::None;
675         }
676     }
677 
678 #ifdef ICE_CPP11_MAPPING
679 
680     /**
681      * Extracts a sequence of data values from the stream.
682      * @param v A pair of pointers representing the beginning and end of the sequence elements.
683      */
read(std::pair<const T *,const T * > & v)684     template<typename T> void read(std::pair<const T*, const T*>& v)
685     {
686         auto holder = new std::vector<T>;
687         _deleters.push_back([holder] { delete holder; });
688         read(*holder);
689         if(holder->size() > 0)
690         {
691             v.first = holder->data();
692             v.second = holder->data() + holder->size();
693         }
694         else
695         {
696             v.first = 0;
697             v.second = 0;
698         }
699     }
700 
701     /**
702      * Reads a list of mandatory data values.
703      */
readAll(T & v)704     template<typename T> void readAll(T& v)
705     {
706         read(v);
707     }
708 
709     /**
710      * Reads a list of mandatory data values.
711      */
readAll(T & v,Te &...ve)712     template<typename T, typename... Te> void readAll(T& v, Te&... ve)
713     {
714         read(v);
715         readAll(ve...);
716     }
717 
718     /**
719      * Reads a list of optional data values.
720      */
721     template<typename T>
readAll(std::initializer_list<int> tags,IceUtil::Optional<T> & v)722     void readAll(std::initializer_list<int> tags, IceUtil::Optional<T>& v)
723     {
724         read(*(tags.begin() + tags.size() - 1), v);
725     }
726 
727     /**
728      * Reads a list of optional data values.
729      */
730     template<typename T, typename... Te>
readAll(std::initializer_list<int> tags,IceUtil::Optional<T> & v,IceUtil::Optional<Te> &...ve)731     void readAll(std::initializer_list<int> tags, IceUtil::Optional<T>& v, IceUtil::Optional<Te>&... ve)
732     {
733         size_t index = tags.size() - sizeof...(ve) - 1;
734         read(*(tags.begin() + index), v);
735         readAll(tags, ve...);
736     }
737 
738 #endif
739 
740     /**
741      * Determine if an optional value is available for reading.
742      *
743      * @param tag The tag associated with the value.
744      * @param expectedFormat The optional format for the value.
745      * @return True if the value is present, false otherwise.
746      */
readOptional(Int tag,OptionalFormat expectedFormat)747     bool readOptional(Int tag, OptionalFormat expectedFormat)
748     {
749         assert(_currentEncaps);
750         if(_currentEncaps->decoder)
751         {
752             return _currentEncaps->decoder->readOptional(tag, expectedFormat);
753         }
754         else
755         {
756             return readOptImpl(tag, expectedFormat);
757         }
758     }
759 
760     /**
761      * Reads a byte from the stream.
762      * @param v The extracted byte.
763      */
read(Byte & v)764     void read(Byte& v)
765     {
766         if(i >= b.end())
767         {
768             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
769         }
770         v = *i++;
771     }
772 
773     /**
774      * Reads a sequence of bytes from the stream.
775      * @param v A vector to hold a copy of the bytes.
776      */
777     void read(std::vector<Byte>& v);
778 
779     /**
780      * Reads a sequence of bytes from the stream.
781      * @param v A pair of pointers into the internal marshaling buffer representing the start and end of the
782      * sequence elements.
783      */
784     void read(std::pair<const Byte*, const Byte*>& v);
785 
786 #ifndef ICE_CPP11_MAPPING
787     /**
788      * Reads a sequence of bytes from the stream.
789      * @param v A pair of pointers into the internal marshaling buffer representing the start and end of the
790      * sequence elements.
791      * @param arr A scoped array.
792      */
read(std::pair<const Byte *,const Byte * > & v,::IceUtil::ScopedArray<Byte> & arr)793     void read(std::pair<const Byte*, const Byte*>& v, ::IceUtil::ScopedArray<Byte>& arr)
794     {
795         arr.reset();
796         read(v);
797     }
798 #endif
799 
800     /**
801      * Reads a bool from the stream.
802      * @param v The extracted bool.
803      */
read(bool & v)804     void read(bool& v)
805     {
806         if(i >= b.end())
807         {
808             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
809         }
810         v = (0 != *i++);
811     }
812 
813     /**
814      * Reads a sequence of boolean values from the stream.
815      * @param v A vector to hold a copy of the boolean values.
816      */
817     void read(std::vector<bool>& v);
818 
819 #ifdef ICE_CPP11_MAPPING
820     /**
821      * Reads a sequence of boolean values from the stream.
822      * @param v A pair of pointers into the internal marshaling buffer representing the start and end of the
823      * sequence elements.
824      */
825     void read(std::pair<const bool*, const bool*>& v);
826 #else
827     /**
828      * Reads a sequence of boolean values from the stream.
829      * @param v A pair of pointers into the internal marshaling buffer representing the start and end of the
830      * sequence elements.
831      * @param arr A scoped array.
832      */
833     void read(std::pair<const bool*, const bool*>& v, ::IceUtil::ScopedArray<bool>& arr);
834 #endif
835 
836     /**
837      * Reads a short from the stream.
838      * @param v The extracted short.
839      */
840     void read(Short& v);
841 
842     /**
843      * Reads a sequence of shorts from the stream.
844      * @param v A vector to hold a copy of the short values.
845      */
846     void read(std::vector<Short>& v);
847 
848 #ifdef ICE_CPP11_MAPPING
849     /**
850      * Reads a sequence of boolean values from the stream.
851      * @param v A pair of pointers representing the start and end of the sequence elements.
852      */
853     void read(std::pair<const short*, const short*>& v);
854 #else
855     /**
856      * Reads a sequence of shorts from the stream.
857      * @param v A pair of pointers representing the start and end of the sequence elements.
858      * @param arr A scoped array.
859      */
860     void read(std::pair<const Short*, const Short*>& v, ::IceUtil::ScopedArray<Short>& arr);
861 #endif
862 
863     /**
864      * Reads an int from the stream.
865      * @param v The extracted int.
866      */
read(Int & v)867     void read(Int& v) // Inlined for performance reasons.
868     {
869         if(b.end() - i < static_cast<int>(sizeof(Int)))
870         {
871             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
872         }
873         const Byte* src = &(*i);
874         i += sizeof(Int);
875 #ifdef ICE_BIG_ENDIAN
876         Byte* dest = reinterpret_cast<Byte*>(&v) + sizeof(Int) - 1;
877         *dest-- = *src++;
878         *dest-- = *src++;
879         *dest-- = *src++;
880         *dest = *src;
881 #else
882         Byte* dest = reinterpret_cast<Byte*>(&v);
883         *dest++ = *src++;
884         *dest++ = *src++;
885         *dest++ = *src++;
886         *dest = *src;
887 #endif
888     }
889 
890     /**
891      * Reads a sequence of ints from the stream.
892      * @param v A vector to hold a copy of the int values.
893      */
894     void read(std::vector<Int>& v);
895 
896 #ifdef ICE_CPP11_MAPPING
897     /**
898      * Reads a sequence of ints from the stream.
899      * @param v A pair of pointers representing the start and end of the sequence elements.
900      */
901     void read(std::pair<const int*, const int*>& v);
902 #else
903     /**
904      * Reads a sequence of ints from the stream.
905      * @param v A pair of pointers representing the start and end of the sequence elements.
906      * @param arr A scoped array.
907      */
908     void read(std::pair<const Int*, const Int*>& v, ::IceUtil::ScopedArray<Int>& arr);
909 #endif
910 
911     /**
912      * Reads a long from the stream.
913      * @param v The extracted long.
914      */
915     void read(Long& v);
916 
917     /**
918      * Reads a sequence of longs from the stream.
919      * @param v A vector to hold a copy of the long values.
920      */
921     void read(std::vector<Long>& v);
922 
923 #ifdef ICE_CPP11_MAPPING
924     /**
925      * Reads a sequence of longs from the stream.
926      * @param v A pair of pointers representing the start and end of the sequence elements.
927      */
928     void read(std::pair<const long long*, const long long*>& v);
929 #else
930     /**
931      * Reads a sequence of longs from the stream.
932      * @param v A pair of pointers representing the start and end of the sequence elements.
933      * @param arr A scoped array.
934      */
935     void read(std::pair<const Long*, const Long*>& v, ::IceUtil::ScopedArray<Long>& arr);
936 #endif
937 
938     /**
939      * Reads a float from the stream.
940      * @param v The extracted float.
941      */
942     void read(Float& v);
943 
944     /**
945      * Reads a sequence of floats from the stream.
946      * @param v A vector to hold a copy of the float values.
947      */
948     void read(std::vector<Float>& v);
949 
950 #ifdef ICE_CPP11_MAPPING
951     /**
952      * Reads a sequence of floats from the stream.
953      * @param v A pair of pointers representing the start and end of the sequence elements.
954      */
955     void read(std::pair<const float*, const float*>& v);
956 #else
957     /**
958      * Reads a sequence of floats from the stream.
959      * @param v A pair of pointers representing the start and end of the sequence elements.
960      * @param arr A scoped array.
961      */
962     void read(std::pair<const Float*, const Float*>& v, ::IceUtil::ScopedArray<Float>& arr);
963 #endif
964 
965     /**
966      * Reads a double from the stream.
967      * @param v The extracted double.
968      */
969     void read(Double& v);
970 
971     /**
972      * Reads a sequence of doubles from the stream.
973      * @param v A vector to hold a copy of the double values.
974      */
975     void read(std::vector<Double>& v);
976 
977 #ifdef ICE_CPP11_MAPPING
978     /**
979      * Reads a sequence of doubles from the stream.
980      * @param v A pair of pointers representing the start and end of the sequence elements.
981      */
982     void read(std::pair<const double*, const double*>& v);
983 #else
984     /**
985      * Reads a sequence of doubles from the stream.
986      * @param v A pair of pointers representing the start and end of the sequence elements.
987      * @param arr A scoped array.
988      */
989     void read(std::pair<const Double*, const Double*>& v, ::IceUtil::ScopedArray<Double>& arr);
990 #endif
991 
992     /**
993      * Reads a string from the stream.
994      * @param v The extracted string.
995      * @param convert Determines whether the string is processed by the string converter, if one
996      * is installed. The default behavior is to convert strings.
997      */
998     void read(std::string& v, bool convert = true);
999 
1000 #ifdef ICE_CPP11_MAPPING
1001     /**
1002      * Reads a string from the stream.
1003      * @param vdata A pointer to the beginning of the string.
1004      * @param vsize The number of bytes in the string.
1005      * @param convert Determines whether the string is processed by the string converter, if one
1006      * is installed. The default behavior is to convert strings.
1007      */
1008     void read(const char*& vdata, size_t& vsize, bool convert = true);
1009 #else
1010     // For custom strings, convert = false
1011     /**
1012      * Reads a string from the stream. String conversion is disabled.
1013      * @param vdata A pointer to the beginning of the string.
1014      * @param vsize The number of bytes in the string.
1015      */
1016     void read(const char*& vdata, size_t& vsize);
1017 
1018     // For custom strings, convert = true
1019     /**
1020      * Reads a string from the stream. String conversion is enabled.
1021      * @param vdata A pointer to the beginning of the string.
1022      * @param vsize The number of bytes in the string.
1023      * @param holder Holds the string contents.
1024      */
1025     void read(const char*& vdata, size_t& vsize, std::string& holder);
1026 #endif
1027 
1028     /**
1029      * Reads a sequence of strings from the stream.
1030      * @param v The extracted string sequence.
1031      * @param convert Determines whether strings are processed by the string converter, if one
1032      * is installed. The default behavior is to convert the strings.
1033      */
1034     void read(std::vector<std::string>& v, bool convert = true);
1035 
1036     /**
1037      * Reads a wide string from the stream.
1038      * @param v The extracted string.
1039      */
1040     void read(std::wstring& v);
1041 
1042     /**
1043      * Reads a sequence of wide strings from the stream.
1044      * @param v The extracted sequence.
1045      */
1046     void read(std::vector<std::wstring>& v);
1047 
1048 #ifdef ICE_CPP11_MAPPING
1049     /**
1050      * Reads a proxy from the stream.
1051      * @return The proxy as the base ObjectPrx type.
1052      */
1053     std::shared_ptr<ObjectPrx> readProxy();
1054 
1055     /**
1056      * Reads a typed proxy from the stream.
1057      * @param v The proxy as a user-defined type.
1058      */
1059     template<typename T, typename ::std::enable_if<::std::is_base_of<ObjectPrx, T>::value>::type* = nullptr>
read(::std::shared_ptr<T> & v)1060     void read(::std::shared_ptr<T>& v)
1061     {
1062         ::std::shared_ptr<ObjectPrx> proxy(readProxy());
1063         if(!proxy)
1064         {
1065             v = 0;
1066         }
1067         else
1068         {
1069             v = ::IceInternal::createProxy<T>();
1070             v->_copyFrom(proxy);
1071         }
1072     }
1073 #else
1074     /**
1075      * Reads a proxy from the stream.
1076      * @param v The proxy as the base ObjectPrx type.
1077      */
1078     void read(ObjectPrx& v);
1079 
1080     /**
1081      * Reads a typed proxy from the stream.
1082      * @param v The proxy as a user-defined type.
1083      */
read(IceInternal::ProxyHandle<T> & v)1084     template<typename T> void read(IceInternal::ProxyHandle<T>& v)
1085     {
1086         _readProxy(this, v); // Generated _readProxy method, necessary for forward declarations.
1087     }
1088 #endif
1089 
1090     /**
1091      * Reads a value (instance of a Slice class) from the stream.
1092      * @param v The instance.
1093      */
1094 #ifdef ICE_CPP11_MAPPING // C++11 mapping
1095     template<typename T, typename ::std::enable_if<::std::is_base_of<Value, T>::value>::type* = nullptr>
read(::std::shared_ptr<T> & v)1096     void read(::std::shared_ptr<T>& v)
1097     {
1098         read(&patchHandle<T>, &v);
1099     }
1100 #else // C++98 mapping
read(IceInternal::Handle<T> & v)1101     template<typename T> void read(IceInternal::Handle<T>& v)
1102     {
1103         read(&patchHandle<T>, &v);
1104     }
1105 #endif
1106 
1107     /**
1108      * Reads a value (instance of a Slice class) from the stream.
1109      * @param patchFunc The patch callback function.
1110      * @param patchAddr Closure data passed to the callback.
1111      */
read(PatchFunc patchFunc,void * patchAddr)1112     void read(PatchFunc patchFunc, void* patchAddr)
1113     {
1114         initEncaps();
1115         _currentEncaps->decoder->read(patchFunc, patchAddr);
1116     }
1117 
1118     /**
1119      * Reads an enumerator from the stream.
1120      * @param maxValue The maximum enumerator value in the definition.
1121      * @return The enumerator value.
1122      */
1123     Int readEnum(Int maxValue);
1124 
1125     /**
1126      * Extracts a user exception from the stream and throws it.
1127      * @param factory If provided, this factory is given the first opportunity to instantiate
1128      * the exception. If not provided, or if the factory does not throw an exception when invoked,
1129      * the stream will attempt to instantiate the exception using static type information.
1130      * @throws UserException The user exception that was unmarshaled.
1131      */
1132     void throwException(ICE_IN(ICE_DELEGATE(UserExceptionFactory)) factory = ICE_NULLPTR);
1133 
1134     /**
1135      * Skips one optional value with the given format.
1136      * @param format The expected format of the optional, if present.
1137      */
1138     void skipOptional(OptionalFormat format);
1139 
1140     /**
1141      * Skips all remaining optional values.
1142      */
1143     void skipOptionals();
1144 
1145     /**
1146      * Advances the current stream position by the given number of bytes.
1147      * @param size The number of bytes to skip.
1148      */
skip(size_type size)1149     void skip(size_type size)
1150     {
1151         if(i + size > b.end())
1152         {
1153             throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
1154         }
1155         i += size;
1156     }
1157 
1158     /**
1159      * Reads a size at the current position and skips that number of bytes.
1160      */
skipSize()1161     void skipSize()
1162     {
1163         Byte bt;
1164         read(bt);
1165         if(static_cast<unsigned char>(bt) == 255)
1166         {
1167             skip(4);
1168         }
1169     }
1170 
1171     /**
1172      * Obtains the current position of the stream.
1173      * @return The current position.
1174      */
pos()1175     size_type pos()
1176     {
1177         return i - b.begin();
1178     }
1179 
1180     /**
1181      * Sets a new position for the stream.
1182      * @param p The new position.
1183      */
pos(size_type p)1184     void pos(size_type p)
1185     {
1186         i = b.begin() + p;
1187     }
1188 
1189     /// \cond INTERNAL
1190     InputStream(IceInternal::Instance*, const EncodingVersion&);
1191     InputStream(IceInternal::Instance*, const EncodingVersion&, IceInternal::Buffer&, bool = false);
1192 
1193     void initialize(IceInternal::Instance*, const EncodingVersion&);
1194 
1195     bool readOptImpl(Int, OptionalFormat);
1196     /// \endcond
1197 
1198 private:
1199 
1200     void initialize(const EncodingVersion&);
1201 
1202     //
1203     // String
1204     //
1205     bool readConverted(std::string&, Int);
1206 
1207     //
1208     // We can't throw these exception from inline functions from within
1209     // this file, because we cannot include the header with the
1210     // exceptions. Doing so would screw up the whole include file
1211     // ordering.
1212     //
1213     void throwUnmarshalOutOfBoundsException(const char*, int);
1214     void throwEncapsulationException(const char*, int);
1215 
1216     std::string resolveCompactId(int) const;
1217 
1218     void postUnmarshal(const ValuePtr&) const;
1219 
1220     class Encaps;
1221     enum SliceType { NoSlice, ValueSlice, ExceptionSlice };
1222 
1223     void traceSkipSlice(const std::string&, SliceType) const;
1224 
1225     ValueFactoryManagerPtr valueFactoryManager() const;
1226 
1227     LoggerPtr logger() const;
1228 
1229 #ifdef ICE_CPP11_MAPPING
1230     std::function<std::string(int)> compactIdResolver() const;
1231 #else
1232     CompactIdResolverPtr compactIdResolver() const;
1233 #endif
1234 
1235     typedef std::vector<ValuePtr> ValueList;
1236 
1237     class ICE_API EncapsDecoder : private ::IceUtil::noncopyable
1238     {
1239     public:
1240 
1241         virtual ~EncapsDecoder();
1242 
1243         virtual void read(PatchFunc, void*) = 0;
1244         virtual void throwException(ICE_IN(ICE_DELEGATE(UserExceptionFactory))) = 0;
1245 
1246         virtual void startInstance(SliceType) = 0;
1247         virtual SlicedDataPtr endInstance(bool) = 0;
1248         virtual const std::string& startSlice() = 0;
1249         virtual void endSlice() = 0;
1250         virtual void skipSlice() = 0;
1251 
readOptional(Int,OptionalFormat)1252         virtual bool readOptional(Int, OptionalFormat)
1253         {
1254             return false;
1255         }
1256 
readPendingValues()1257         virtual void readPendingValues()
1258         {
1259         }
1260 
1261     protected:
1262 
EncapsDecoder(InputStream * stream,Encaps * encaps,bool sliceValues,size_t classGraphDepthMax,const Ice::ValueFactoryManagerPtr & f)1263         EncapsDecoder(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
1264                       const Ice::ValueFactoryManagerPtr& f) :
1265             _stream(stream), _encaps(encaps), _sliceValues(sliceValues), _classGraphDepthMax(classGraphDepthMax),
1266             _classGraphDepth(0), _valueFactoryManager(f), _typeIdIndex(0)
1267         {
1268         }
1269 
1270         std::string readTypeId(bool);
1271         ValuePtr newInstance(const std::string&);
1272 
1273         void addPatchEntry(Int, PatchFunc, void*);
1274         void unmarshal(Int, const ValuePtr&);
1275 
1276         typedef std::map<Int, ValuePtr> IndexToPtrMap;
1277         typedef std::map<Int, std::string> TypeIdMap;
1278 
1279         struct PatchEntry
1280         {
1281             PatchFunc patchFunc;
1282             void* patchAddr;
1283             size_t classGraphDepth;
1284         };
1285         typedef std::vector<PatchEntry> PatchList;
1286         typedef std::map<Int, PatchList> PatchMap;
1287 
1288         InputStream* _stream;
1289         Encaps* _encaps;
1290         const bool _sliceValues;
1291         const size_t _classGraphDepthMax;
1292         size_t _classGraphDepth;
1293         Ice::ValueFactoryManagerPtr _valueFactoryManager;
1294 
1295         // Encapsulation attributes for object un-marshalling
1296         PatchMap _patchMap;
1297 
1298     private:
1299 
1300         // Encapsulation attributes for object un-marshalling
1301         IndexToPtrMap _unmarshaledMap;
1302         TypeIdMap _typeIdMap;
1303         Int _typeIdIndex;
1304         ValueList _valueList;
1305     };
1306 
1307     class ICE_API EncapsDecoder10 : public EncapsDecoder
1308     {
1309     public:
1310 
EncapsDecoder10(InputStream * stream,Encaps * encaps,bool sliceValues,size_t classGraphDepthMax,const Ice::ValueFactoryManagerPtr & f)1311         EncapsDecoder10(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
1312                         const Ice::ValueFactoryManagerPtr& f) :
1313             EncapsDecoder(stream, encaps, sliceValues, classGraphDepthMax, f),
1314             _sliceType(NoSlice)
1315         {
1316         }
1317 
1318         virtual void read(PatchFunc, void*);
1319         virtual void throwException(ICE_IN(ICE_DELEGATE(UserExceptionFactory)));
1320 
1321         virtual void startInstance(SliceType);
1322         virtual SlicedDataPtr endInstance(bool);
1323         virtual const std::string& startSlice();
1324         virtual void endSlice();
1325         virtual void skipSlice();
1326 
1327         virtual void readPendingValues();
1328 
1329     private:
1330 
1331         void readInstance();
1332 
1333         // Instance attributes
1334         SliceType _sliceType;
1335         bool _skipFirstSlice;
1336 
1337         // Slice attributes
1338         Int _sliceSize;
1339         std::string _typeId;
1340     };
1341 
1342     class ICE_API EncapsDecoder11 : public EncapsDecoder
1343     {
1344     public:
1345 
EncapsDecoder11(InputStream * stream,Encaps * encaps,bool sliceValues,size_t classGraphDepthMax,const Ice::ValueFactoryManagerPtr & f)1346         EncapsDecoder11(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
1347                         const Ice::ValueFactoryManagerPtr& f) :
1348             EncapsDecoder(stream, encaps, sliceValues, classGraphDepthMax, f),
1349             _preAllocatedInstanceData(0), _current(0), _valueIdIndex(1)
1350         {
1351         }
1352 
1353         virtual void read(PatchFunc, void*);
1354         virtual void throwException(ICE_IN(ICE_DELEGATE(UserExceptionFactory)));
1355 
1356         virtual void startInstance(SliceType);
1357         virtual SlicedDataPtr endInstance(bool);
1358         virtual const std::string& startSlice();
1359         virtual void endSlice();
1360         virtual void skipSlice();
1361 
1362         virtual bool readOptional(Int, OptionalFormat);
1363 
1364     private:
1365 
1366         Int readInstance(Int, PatchFunc, void*);
1367         SlicedDataPtr readSlicedData();
1368 
1369         struct IndirectPatchEntry
1370         {
1371             Int index;
1372             PatchFunc patchFunc;
1373             void* patchAddr;
1374         };
1375         typedef std::vector<IndirectPatchEntry> IndirectPatchList;
1376 
1377         typedef std::vector<Int> IndexList;
1378         typedef std::vector<IndexList> IndexListList;
1379 
1380         struct InstanceData
1381         {
InstanceDataInstanceData1382             InstanceData(InstanceData* p) : previous(p), next(0)
1383             {
1384                 if(previous)
1385                 {
1386                     previous->next = this;
1387                 }
1388             }
1389 
~InstanceDataInstanceData1390             ~InstanceData()
1391             {
1392                 if(next)
1393                 {
1394                     delete next;
1395                 }
1396             }
1397 
1398             // Instance attributes
1399             SliceType sliceType;
1400             bool skipFirstSlice;
1401             SliceInfoSeq slices; // Preserved slices.
1402             IndexListList indirectionTables;
1403 
1404             // Slice attributes
1405             Byte sliceFlags;
1406             Int sliceSize;
1407             std::string typeId;
1408             int compactId;
1409             IndirectPatchList indirectPatchList;
1410 
1411             InstanceData* previous;
1412             InstanceData* next;
1413         };
1414         InstanceData _preAllocatedInstanceData;
1415         InstanceData* _current;
1416 
push(SliceType sliceType)1417         void push(SliceType sliceType)
1418         {
1419             if(!_current)
1420             {
1421                 _current = &_preAllocatedInstanceData;
1422             }
1423             else
1424             {
1425                 _current = _current->next ? _current->next : new InstanceData(_current);
1426             }
1427             _current->sliceType = sliceType;
1428             _current->skipFirstSlice = false;
1429         }
1430 
1431         Int _valueIdIndex; // The ID of the next value to unmarshal.
1432     };
1433 
1434     class Encaps : private ::IceUtil::noncopyable
1435     {
1436     public:
1437 
Encaps()1438         Encaps() : start(0), decoder(0), previous(0)
1439         {
1440             // Inlined for performance reasons.
1441         }
~Encaps()1442         ~Encaps()
1443         {
1444             // Inlined for performance reasons.
1445             delete decoder;
1446         }
reset()1447         void reset()
1448         {
1449             // Inlined for performance reasons.
1450             delete decoder;
1451             decoder = 0;
1452 
1453             previous = 0;
1454         }
1455 
1456         Container::size_type start;
1457         Int sz;
1458         EncodingVersion encoding;
1459 
1460         EncapsDecoder* decoder;
1461 
1462         Encaps* previous;
1463     };
1464 
1465     //
1466     // Optimization. The instance may not be deleted while a
1467     // stack-allocated stream still holds it.
1468     //
1469     IceInternal::Instance* _instance;
1470 
1471     //
1472     // The encoding version to use when there's no encapsulation to
1473     // read from. This is for example used to read message headers.
1474     //
1475     EncodingVersion _encoding;
1476 
1477     Encaps* _currentEncaps;
1478 
1479     void initEncaps();
1480 
1481     Encaps _preAllocatedEncaps;
1482 
1483 #ifndef ICE_CPP11_MAPPING
1484     bool _collectObjects;
1485 #endif
1486 
1487     bool _traceSlicing;
1488 
1489     size_t _classGraphDepthMax;
1490 
1491     void* _closure;
1492 
1493     bool _sliceValues;
1494 
1495     int _startSeq;
1496     int _minSeqSize;
1497 
1498     ValueFactoryManagerPtr _valueFactoryManager;
1499     LoggerPtr _logger;
1500 #ifdef ICE_CPP11_MAPPING
1501     std::function<std::string(int)> _compactIdResolver;
1502 #else
1503     CompactIdResolverPtr _compactIdResolver;
1504 #endif
1505 
1506 #ifdef ICE_CPP11_MAPPING
1507     std::vector<std::function<void()>> _deleters;
1508 #endif
1509 
1510 };
1511 
1512 } // End namespace Ice
1513 
1514 #endif
1515