Ice 3.8
C++ API Reference
Loading...
Searching...
No Matches
InputStream.h
1// Copyright (c) ZeroC, Inc.
2
3#ifndef ICE_INPUT_STREAM_H
4#define ICE_INPUT_STREAM_H
5
6#include "Buffer.h"
7#include "CommunicatorF.h"
8#include "Ice/Version.h"
9#include "InstanceF.h"
10#include "LocalException.h"
11#include "Logger.h"
12#include "ReferenceF.h"
13#include "SliceLoader.h"
14#include "SlicedDataF.h"
15#include "StreamableTraits.h"
16#include "UserExceptionFactory.h"
17#include "ValueF.h"
18
19#include <cassert>
20#include <cstdint>
21#include <map>
22#include <string>
23#include <string_view>
24
25namespace IceInternal::Ex
26{
27 ICE_API void throwUOE(const char* file, int line, const std::string&, const Ice::ValuePtr&);
28 ICE_API void throwMemoryLimitException(const char* file, int line, size_t, std::int32_t);
29 ICE_API void throwMarshalException(const char* file, int line, std::string);
30}
31
32namespace Ice
33{
34 class ObjectPrx;
35
36 /// @private
37 template<typename T> inline void patchValue(void* addr, const ValuePtr& v)
38 {
39 auto* ptr = static_cast<std::shared_ptr<T>*>(addr);
40 *ptr = std::dynamic_pointer_cast<T>(v);
41 if (v && !(*ptr))
42 {
43 IceInternal::Ex::throwUOE(__FILE__, __LINE__, std::string{T::ice_staticId()}, v);
44 }
45 }
46
47 /// Represents a byte buffer used for unmarshaling data encoded using the Slice encoding.
48 /// @headerfile Ice/Ice.h
49 class ICE_API InputStream final : public IceInternal::Buffer
50 {
51 public:
52 /// The size type for this byte buffer.
53 using size_type = std::size_t;
54
55 /// @private
56 using PatchFunc = std::function<void(void* addr, const ValuePtr& v)>;
57
58 /// Constructs an InputStream using a communicator and this communicator's default encoding version.
59 /// @param communicator The communicator to use for unmarshaling tasks.
60 /// @param bytes The encoded data.
61 /// @param sliceLoader The Slice loader. When nullptr, use the communicator's Slice loader.
63 const CommunicatorPtr& communicator,
64 const std::vector<std::byte>& bytes,
65 SliceLoaderPtr sliceLoader = nullptr);
66
67 /// @copydoc InputStream(const CommunicatorPtr&, const std::vector<std::byte>&, SliceLoaderPtr)
69 const CommunicatorPtr& communicator,
70 std::pair<const std::byte*, const std::byte*> bytes,
71 SliceLoaderPtr sliceLoader = nullptr);
72
73 /// Constructs an InputStream using a communicator and encoding version.
74 /// @param communicator The communicator to use for unmarshaling tasks.
75 /// @param encoding The encoding version used to encode the data to be unmarshaled.
76 /// @param bytes The encoded data.
77 /// @param sliceLoader The Slice loader. When nullptr, use the communicator's Slice loader.
79 const CommunicatorPtr& communicator,
80 EncodingVersion encoding,
81 const std::vector<std::byte>& bytes,
82 SliceLoaderPtr sliceLoader = nullptr);
83
84 /// @copydoc InputStream(const CommunicatorPtr&, EncodingVersion, const std::vector<std::byte>&, SliceLoaderPtr)
86 const CommunicatorPtr& communicator,
87 EncodingVersion encoding,
88 std::pair<const std::byte*, const std::byte*> bytes,
89 SliceLoaderPtr sliceLoader = nullptr);
90
91 /// @private
92 /// Constructs a stream with an empty buffer.
93 InputStream(IceInternal::Instance* instance, EncodingVersion encoding, SliceLoaderPtr sliceLoader = nullptr);
94
95 /// @private
96 /// Constructs a stream with the specified encoding and buffer.
98 IceInternal::Instance* instance,
99 EncodingVersion encoding,
100 IceInternal::Buffer& buf,
101 bool adopt,
102 SliceLoaderPtr sliceLoader = nullptr);
103
104 /// Move constructor.
105 /// @param other The input stream to move into this input stream.
106 InputStream(InputStream&& other) noexcept;
107
108 /// Move assignment operator.
109 /// @param other The input stream to move into this input stream.
110 /// @return A reference to this input stream.
112
114 {
115 // Inlined for performance reasons.
116
117 if (_currentEncaps != &_preAllocatedEncaps)
118 {
119 clear(); // Not inlined.
120 }
121
122 for (const auto& d : _deleters)
123 {
124 d();
125 }
126 }
127
128 /// Releases any data retained by encapsulations.
129 void clear();
130
131 /// @private
132 // Must return Instance*, because we don't hold an InstancePtr for optimization reasons (see comments below).
133 [[nodiscard]] IceInternal::Instance* instance() const { return _instance; } // Inlined for performance reasons.
134
135 /// Swaps the contents of one stream with another.
136 /// @param other The other stream.
137 void swap(InputStream& other) noexcept;
138
139 /// @cond INTERNAL
140
141 /// Gets the closure associated with this stream.
142 /// @return The closure.
143 [[nodiscard]] void* getClosure() const;
144
145 /// Associates a closure with this stream.
146 /// @param p The closure.
147 /// @return The previous closure, or nullptr.
148 void* setClosure(void* p);
149
150 void resetEncapsulation();
151
152 /// Resizes the stream to a new size.
153 /// @param sz The new size.
154 void resize(Container::size_type sz)
155 {
156 b.resize(sz);
157 i = b.end();
158 }
159 /// @endcond
160
161 /// Marks the start of a class instance.
163 {
164 assert(_currentEncaps && _currentEncaps->decoder);
165 _currentEncaps->decoder->startInstance(ValueSlice);
166 }
167
168 /// Marks the end of a class instance.
169 /// @return An object that encapsulates the unknown slice data.
171 {
172 assert(_currentEncaps && _currentEncaps->decoder);
173 return _currentEncaps->decoder->endInstance();
174 }
175
176 /// Marks the start of a user exception.
178 {
179 assert(_currentEncaps && _currentEncaps->decoder);
180 _currentEncaps->decoder->startInstance(ExceptionSlice);
181 }
182
183 /// Marks the end of a user exception.
185 {
186 assert(_currentEncaps && _currentEncaps->decoder);
187 _currentEncaps->decoder->endInstance();
188 }
189
190 /// Reads the start of an encapsulation.
191 /// @return The encoding version used by the encapsulation.
193
194 /// Ends the current encapsulation.
196
197 /// Skips an empty encapsulation.
198 /// @return The encapsulation's encoding version.
200
201 /// Returns a blob of bytes representing an encapsulation.
202 /// @param[out] v A pointer into the internal marshaling buffer representing the start of the encoded
203 /// encapsulation.
204 /// @param[out] sz The number of bytes in the encapsulation.
205 /// @return encoding The encapsulation's encoding version.
206 EncodingVersion readEncapsulation(const std::byte*& v, std::int32_t& sz);
207
208 /// Gets the current encoding version.
209 /// @return The encoding version.
210 [[nodiscard]] const EncodingVersion& getEncoding() const
211 {
212 return _currentEncaps ? _currentEncaps->encoding : _encoding;
213 }
214
215 /// Gets the size of the current encapsulation, excluding the encapsulation header.
216 /// @return The size of the encapsulated data.
217 std::int32_t getEncapsulationSize();
218
219 /// Skips over an encapsulation.
220 /// @return The encoding version of the skipped encapsulation.
222
223 /// Reads the start of a value or exception slice.
225 {
226 assert(_currentEncaps && _currentEncaps->decoder);
227 _currentEncaps->decoder->startSlice();
228 }
229
230 /// Indicates that the end of a value or exception slice has been reached.
231 void endSlice()
232 {
233 assert(_currentEncaps && _currentEncaps->decoder);
234 _currentEncaps->decoder->endSlice();
235 }
236
237 /// Skips over a value or exception slice.
239 {
240 assert(_currentEncaps && _currentEncaps->decoder);
241 _currentEncaps->decoder->skipSlice();
242 }
243
244 /// Indicates that unmarshaling is complete, except for any class instances. The application must call this
245 /// function only when the stream actually contains class instances. Calling `readPendingValues` triggers the
246 /// patch callbacks to inform the application that unmarshaling of an instance is complete.
248
249 /// Reads a size from the stream.
250 /// @return The unmarshaled size.
251 std::int32_t readSize() // Inlined for performance reasons.
252 {
253 std::uint8_t byte;
254 read(byte);
255 auto val = static_cast<unsigned char>(byte);
256 if (val == 255)
257 {
258 std::int32_t v;
259 read(v);
260 if (v < 0)
261 {
262 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
263 }
264 return v;
265 }
266 else
267 {
268 return static_cast<std::int32_t>(static_cast<unsigned char>(byte));
269 }
270 }
271
272 /// Reads and validates a sequence size.
273 /// @param minSize The minimum size required by the sequence type.
274 /// @return The extracted size.
275 std::int32_t readAndCheckSeqSize(int minSize);
276
277 /// Reads a blob of bytes from the stream.
278 /// @param[out] bytes The vector to hold a copy of the bytes from the marshaling buffer.
279 /// @param sz The number of bytes to read.
280 void readBlob(std::vector<std::byte>& bytes, std::int32_t sz);
281
282 /// Reads a blob of bytes from the stream.
283 /// @param[out] v A pointer into the internal marshaling buffer representing the start of the blob.
284 /// @param sz The number of bytes to read.
285 void readBlob(const std::byte*& v, Container::size_type sz)
286 {
287 if (sz > 0)
288 {
289 v = i;
290 if (static_cast<Container::size_type>(b.end() - i) < sz)
291 {
292 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
293 }
294 i += sz;
295 }
296 else
297 {
298 v = i;
299 }
300 }
301
302 /// Reads a value from the stream.
303 /// @tparam T The type of the value to read.
304 /// @param[out] v The unmarshaled value.
305 template<typename T> void read(T& v) { StreamHelper<T, StreamableTraits<T>::helper>::read(this, v); }
306
307#ifdef ICE_DOXYGEN
308 /// Reads an optional value from the stream.
309 /// @tparam T The type of the value to read.
310 /// @param tag The tag.
311 /// @param[out] v The unmarshaled value.
312 template<typename T> void read(std::int32_t tag, T& v);
313#endif
314
315 /// Reads a value (single element list) from the stream.
316 /// @tparam T The type of value.
317 /// @param[out] v The unmarshaled value
318 template<typename T> void readAll(T& v) { read(v); }
319
320 /// Reads a list of values from the stream.
321 /// @tparam T The type of the first value.
322 /// @tparam Te The types of the remaining values.
323 /// @param[out] v The first unmarshaled value
324 /// @param[out] ve The remaining unmarshaled values.
325 template<typename T, typename... Te> void readAll(T& v, Te&... ve)
326 {
327 read(v);
328 readAll(ve...);
329 }
330
331 /// Reads an optional value (single element list) from the stream.
332 /// @tparam T The type of the value.
333 /// @param tags The tag list.
334 /// @param[out] v The unmarshaled value.
335 template<typename T> void readAll(std::initializer_list<std::int32_t> tags, std::optional<T>& v)
336 {
337 read(*(tags.begin() + tags.size() - 1), v);
338 }
339
340 /// Reads a list of optional values from the stream.
341 /// @tparam T The type of the first value.
342 /// @tparam Te The types of the remaining values.
343 /// @param tags The tag list.
344 /// @param[out] v The first unmarshaled value.
345 /// @param[out] ve The remaining unmarshaled values.
346 template<typename T, typename... Te>
347 void readAll(std::initializer_list<std::int32_t> tags, std::optional<T>& v, std::optional<Te>&... ve)
348 {
349 size_t index = tags.size() - sizeof...(ve) - 1;
350 read(*(tags.begin() + index), v);
351 readAll(tags, ve...);
352 }
353
354 /// Checks if an optional value is available for reading.
355 /// @param tag The tag associated with the value.
356 /// @param expectedFormat The optional format for the value.
357 /// @return `true` if the value is present, `false` otherwise.
358 bool readOptional(std::int32_t tag, OptionalFormat expectedFormat)
359 {
360 assert(_currentEncaps);
361 if (_currentEncaps->decoder)
362 {
363 return _currentEncaps->decoder->readOptional(tag, expectedFormat);
364 }
365 else
366 {
367 return readOptImpl(tag, expectedFormat);
368 }
369 }
370
371 /// @cond INTERNAL
372
373 // We don't document all the read "specializations" in Doxygen. But we do keep them mostly documented for
374 // tool-tips.
375
376 /// Reads an optional value from the stream.
377 /// @tparam T The type of the value to read.
378 /// @param tag The tag.
379 /// @param[out] v The unmarshaled value.
380 template<typename T, std::enable_if_t<!std::is_base_of_v<ObjectPrx, T>, bool> = true>
381 void read(std::int32_t tag, std::optional<T>& v)
382 {
383 if (readOptional(
384 tag,
386 optionalFormat))
387 {
388 v.emplace();
389 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::read(this, *v);
390 }
391 else
392 {
393 v = std::nullopt;
394 }
395 }
396
397 /// Reads an optional proxy from the stream.
398 /// @tparam T The type of the value to read.
399 /// @param tag The tag.
400 /// @param[out] v The proxy unmarshaled by this function. If nullopt, the proxy was not present in the stream or
401 /// was set to nullopt (set to nullopt is supported for backward compatibility with Ice 3.7 and earlier
402 /// releases).
403 template<typename T, std::enable_if_t<std::is_base_of_v<ObjectPrx, T>, bool> = true>
404 void read(std::int32_t tag, std::optional<T>& v)
405 {
406 if (readOptional(tag, OptionalFormat::FSize))
407 {
408 skip(4); // the fixed-length size on 4 bytes
409 read(v); // can be nullopt
410 }
411 else
412 {
413 v = std::nullopt;
414 }
415 }
416
417 /// Reads a sequence from the stream.
418 /// @param[out] v A pair of pointers representing the beginning and end of the sequence elements.
419 template<typename T> void read(std::pair<const T*, const T*>& v)
420 {
421 auto holder = new std::vector<T>;
422 _deleters.push_back([holder] { delete holder; });
423 read(*holder);
424 if (holder->size() > 0)
425 {
426 v.first = holder->data();
427 v.second = holder->data() + holder->size();
428 }
429 else
430 {
431 v.first = 0;
432 v.second = 0;
433 }
434 }
435
436#if defined(ICE_UNALIGNED) || (defined(_WIN32) && defined(ICE_API_EXPORTS))
437 // Optimization with unaligned reads
438 void read(std::pair<const std::int16_t*, const std::int16_t*>& v) { unalignedRead(v); }
439 void read(std::pair<const std::int32_t*, const std::int32_t*>& v) { unalignedRead(v); }
440 void read(std::pair<const std::int64_t*, const std::int64_t*>& v) { unalignedRead(v); }
441 void read(std::pair<const float*, const float*>& v) { unalignedRead(v); }
442 void read(std::pair<const double*, const double*>& v) { unalignedRead(v); }
443#endif
444
445 /// Reads a byte from the stream.
446 /// @param[out] v The extracted byte.
447 void read(std::byte& v)
448 {
449 if (i >= b.end())
450 {
451 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
452 }
453 v = *i++;
454 }
455
456 /// Reads a byte from the stream.
457 /// @param[out] v The extracted byte.
458 void read(std::uint8_t& v)
459 {
460 if (i >= b.end())
461 {
462 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
463 }
464 v = static_cast<std::uint8_t>(*i++);
465 }
466
467 /// Reads a sequence of bytes from the stream.
468 /// @param[out] v A vector to hold a copy of the bytes.
469 void read(std::vector<std::byte>& v);
470
471 /// Reads a sequence of bytes from the stream.
472 /// @param[out] v A pair of pointers into the internal marshaling buffer representing the start and end of the
473 /// sequence elements.
474 void read(std::pair<const std::byte*, const std::byte*>& v);
475
476 /// Reads a bool from the stream.
477 /// @param[out] v The extracted bool.
478 void read(bool& v)
479 {
480 if (i >= b.end())
481 {
482 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
483 }
484 v = (std::byte{0} != *i++);
485 }
486
487 /// Reads a sequence of boolean values from the stream.
488 /// @param[out] v A vector to hold a copy of the boolean values.
489 void read(std::vector<bool>& v);
490
491 /// Reads a sequence of boolean values from the stream.
492 /// @param[out] v A pair of pointers into the internal marshaling buffer representing the start and end of the
493 /// sequence elements.
494 void read(std::pair<const bool*, const bool*>& v);
495
496 /// Reads a short into an int16_t.
497 /// @param[out] v The extracted int16_t.
498 void read(std::int16_t& v);
499
500 /// Reads a sequence of Slice shorts into a vector of int16_t.
501 /// @param[out] v A vector to hold a copy of the int16_t values.
502 void read(std::vector<std::int16_t>& v);
503
504 /// Reads an int from the stream.
505 /// @param[out] v The extracted int.
506 void read(std::int32_t& v);
507
508 /// Reads a sequence of ints from the stream.
509 /// @param[out] v A vector to hold a copy of the int values.
510 void read(std::vector<std::int32_t>& v);
511
512 /// Reads a long from the stream.
513 /// @param[out]v The extracted long.
514 void read(std::int64_t& v);
515
516 /// Reads a sequence of longs from the stream.
517 /// @param[out] v A vector to hold a copy of the long values.
518 void read(std::vector<std::int64_t>& v);
519
520 /// Read a float into a float.
521 /// @param[out] v The extracted float.
522 void read(float& v);
523
524 /// Reads a sequence of floats into a vector of float.
525 /// @param[out] v An output vector filled by this function.
526 void read(std::vector<float>& v);
527
528 /// Reads a double into a double.
529 /// @param[out] v The extracted double.
530 void read(double& v);
531
532 /// Reads a sequence of doubles into a vector of double.
533 /// @param[out] v An output vector filled by this function.
534 void read(std::vector<double>& v);
535
536 /// @endcond
537
538 // We document read functions with an extra parameter.
539
540 /// Reads a string from the stream.
541 /// @param[out] v The unmarshaled string.
542 /// @param convert `true` to process the unmarshaled string through the string converter (if installed on the
543 /// communicator), `false` otherwise.
544 void read(std::string& v, bool convert = true);
545
546 /// Reads a string from the stream.
547 /// @param[out] vdata A pointer to the beginning of the string.
548 /// @param[out] vsize The number of bytes in the string.
549 /// @param convert `true` to process the unmarshaled string through the string converter (if installed on the
550 /// communicator), `false` otherwise.
551 void read(const char*& vdata, size_t& vsize, bool convert = true);
552
553 /// Reads a sequence of strings from the stream.
554 /// @param[out] v The unmarshaled string sequence.
555 /// @param convert `true` to process the unmarshaled string through the string converter (if installed on the
556 /// communicator), `false` otherwise.
557 void read(std::vector<std::string>& v, bool convert = true);
558
559 /// @cond INTERNAL
560
561 /// Reads a wide string from the stream.
562 /// @param[out] v The extracted string.
563 void read(std::wstring& v);
564
565 /// Reads a sequence of wide strings from the stream.
566 /// @param[out] v The extracted sequence.
567 void read(std::vector<std::wstring>& v);
568
569 /// Reads a typed proxy from the stream.
570 /// @tparam Prx The type of the value to read.
571 /// @param[out] v The unmarshaled proxy.
572 template<typename Prx, std::enable_if_t<std::is_base_of_v<ObjectPrx, Prx>, bool> = true>
573 void read(std::optional<Prx>& v)
574 {
575 IceInternal::ReferencePtr ref = readReference();
576 if (ref)
577 {
578 v = Prx::_fromReference(ref);
579 }
580 else
581 {
582 v = std::nullopt;
583 }
584 }
585
586 /// Reads an instance of a Slice class from the stream.
587 /// @tparam T The type of the value to read.
588 /// @param[out] v The unmarshaled instance.
589 template<typename T, std::enable_if_t<std::is_base_of_v<Value, T>>* = nullptr> void read(std::shared_ptr<T>& v)
590 {
591 read(patchValue<T>, &v);
592 }
593
594 /// @private
595 /// Reads a value (instance of a Slice class) from the stream.
596 /// @param patchFunc The patch callback function.
597 /// @param patchAddr Closure data passed to the callback.
598 void read(PatchFunc patchFunc, void* patchAddr)
599 {
600 initEncaps();
601 _currentEncaps->decoder->read(std::move(patchFunc), patchAddr);
602 }
603
604 /// @endcond
605
606 /// Reads an enumerator from the stream.
607 /// @param maxValue The maximum enumerator value in the definition.
608 /// @return The enumerator value.
609 std::int32_t readEnum(std::int32_t maxValue);
610
611 /// Reads a user exception from the stream and throws it.
612 /// @param factory The factory function that creates the exception instance. When null, the exception is created
613 /// using helper functions generated by the Slice compiler.
614 /// @throws UserException The user exception that was unmarshaled.
615 void throwException(UserExceptionFactory factory = nullptr);
616
617 /// Skips one optional value with the given format.
618 /// @param format The expected format of the optional, if present.
620
621 /// Skips all remaining optional values.
623
624 /// Advances the current stream position by the given number of bytes.
625 /// @param size The number of bytes to skip.
626 void skip(size_type size)
627 {
628 if (i + size > b.end())
629 {
630 throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
631 }
632 i += size;
633 }
634
635 /// Reads a size at the current position and skips that number of bytes.
636 void skipSize()
637 {
638 std::uint8_t bt;
639 read(bt);
640 if (static_cast<unsigned char>(bt) == 255)
641 {
642 skip(4);
643 }
644 }
645
646 /// Gets the current position of the stream.
647 /// @return The current position.
648 size_type pos() { return static_cast<size_t>(i - b.begin()); }
649
650 /// Sets a new position for the stream.
651 /// @param p The new position.
652 void pos(size_type p) { i = b.begin() + p; }
653
654 /// @private
655 bool readOptImpl(std::int32_t, OptionalFormat);
656
657 private:
658#if defined(ICE_UNALIGNED) || (defined(_WIN32) && defined(ICE_API_EXPORTS))
659 template<typename T> void unalignedRead(std::pair<const T*, const T*>& v)
660 {
661 int sz = readAndCheckSeqSize(static_cast<int>(sizeof(T)));
662
663 if (sz > 0)
664 {
665 v.first = reinterpret_cast<T*>(i);
666 i += sz * static_cast<int>(sizeof(T));
667 v.second = reinterpret_cast<T*>(i);
668 }
669 else
670 {
671 v.first = v.second = nullptr;
672 }
673 }
674#endif
675
676 // The primary constructor, called by all other constructors. It requires a non-null instance.
677 InputStream(
678 IceInternal::Instance* instance,
679 EncodingVersion encoding,
680 IceInternal::Buffer&& buf,
681 SliceLoaderPtr sliceLoader);
682
683 // Reads a reference from the stream; the return value can be null.
684 IceInternal::ReferencePtr readReference();
685
686 bool readConverted(std::string&, std::int32_t);
687
688 void throwUnmarshalOutOfBoundsException(const char*, int);
689
690 class Encaps;
691 enum SliceType
692 {
693 NoSlice,
694 ValueSlice,
695 ExceptionSlice
696 };
697
698 void traceSkipSlice(std::string_view, SliceType) const;
699
700 using ValueList = std::vector<ValuePtr>;
701
702 class ICE_API EncapsDecoder
703 {
704 public:
705 EncapsDecoder(const EncapsDecoder&) = delete;
706 virtual ~EncapsDecoder();
707
708 EncapsDecoder& operator=(const EncapsDecoder&) = delete;
709
710 virtual void read(PatchFunc, void*) = 0;
711 virtual void throwException(UserExceptionFactory) = 0;
712
713 virtual void startInstance(SliceType) = 0;
714 virtual SlicedDataPtr endInstance() = 0;
715 virtual void startSlice() = 0;
716 virtual void endSlice() = 0;
717 virtual void skipSlice() = 0;
718
719 virtual bool readOptional(std::int32_t, OptionalFormat) { return false; }
720
721 virtual void readPendingValues() {}
722
723 protected:
724 EncapsDecoder(InputStream* stream, Encaps* encaps, std::int32_t classGraphDepthMax)
725 : _stream(stream),
726 _encaps(encaps),
727 _classGraphDepthMax(classGraphDepthMax)
728 {
729 }
730
731 std::string readTypeId(bool);
732 ValuePtr newInstance(std::string_view);
733
734 void addPatchEntry(std::int32_t, const PatchFunc&, void*);
735 void unmarshal(std::int32_t, const ValuePtr&);
736
737 using IndexToPtrMap = std::map<std::int32_t, ValuePtr>;
738 using TypeIdMap = std::map<std::int32_t, std::string>;
739
740 /// @private
741 struct PatchEntry
742 {
743 PatchFunc patchFunc;
744 void* patchAddr;
745 std::int32_t classGraphDepth;
746 };
747 using PatchList = std::vector<PatchEntry>;
748 using PatchMap = std::map<std::int32_t, PatchList>;
749
750 InputStream* _stream;
751 Encaps* _encaps;
752 const std::int32_t _classGraphDepthMax;
753 std::int32_t _classGraphDepth{0};
754
755 // Encapsulation attributes for object un-marshaling
756 PatchMap _patchMap;
757
758 private:
759 // Encapsulation attributes for object un-marshaling
760 IndexToPtrMap _unmarshaledMap;
761 TypeIdMap _typeIdMap;
762 std::int32_t _typeIdIndex{0};
763 ValueList _valueList;
764 };
765
766 class ICE_API EncapsDecoder10 : public EncapsDecoder
767 {
768 public:
769 EncapsDecoder10(InputStream* stream, Encaps* encaps, std::int32_t classGraphDepthMax)
770 : EncapsDecoder(stream, encaps, classGraphDepthMax)
771 {
772 }
773
774 void read(PatchFunc, void*) override;
775 void throwException(UserExceptionFactory) override;
776
777 void startInstance(SliceType) override;
778 SlicedDataPtr endInstance() override;
779 void startSlice() override;
780 void endSlice() override;
781 void skipSlice() override;
782
783 void readPendingValues() override;
784
785 private:
786 void readInstance();
787
788 // Instance attributes
789 SliceType _sliceType{NoSlice};
790 bool _skipFirstSlice{false};
791
792 // Slice attributes
793 std::int32_t _sliceSize{0};
794 std::string _typeId;
795 };
796
797 class ICE_API EncapsDecoder11 : public EncapsDecoder
798 {
799 public:
800 EncapsDecoder11(InputStream* stream, Encaps* encaps, std::int32_t classGraphDepthMax)
801 : EncapsDecoder(stream, encaps, classGraphDepthMax),
802 _preAllocatedInstanceData(nullptr)
803 {
804 }
805
806 void read(PatchFunc, void*) override;
807 void throwException(UserExceptionFactory) override;
808
809 void startInstance(SliceType) override;
810 SlicedDataPtr endInstance() override;
811 void startSlice() override;
812 void endSlice() override;
813 void skipSlice() override;
814
815 bool readOptional(std::int32_t, OptionalFormat) override;
816
817 private:
818 std::int32_t readInstance(std::int32_t, const PatchFunc&, void*);
819 SlicedDataPtr readSlicedData();
820
821 struct IndirectPatchEntry
822 {
823 std::int32_t index;
824 PatchFunc patchFunc;
825 void* patchAddr;
826 };
827 using IndirectPatchList = std::vector<IndirectPatchEntry>;
828
829 using IndexList = std::vector<std::int32_t>;
830 using IndexListList = std::vector<IndexList>;
831
832 struct InstanceData
833 {
834 InstanceData(InstanceData* p) : previous(p)
835 {
836 if (previous)
837 {
838 previous->next = this;
839 }
840 }
841
842 ~InstanceData()
843 {
844 if (next)
845 {
846 delete next;
847 }
848 }
849
850 // Instance attributes
851 SliceType sliceType{NoSlice};
852 bool skipFirstSlice{false};
853 SliceInfoSeq slices; // Preserved slices.
854 IndexListList indirectionTables;
855
856 // Slice attributes
857 std::uint8_t sliceFlags{0};
858 std::int32_t sliceSize{0};
859 std::string typeId;
860 int compactId{-1};
861 IndirectPatchList indirectPatchList;
862
863 InstanceData* previous{nullptr};
864 InstanceData* next{nullptr};
865 };
866 InstanceData _preAllocatedInstanceData;
867 InstanceData* _current{nullptr};
868
869 void push(SliceType sliceType)
870 {
871 if (!_current)
872 {
873 _current = &_preAllocatedInstanceData;
874 }
875 else
876 {
877 _current = _current->next ? _current->next : new InstanceData(_current);
878 }
879 _current->sliceType = sliceType;
880 _current->skipFirstSlice = false;
881 }
882
883 std::int32_t _valueIdIndex{1}; // The ID of the next value to unmarshal.
884 };
885
886 class Encaps
887 {
888 public:
889 Encaps() = default;
890 Encaps(const Encaps&) = delete;
891 ~Encaps() { delete decoder; }
892 Encaps& operator=(const Encaps&) = delete;
893
894 void reset()
895 {
896 // Inlined for performance reasons.
897 delete decoder;
898 decoder = nullptr;
899
900 previous = nullptr;
901 }
902
903 Container::size_type start{0};
904 std::int32_t sz;
905 EncodingVersion encoding;
906
907 EncapsDecoder* decoder{nullptr};
908
909 Encaps* previous{nullptr};
910 };
911
912 // Optimization. The instance may not be deleted while a stack-allocated stream still holds it.
913 IceInternal::Instance* const _instance;
914
915 //
916 // The encoding version to use when there's no encapsulation to
917 // read from. This is for example used to read message headers.
918 //
919 EncodingVersion _encoding;
920
921 Encaps* _currentEncaps{nullptr};
922
923 void initEncaps();
924
925 Encaps _preAllocatedEncaps;
926
927 // Retrieved during construction and cached.
928 const std::int32_t _classGraphDepthMax;
929
930 void* _closure{nullptr};
931
932 int _startSeq{-1};
933 int _minSeqSize{0};
934
935 const SliceLoaderPtr _sliceLoader; // never null
936
937 std::vector<std::function<void()>> _deleters;
938 };
939
940} // End namespace Ice
941
942#endif
void readAll(T &v, Te &... ve)
Reads a list of values from the stream.
InputStream(const CommunicatorPtr &communicator, EncodingVersion encoding, const std::vector< std::byte > &bytes, SliceLoaderPtr sliceLoader=nullptr)
Constructs an InputStream using a communicator and encoding version.
InputStream(InputStream &&other) noexcept
Move constructor.
void readBlob(const std::byte *&v, Container::size_type sz)
Reads a blob of bytes from the stream.
InputStream & operator=(InputStream &&other) noexcept
Move assignment operator.
void readAll(std::initializer_list< std::int32_t > tags, std::optional< T > &v)
Reads an optional value (single element list) from the stream.
void endEncapsulation()
Ends the current encapsulation.
void skipOptional(OptionalFormat format)
Skips one optional value with the given format.
void endException()
Marks the end of a user exception.
bool readOptional(std::int32_t tag, OptionalFormat expectedFormat)
Checks if an optional value is available for reading.
InputStream(const CommunicatorPtr &communicator, EncodingVersion encoding, std::pair< const std::byte *, const std::byte * > bytes, SliceLoaderPtr sliceLoader=nullptr)
Constructs an InputStream using a communicator and encoding version.
void skipSlice()
Skips over a value or exception slice.
void readPendingValues()
Indicates that unmarshaling is complete, except for any class instances.
void skipSize()
Reads a size at the current position and skips that number of bytes.
EncodingVersion skipEncapsulation()
Skips over an encapsulation.
void readBlob(std::vector< std::byte > &bytes, std::int32_t sz)
Reads a blob of bytes from the stream.
void skipOptionals()
Skips all remaining optional values.
void read(std::int32_t tag, T &v)
Reads an optional value from the stream.
InputStream(const CommunicatorPtr &communicator, std::pair< const std::byte *, const std::byte * > bytes, SliceLoaderPtr sliceLoader=nullptr)
Constructs an InputStream using a communicator and this communicator's default encoding version.
void endSlice()
Indicates that the end of a value or exception slice has been reached.
void startValue()
Marks the start of a class instance.
const EncodingVersion & startEncapsulation()
Reads the start of an encapsulation.
void swap(InputStream &other) noexcept
Swaps the contents of one stream with another.
std::int32_t readSize()
Reads a size from the stream.
void readAll(std::initializer_list< std::int32_t > tags, std::optional< T > &v, std::optional< Te > &... ve)
Reads a list of optional values from the stream.
void startException()
Marks the start of a user exception.
void startSlice()
Reads the start of a value or exception slice.
void skip(size_type size)
Advances the current stream position by the given number of bytes.
SlicedDataPtr endValue()
Marks the end of a class instance.
size_type pos()
Gets the current position of the stream.
void throwException(UserExceptionFactory factory=nullptr)
Reads a user exception from the stream and throws it.
void read(const char *&vdata, size_t &vsize, bool convert=true)
Reads a string from the stream.
std::int32_t getEncapsulationSize()
Gets the size of the current encapsulation, excluding the encapsulation header.
std::int32_t readAndCheckSeqSize(int minSize)
Reads and validates a sequence size.
EncodingVersion skipEmptyEncapsulation()
Skips an empty encapsulation.
void read(T &v)
Reads a value from the stream.
std::size_t size_type
The size type for this byte buffer.
Definition InputStream.h:53
void pos(size_type p)
Sets a new position for the stream.
void read(std::string &v, bool convert=true)
Reads a string from the stream.
const EncodingVersion & getEncoding() const
Gets the current encoding version.
InputStream(const CommunicatorPtr &communicator, const std::vector< std::byte > &bytes, SliceLoaderPtr sliceLoader=nullptr)
Constructs an InputStream using a communicator and this communicator's default encoding version.
void clear()
Releases any data retained by encapsulations.
void readAll(T &v)
Reads a value (single element list) from the stream.
EncodingVersion readEncapsulation(const std::byte *&v, std::int32_t &sz)
Returns a blob of bytes representing an encapsulation.
void read(std::vector< std::string > &v, bool convert=true)
Reads a sequence of strings from the stream.
std::int32_t readEnum(std::int32_t maxValue)
Reads an enumerator from the stream.
The base class for all Ice proxies.
Definition Proxy.h:232
std::shared_ptr< Communicator > CommunicatorPtr
A shared pointer to a Communicator.
OptionalFormat
The optional format, used for marshaling optional fields and arguments.
std::shared_ptr< SliceLoader > SliceLoaderPtr
A shared pointer to a SliceLoader.
Definition SliceLoader.h:44
std::vector< SliceInfoPtr > SliceInfoSeq
The slices of unknown types.
Definition SlicedDataF.h:17
std::function< void(std::string_view)> UserExceptionFactory
Creates and throws a user exception.
std::shared_ptr< Value > ValuePtr
A shared pointer to a Value.
Definition ValueF.h:13
std::shared_ptr< SlicedData > SlicedDataPtr
A shared pointer to a SlicedData.
Definition SlicedDataF.h:22
The Ice RPC framework.
Definition SampleEvent.h:59
Represents a version of the Slice encoding.
Definition Version.h:65
A helper template class for writing (marshaling) and reading (unmarshaling) values to and from a stre...
static constexpr bool fixedLength
Indicates if the type is always encoded on a fixed number of bytes.
static constexpr StreamHelperCategory helper
The category trait, used for selecting the appropriate StreamHelper.