Ice 3.8
C++ API Reference
Loading...
Searching...
No Matches
OutputStream.h
1// Copyright (c) ZeroC, Inc.
2
3#ifndef ICE_OUTPUT_STREAM_H
4#define ICE_OUTPUT_STREAM_H
5
6#include "Buffer.h"
7#include "CommunicatorF.h"
8#include "Ice/Format.h"
9#include "Ice/StringConverter.h"
10#include "Ice/Version.h"
11#include "Ice/VersionFunctions.h"
12#include "InstanceF.h"
13#include "SlicedDataF.h"
14#include "StreamableTraits.h"
15#include "ValueF.h"
16
17#include <cassert>
18#include <cstdint>
19#include <cstring>
20#include <map>
21#include <string>
22#include <string_view>
23#include <vector>
24
25namespace Ice
26{
27 class ObjectPrx;
28
29 /// Represents a byte buffer used for marshaling data using the Slice encoding.
30 /// @headerfile Ice/Ice.h
31 class ICE_API OutputStream : public IceInternal::Buffer
32 {
33 public:
34 /// The size type for this byte buffer.
35 using size_type = std::size_t;
36
37 /// Constructs an OutputStream.
38 /// @param encoding The encoding version to use.
39 /// @param format The class format to use.
40 /// @param stringConverter The narrow string converter to use.
41 /// @param wstringConverter The wide string converter to use.
45 StringConverterPtr stringConverter = nullptr,
46 WstringConverterPtr wstringConverter = nullptr);
47
48 /// Constructs an OutputStream using the format, string converter and wstring converter provided by the
49 /// communicator, and the specified encoding.
50 /// @param communicator The communicator.
51 /// @param encoding The encoding version to use.
52 OutputStream(const CommunicatorPtr& communicator, EncodingVersion encoding);
53
54 /// Constructs an OutputStream using the encoding, format, string converter and wstring converter provided by
55 /// the communicator.
56 /// @param communicator The communicator.
57 OutputStream(const CommunicatorPtr& communicator);
58
59 /// Constructs an OutputStream over an application-supplied buffer.
60 /// @param bytes Application-supplied memory that the OutputStream uses as its initial marshaling buffer. The
61 /// stream will reallocate if the size of the marshaled data exceeds the application's buffer.
62 /// @param encoding The encoding version to use.
63 /// @param format The class format to use.
64 /// @param stringConverter The narrow string converter to use.
65 /// @param wstringConverter The wide string converter to use.
67 std::pair<const std::byte*, const std::byte*> bytes,
70 StringConverterPtr stringConverter = nullptr,
71 WstringConverterPtr wstringConverter = nullptr);
72
73 /// Move constructor.
74 /// @param other The output stream to move into this output stream.
75 OutputStream(OutputStream&& other) noexcept;
76
77 /// Move assignment operator.
78 /// @param other The output stream to move into this output stream.
79 /// @return A reference to this output stream.
81
83 {
84 // Inlined for performance reasons.
85
86 if (_currentEncaps != &_preAllocatedEncaps)
87 {
88 clear(); // Not inlined.
89 }
90 }
91
92 /// Releases any data retained by encapsulations.
93 void clear();
94
95 /// Swaps the contents of one stream with another.
96 /// @param other The other stream.
97 void swap(OutputStream& other) noexcept;
98
99 /// @cond INTERNAL
100
101 /// Gets the closure associated with this stream.
102 /// @return The closure.
103 [[nodiscard]] void* getClosure() const;
104
105 /// Associates a closure with this stream.
106 /// @param p The closure
107 /// @return The previous closure, or nullptr.
108 void* setClosure(void* p);
109
110 void resetEncapsulation();
111 /// @endcond
112
113 /// Resizes the stream to a new size.
114 /// @param sz The new size.
115 void resize(Container::size_type sz) { b.resize(sz); }
116
117 /// Marks the start of a class instance.
118 /// @param data Contains the marshaled form of unknown slices from the class instance. If not nullptr, these
119 /// slices will be marshaled with the instance.
120 void startValue(const SlicedDataPtr& data)
121 {
122 assert(_currentEncaps && _currentEncaps->encoder);
123 _currentEncaps->encoder->startInstance(ValueSlice, data);
124 }
125
126 /// Marks the end of a class instance.
127 void endValue()
128 {
129 assert(_currentEncaps && _currentEncaps->encoder);
130 _currentEncaps->encoder->endInstance();
131 }
132
133 /// Marks the start of an exception instance.
135 {
136 assert(_currentEncaps && _currentEncaps->encoder);
137 _currentEncaps->encoder->startInstance(ExceptionSlice, nullptr);
138 }
139
140 /// Marks the end of an exception instance.
142 {
143 assert(_currentEncaps && _currentEncaps->encoder);
144 _currentEncaps->encoder->endInstance();
145 }
146
147 /// Writes the start of an encapsulation using the default encoding version and class encoding format.
149
150 /// Writes the start of an encapsulation using the specified encoding version and class encoding format.
151 /// @param encoding The encoding version to use for the encapsulation.
152 /// @param format The class format to use for the encapsulation. nullopt is equivalent to the OutputStream's
153 /// class format.
154 void startEncapsulation(const EncodingVersion& encoding, std::optional<FormatType> format);
155
156 /// Ends the current encapsulation.
158
159 /// Writes an empty encapsulation using the specified encoding version.
160 /// @param encoding The encoding version to use for the encapsulation.
162
163 /// Copies the marshaled form of an encapsulation to the buffer.
164 /// @param v The start of the buffer.
165 /// @param sz The number of bytes to copy.
166 void writeEncapsulation(const std::byte* v, std::int32_t sz);
167
168 /// Gets the current encoding version.
169 /// @return The encoding version.
170 [[nodiscard]] const EncodingVersion& getEncoding() const
171 {
172 return _currentEncaps ? _currentEncaps->encoding : _encoding;
173 }
174
175 /// Writes the start of a class instance or exception slice.
176 /// @param typeId The Slice type ID for this slice.
177 /// @param compactId The compact ID corresponding to the type, or -1 if no compact ID is used.
178 /// @param last `true` if this is the last slice, `false` otherwise.
179 void startSlice(std::string_view typeId, int compactId, bool last)
180 {
181 assert(_currentEncaps && _currentEncaps->encoder);
182 _currentEncaps->encoder->startSlice(typeId, compactId, last);
183 }
184
185 /// Marks the end of a class instance or exception slice.
186 void endSlice()
187 {
188 assert(_currentEncaps && _currentEncaps->encoder);
189 _currentEncaps->encoder->endSlice();
190 }
191
192 /// Encodes the state of class instances whose insertion was delayed during a previous call `write`. This
193 /// function must be called only once. For backward compatibility with encoding version 1.0, this function must
194 /// be called only when non-optional fields or parameters use class types.
196
197 /// Writes a size value.
198 /// @param v A non-negative integer.
199 void writeSize(std::int32_t v) // Inlined for performance reasons.
200 {
201 assert(v >= 0);
202 if (v > 254)
203 {
204 write(std::uint8_t(255));
205 write(v);
206 }
207 else
208 {
209 write(static_cast<std::uint8_t>(v));
210 }
211 }
212
213 /// Replaces a size value at the specified position in the stream. This function does not change the stream's
214 /// current position.
215 /// @param v A non-negative integer representing the size.
216 /// @param dest The buffer destination for the size.
217 void rewriteSize(std::int32_t v, Container::iterator dest)
218 {
219 assert(v >= 0);
220 if (v > 254)
221 {
222 *dest++ = std::byte{255};
223 write(v, dest);
224 }
225 else
226 {
227 *dest = static_cast<std::byte>(v);
228 }
229 }
230
231 /// Writes a placeholder value for the size and returns the starting position of the size value; after writing
232 /// the data, call #endSize to patch the placeholder with the actual size at the given position.
233 /// @return The starting position of the size value.
235 {
236 size_type position = b.size();
237 write(std::int32_t(0));
238 return position;
239 }
240
241 /// Updates the size value at the given position. The new size is computed from stream's current position.
242 /// @param position The starting position of the size value as returned by #startSize.
243 void endSize(size_type position) { rewrite(static_cast<std::int32_t>(b.size() - position) - 4, position); }
244
245 /// Copies the specified blob of bytes to the stream without modification.
246 /// @param v The bytes to copy.
247 void writeBlob(const std::vector<std::byte>& v);
248
249 /// Copies the specified blob of bytes to the stream without modification.
250 /// @param v The start of the buffer to copy.
251 /// @param sz The number of bytes to copy.
252 void writeBlob(const std::byte* v, Container::size_type sz)
253 {
254 if (sz > 0)
255 {
256 Container::size_type position = b.size();
257 resize(position + sz);
258 memcpy(&b[position], &v[0], sz);
259 }
260 }
261
262 /// Writes a value to the stream.
263 /// @tparam T The type of the value to marshal.
264 /// @param v The value to marshal.
265 template<typename T> void write(const T& v) { StreamHelper<T, StreamableTraits<T>::helper>::write(this, v); }
266
267#ifdef ICE_DOXYGEN
268 /// Writes an optional value to the stream.
269 /// @tparam T The type of the value to marshal.
270 /// @param tag The tag.
271 /// @param v The value to marshal.
272 template<typename T> void write(std::int32_t tag, const std::optional<T>& v);
273
274 /// Writes a tuple to the stream.
275 /// @tparam I The index of the first element to marshal.
276 /// @tparam Te The types of the values in the tuple, starting at index @p I.
277 /// @param tuple The tuple to marshal.
278 // Declared here because the actual definition below breaks doxygen 1.13.2.
279 template<size_t I = 0, typename... Te >> writeAll(std::tuple<Te...> tuple);
280#endif
281
282 /// Writes a value (single element list) to the stream.
283 /// @tparam T The type of the value.
284 /// @param v The value to marshal.
285 template<typename T> void writeAll(const T& v) { write(v); }
286
287 /// Writes a list of values to the stream.
288 /// @tparam T The type of the first value.
289 /// @tparam Te The types of the remaining values.
290 /// @param v The first value to marshal.
291 /// @param ve The remaining values.
292 template<typename T, typename... Te> void writeAll(const T& v, const Te&... ve)
293 {
294 write(v);
295 writeAll(ve...);
296 }
297
298 /// Writes an optional value (single element list) to the stream.
299 /// @tparam T The type of the value.
300 /// @param tags The tag list. The last tag is used to marshal the value.
301 /// @param v The value to marshal.
302 template<typename T> void writeAll(std::initializer_list<std::int32_t> tags, const std::optional<T>& v)
303 {
304 write(*(tags.begin() + tags.size() - 1), v);
305 }
306
307 /// Writes a list of optional values to the stream.
308 /// @tparam T The type of the first value.
309 /// @tparam Te The types of the remaining values.
310 /// @param tags The tag list.
311 /// @param v The first value to marshal.
312 /// @param ve The remaining values.
313 template<typename T, typename... Te>
314 void
315 writeAll(std::initializer_list<std::int32_t> tags, const std::optional<T>& v, const std::optional<Te>&... ve)
316 {
317 size_t index = tags.size() - sizeof...(ve) - 1;
318 write(*(tags.begin() + index), v);
319 writeAll(tags, ve...);
320 }
321
322 /// Writes the tag and format of an optional value.
323 /// @param tag The tag.
324 /// @param format The optional format.
325 /// @return `true` if the current encoding version supports optional values, `false` otherwise.
326 /// If `true`, the data associated with the optional value must be written next.
327 bool writeOptional(std::int32_t tag, OptionalFormat format)
328 {
329 assert(_currentEncaps);
330 if (_currentEncaps->encoder)
331 {
332 return _currentEncaps->encoder->writeOptional(tag, format);
333 }
334 else
335 {
336 return writeOptImpl(tag, format);
337 }
338 }
339
340 /// @cond INTERNAL
341
342 // We don't document all the write "specializations" in Doxygen. But we do keep them mostly documented for
343 // tool-tips.
344
345 /// Writes an optional value to the stream.
346 /// @tparam T The type of the value to marshal. Not for proxy types.
347 /// @param tag The tag.
348 /// @param v The value to marshal.
349 template<typename T, std::enable_if_t<!std::is_base_of_v<ObjectPrx, T>, bool> = true>
350 void write(std::int32_t tag, const std::optional<T>& v)
351 {
352 if (!v)
353 {
354 return; // Optional not set
355 }
356
357 if (writeOptional(
358 tag,
359 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::
360 optionalFormat))
361 {
362 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::write(this, *v);
363 }
364 }
365
366 /// Writes an optional value to the stream.
367 /// @tparam T The proxy type.
368 /// @param tag The tag.
369 /// @param v The value to marshal.
370 template<typename T, std::enable_if_t<std::is_base_of_v<ObjectPrx, T>, bool> = true>
371 void write(std::int32_t tag, const std::optional<T>& v)
372 {
373 if (!v)
374 {
375 return; // Optional not set
376 }
377
378 if (writeOptional(tag, OptionalFormat::FSize))
379 {
380 size_type pos = startSize();
381 writeProxy(*v);
382 endSize(pos);
383 }
384 }
385
386 /// Writes a sequence to the stream.
387 /// @tparam T The type of the elements in the sequence.
388 /// @param v The sequence to marshal.
389 template<typename T> void write(const std::vector<T>& v)
390 {
391 if (v.empty())
392 {
393 writeSize(0);
394 }
395 else
396 {
397 write(&v[0], &v[0] + v.size());
398 }
399 }
400
401 /// Writes a sequence to the stream.
402 /// @tparam T The type of the elements in the sequence.
403 /// @param begin The beginning of the sequence.
404 /// @param end The end of the sequence.
405 template<typename T> void write(const T* begin, const T* end)
406 {
407 writeSize(static_cast<std::int32_t>(end - begin));
408 for (const T* p = begin; p != end; ++p)
409 {
410 write(*p);
411 }
412 }
413
414 // Helper function for the next writeAll.
415 template<size_t I = 0, typename... Te> std::enable_if_t<I == sizeof...(Te), void> writeAll(std::tuple<Te...>)
416 {
417 // Do nothing. Either tuple is empty or we are at the end.
418 }
419
420 /// Writes a tuple to the stream.
421 /// @tparam I The index of the first element to marshal.
422 /// @tparam Te The types of the values in the tuple, starting at index @p I.
423 /// @param tuple The tuple to marshal.
424 template<size_t I = 0, typename... Te>
425 std::enable_if_t < I<sizeof...(Te), void> writeAll(std::tuple<Te...> tuple)
426 {
427 write(std::get<I>(tuple));
428 writeAll<I + 1, Te...>(tuple);
429 }
430
431 /// Writes a byte to the stream.
432 /// @param v The byte to marshal.
433 void write(std::byte v) { b.push_back(v); }
434
435 /// Writes a byte to the stream.
436 /// @param v The byte to marshal.
437 void write(std::uint8_t v) { b.push_back(std::byte{v}); }
438
439 /// Writes a boolean to the stream.
440 /// @param v The boolean to marshal.
441 void write(bool v) { b.push_back(static_cast<std::byte>(v)); }
442
443 /// Writes a boolean sequence to the stream.
444 /// @param v The sequence to be written.
445 void write(const std::vector<bool>& v);
446
447 /// Writes an int16_t as a Slice short.
448 /// @param v The int16_t to marshal.
449 void write(std::int16_t v);
450
451 /// Writes an int to the stream.
452 /// @param v The int to marshal.
453 void write(std::int32_t v) // Inlined for performance reasons.
454 {
455 Container::size_type position = b.size();
456 resize(position + sizeof(std::int32_t));
457 write(v, &b[position]);
458 }
459
460 /// Writes a long to the stream.
461 /// @param v The long to marshal.
462 void write(std::int64_t v);
463
464 /// Writes a float as a Slice float.
465 /// @param v The float to marshal.
466 void write(float v);
467
468 /// Writes a double as a Slice double.
469 /// @param v The double to marshal.
470 void write(double v);
471
472 /// Writes a wide string to the stream.
473 /// @param v The wide string to marshal.
474 void write(const std::wstring& v) { write(std::wstring_view(v)); }
475
476 /// Writes a wide string view to the stream.
477 /// @param v The wide string view to marshal.
478 void write(std::wstring_view v);
479
480 /// @endcond
481
482 /// Overwrites a 32-bit integer value at the given position in the stream.
483 /// This function does not change the stream's current position.
484 /// @param v The integer value to marshal.
485 /// @param dest The buffer destination for the integer value.
486 void write(std::int32_t v, Container::iterator dest);
487
488 /// Writes a byte sequence to the stream.
489 /// @param start The beginning of the sequence.
490 /// @param end The end of the sequence.
491 void write(const std::byte* start, const std::byte* end);
492
493 /// Writes a byte sequence to the stream.
494 /// @param start The beginning of the sequence.
495 /// @param end The end of the sequence.
496 void write(const std::uint8_t* start, const std::uint8_t* end);
497
498 /// Writes a boolean sequence to the stream.
499 /// @param begin The beginning of the sequence.
500 /// @param end The end of the sequence.
501 void write(const bool* begin, const bool* end);
502
503 /// Writes an int16_t sequence as a Slice short sequence.
504 /// @param begin The beginning of the sequence.
505 /// @param end The end of the sequence.
506 void write(const std::int16_t* begin, const std::int16_t* end);
507
508 /// Writes an int sequence to the stream.
509 /// @param begin The beginning of the sequence.
510 /// @param end The end of the sequence.
511 void write(const std::int32_t* begin, const std::int32_t* end);
512
513 /// Writes a long sequence to the stream.
514 /// @param begin The beginning of the sequence.
515 /// @param end The end of the sequence.
516 void write(const std::int64_t* begin, const std::int64_t* end);
517
518 /// Writes a float sequence as a Slice float sequence.
519 /// @param begin The beginning of the sequence.
520 /// @param end The end of the sequence.
521 void write(const float* begin, const float* end);
522
523 /// Writes a double sequence as a Slice double sequence.
524 /// @param begin The beginning of the sequence.
525 /// @param end The end of the sequence.
526 void write(const double* begin, const double* end);
527
528 /// Writes a string to the stream.
529 /// @param v The string to marshal.
530 /// @param convert `true` to process @p v through the narrow string converter (if not null), `false` to write
531 /// @p v as-is.
532 void write(const std::string& v, bool convert = true) { write(std::string_view(v), convert); }
533
534 /// Writes a string view to the stream.
535 /// @param v The string view to marshal.
536 /// @param convert `true` to process @p v through the narrow string converter (if not null), `false` to write
537 /// @p v as-is.
538 void write(std::string_view v, bool convert = true)
539 {
540 auto sz = static_cast<std::int32_t>(v.size());
541 if (convert && sz > 0)
542 {
543 writeConverted(v.data(), static_cast<size_t>(sz));
544 }
545 else
546 {
547 writeSize(sz);
548 if (sz > 0)
549 {
550 Container::size_type position = b.size();
551 resize(position + static_cast<size_t>(sz));
552 memcpy(&b[position], v.data(), static_cast<size_t>(sz));
553 }
554 }
555 }
556
557 /// Writes a string to the stream.
558 /// @param vdata The string to marshal.
559 /// @param vsize The size of the string.
560 /// @param convert `true` to process @p vdata through the narrow string converter (if not null), `false` to
561 /// write @p vdata as-is.
562 void write(const char* vdata, size_t vsize, bool convert = true)
563 {
564 auto sz = static_cast<std::int32_t>(vsize);
565 if (convert && sz > 0)
566 {
567 writeConverted(vdata, vsize);
568 }
569 else
570 {
571 writeSize(sz);
572 if (sz > 0)
573 {
574 Container::size_type position = b.size();
575 resize(position + static_cast<size_t>(sz));
576 memcpy(&b[position], vdata, vsize);
577 }
578 }
579 }
580
581 /// Writes a string to the stream.
582 /// @param vdata The null-terminated string to marshal.
583 /// @param convert `true` to process @p vdata through the narrow string converter (if not null), `false` to
584 /// write @p vdata as-is.
585 void write(const char* vdata, bool convert = true) { write(vdata, strlen(vdata), convert); }
586
587 /// Writes a string sequence to the stream.
588 /// @param begin The beginning of the sequence.
589 /// @param end The end of the sequence.
590 /// @param convert `true` to process the strings through the narrow string converter (if not null), `false` to
591 /// write the strings as-is.
592 void write(const std::string* begin, const std::string* end, bool convert = true);
593
594 /// Writes a wide string sequence to the stream.
595 /// @param begin The beginning of the sequence.
596 /// @param end The end of the sequence.
597 void write(const std::wstring* begin, const std::wstring* end);
598
599 /// Writes a proxy to the stream.
600 /// @param v The proxy to be written.
601 void writeProxy(const ObjectPrx& v);
602
603 /// Writes a null proxy to the stream.
605
606 /// @cond INTERNAL
607
608 /// Writes a proxy to the stream.
609 /// @param v The proxy to marshal.
610 template<typename Prx, std::enable_if_t<std::is_base_of_v<ObjectPrx, Prx>, bool> = true>
611 void write(const std::optional<Prx>& v)
612 {
613 if (v)
614 {
615 writeProxy(v.value());
616 }
617 else
618 {
619 writeNullProxy();
620 }
621 }
622
623 /// Writes a value instance to the stream.
624 /// @param v The value to marshal.
625 template<typename T, std::enable_if_t<std::is_base_of_v<Value, T>>* = nullptr>
626 void write(const std::shared_ptr<T>& v)
627 {
628 initEncaps();
629 _currentEncaps->encoder->write(v);
630 }
631
632 /// @endcond
633
634 /// Writes an enumerator to the stream.
635 /// @param v The enumerator to marshal.
636 /// @param maxValue The maximum value of all enumerators in this enumeration.
637 void writeEnum(std::int32_t v, std::int32_t maxValue);
638
639 /// Writes a user exception to the stream.
640 /// @param v The exception to marshal.
642
643 /// Gets the current position of the stream.
644 /// @return The current position.
645 size_type pos() { return b.size(); }
646
647 /// Overwrites a 32-bit integer value at the specified position in the stream. This function does not change the
648 /// stream's current position.
649 /// @param v The value to marshal.
650 /// @param pos The buffer position for the value.
651 void rewrite(std::int32_t v, size_type pos) { write(v, b.begin() + pos); }
652
653 /// Indicates that marshaling is complete. This function must only be called once.
654 /// @param[out] v Filled with a copy of the encoded data.
655 void finished(std::vector<std::byte>& v);
656
657 /// Indicates that marshaling is complete. This function must only be called once.
658 /// @return A pair of pointers into the internal marshaling buffer. These pointers are valid for the lifetime
659 /// of the stream.
660 std::pair<const std::byte*, const std::byte*> finished();
661
662 /// @private
663 OutputStream(IceInternal::Instance*, EncodingVersion encoding);
664
665 private:
666 // Optionals
667 bool writeOptImpl(std::int32_t, OptionalFormat);
668
669 //
670 // String
671 //
672 void writeConverted(const char*, size_t);
673
674 StringConverterPtr _stringConverter;
675 WstringConverterPtr _wstringConverter;
676
677 //
678 // The public stream API needs to attach data to a stream.
679 //
680 void* _closure;
681
682 class Encaps;
683 enum SliceType
684 {
685 NoSlice,
686 ValueSlice,
687 ExceptionSlice
688 };
689
690 using ValueList = std::vector<ValuePtr>;
691
692 class ICE_API EncapsEncoder
693 {
694 public:
695 EncapsEncoder(const EncapsEncoder&) = delete;
696 virtual ~EncapsEncoder();
697
698 EncapsEncoder& operator=(const EncapsEncoder&) = delete;
699
700 virtual void write(const ValuePtr&) = 0;
701 virtual void write(const UserException&) = 0;
702
703 virtual void startInstance(SliceType, const SlicedDataPtr&) = 0;
704 virtual void endInstance() = 0;
705 virtual void startSlice(std::string_view, int, bool) = 0;
706 virtual void endSlice() = 0;
707
708 virtual bool writeOptional(std::int32_t, OptionalFormat) { return false; }
709
710 virtual void writePendingValues() {}
711
712 protected:
713 EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps) {}
714
715 std::int32_t registerTypeId(std::string_view);
716
717 OutputStream* _stream;
718 Encaps* _encaps;
719
720 using PtrToIndexMap = std::map<ValuePtr, std::int32_t>;
721 using TypeIdMap = std::map<std::string, std::int32_t, std::less<>>;
722
723 // Encapsulation attributes for value marshaling.
724 PtrToIndexMap _marshaledMap;
725
726 private:
727 // Encapsulation attributes for value marshaling.
728 TypeIdMap _typeIdMap;
729 std::int32_t _typeIdIndex{0};
730 };
731
732 class ICE_API EncapsEncoder10 : public EncapsEncoder
733 {
734 public:
735 EncapsEncoder10(OutputStream* stream, Encaps* encaps) : EncapsEncoder(stream, encaps) {}
736
737 void write(const ValuePtr&) override;
738 void write(const UserException&) override;
739
740 void startInstance(SliceType, const SlicedDataPtr&) override;
741 void endInstance() override;
742 void startSlice(std::string_view, int, bool) override;
743 void endSlice() override;
744
745 void writePendingValues() override;
746
747 private:
748 std::int32_t registerValue(const ValuePtr&);
749
750 // Instance attributes
751 SliceType _sliceType{NoSlice};
752
753 // Slice attributes
754 Container::size_type _writeSlice{0}; // Position of the slice data members
755
756 // Encapsulation attributes for value marshaling.
757 std::int32_t _valueIdIndex{0};
758 PtrToIndexMap _toBeMarshaledMap;
759 };
760
761 class ICE_API EncapsEncoder11 : public EncapsEncoder
762 {
763 public:
764 EncapsEncoder11(OutputStream* stream, Encaps* encaps)
765 : EncapsEncoder(stream, encaps),
766 _preAllocatedInstanceData(nullptr)
767 {
768 }
769
770 void write(const ValuePtr&) override;
771 void write(const UserException&) override;
772
773 void startInstance(SliceType, const SlicedDataPtr&) override;
774 void endInstance() override;
775 void startSlice(std::string_view, int, bool) override;
776 void endSlice() override;
777
778 bool writeOptional(std::int32_t, OptionalFormat) override;
779
780 private:
781 void writeSlicedData(const SlicedDataPtr&);
782 void writeInstance(const ValuePtr&);
783
784 struct InstanceData
785 {
786 InstanceData(InstanceData* p) : previous(p)
787 {
788 if (previous)
789 {
790 previous->next = this;
791 }
792 }
793
794 ~InstanceData()
795 {
796 if (next)
797 {
798 delete next;
799 }
800 }
801
802 // Instance attributes
803 SliceType sliceType{NoSlice};
804 bool firstSlice{false};
805
806 // Slice attributes
807 std::uint8_t sliceFlags{0};
808 Container::size_type writeSlice{0}; // Position of the slice data members
809 Container::size_type sliceFlagsPos{0}; // Position of the slice flags
810 PtrToIndexMap indirectionMap;
811 ValueList indirectionTable;
812
813 InstanceData* previous{nullptr};
814 InstanceData* next{nullptr};
815 };
816 InstanceData _preAllocatedInstanceData;
817 InstanceData* _current{nullptr};
818
819 std::int32_t _valueIdIndex{1}; // The ID of the next value to marshal
820 };
821
822 class Encaps
823 {
824 public:
825 Encaps() = default;
826 Encaps(const Encaps&) = delete;
827 ~Encaps() { delete encoder; }
828 Encaps& operator=(const Encaps&) = delete;
829
830 void reset()
831 {
832 // Inlined for performance reasons.
833 delete encoder;
834 encoder = nullptr;
835
836 previous = nullptr;
837 }
838
839 Container::size_type start;
840 EncodingVersion encoding;
841 FormatType format{FormatType::CompactFormat};
842
843 EncapsEncoder* encoder{nullptr};
844
845 Encaps* previous{nullptr};
846 };
847
848 //
849 // The encoding version to use when there's no encapsulation to
850 // read from or write to. This is for example used to read message
851 // headers or when the user is using the streaming API with no
852 // encapsulation.
853 //
854 EncodingVersion _encoding;
855
856 FormatType _format; // TODO: make it const
857
858 Encaps* _currentEncaps;
859
860 void initEncaps();
861
862 Encaps _preAllocatedEncaps;
863 };
864
865} // End namespace Ice
866
867#endif
The base class for all Ice proxies.
Definition Proxy.h:232
void startValue(const SlicedDataPtr &data)
Marks the start of a class instance.
void startEncapsulation()
Writes the start of an encapsulation using the default encoding version and class encoding format.
void write(const std::int16_t *begin, const std::int16_t *end)
Writes an int16_t sequence as a Slice short sequence.
void rewriteSize(std::int32_t v, Container::iterator dest)
Replaces a size value at the specified position in the stream.
void writePendingValues()
Encodes the state of class instances whose insertion was delayed during a previous call write.
void write(const T &v)
Writes a value to the stream.
OutputStream(EncodingVersion encoding=currentEncoding, FormatType format=FormatType::CompactFormat, StringConverterPtr stringConverter=nullptr, WstringConverterPtr wstringConverter=nullptr)
Constructs an OutputStream.
void write(const std::uint8_t *start, const std::uint8_t *end)
Writes a byte sequence to the stream.
void writeException(const UserException &v)
Writes a user exception to the stream.
void writeBlob(const std::vector< std::byte > &v)
Copies the specified blob of bytes to the stream without modification.
void write(std::int32_t v, Container::iterator dest)
Overwrites a 32-bit integer value at the given position in the stream.
void finished(std::vector< std::byte > &v)
Indicates that marshaling is complete.
void writeAll(const T &v)
Writes a value (single element list) to the stream.
void writeNullProxy()
Writes a null proxy to the stream.
void startException()
Marks the start of an exception instance.
OutputStream(const CommunicatorPtr &communicator, EncodingVersion encoding)
Constructs an OutputStream using the format, string converter and wstring converter provided by the c...
void write(const std::int64_t *begin, const std::int64_t *end)
Writes a long sequence to the stream.
void writeAll(std::initializer_list< std::int32_t > tags, const std::optional< T > &v)
Writes an optional value (single element list) to the stream.
size_type startSize()
Writes a placeholder value for the size and returns the starting position of the size value; after wr...
size_type pos()
Gets the current position of the stream.
void writeAll(const T &v, const Te &... ve)
Writes a list of values to the stream.
void resize(Container::size_type sz)
Resizes the stream to a new size.
bool writeOptional(std::int32_t tag, OptionalFormat format)
Writes the tag and format of an optional value.
void startEncapsulation(const EncodingVersion &encoding, std::optional< FormatType > format)
Writes the start of an encapsulation using the specified encoding version and class encoding format.
void write(const float *begin, const float *end)
Writes a float sequence as a Slice float sequence.
void writeEncapsulation(const std::byte *v, std::int32_t sz)
Copies the marshaled form of an encapsulation to the buffer.
void startSlice(std::string_view typeId, int compactId, bool last)
Writes the start of a class instance or exception slice.
const EncodingVersion & getEncoding() const
Gets the current encoding version.
void write(const bool *begin, const bool *end)
Writes a boolean sequence to the stream.
void write(std::int32_t tag, const std::optional< T > &v)
Writes an optional value to the stream.
void write(const std::wstring *begin, const std::wstring *end)
Writes a wide string sequence to the stream.
void write(const double *begin, const double *end)
Writes a double sequence as a Slice double sequence.
void endEncapsulation()
Ends the current encapsulation.
void endValue()
Marks the end of a class instance.
void write(std::string_view v, bool convert=true)
Writes a string view to the stream.
void endSize(size_type position)
Updates the size value at the given position.
void writeEnum(std::int32_t v, std::int32_t maxValue)
Writes an enumerator to the stream.
void swap(OutputStream &other) noexcept
Swaps the contents of one stream with another.
void endException()
Marks the end of an exception instance.
writeAll(std::tuple< Te... > tuple)
Writes a tuple to the stream.
void write(const std::int32_t *begin, const std::int32_t *end)
Writes an int sequence to the stream.
void writeProxy(const ObjectPrx &v)
Writes a proxy to the stream.
void write(const std::string *begin, const std::string *end, bool convert=true)
Writes a string sequence to the stream.
void writeAll(std::initializer_list< std::int32_t > tags, const std::optional< T > &v, const std::optional< Te > &... ve)
Writes a list of optional values to the stream.
OutputStream(OutputStream &&other) noexcept
Move constructor.
void writeEmptyEncapsulation(const EncodingVersion &encoding)
Writes an empty encapsulation using the specified encoding version.
OutputStream(std::pair< const std::byte *, const std::byte * > bytes, EncodingVersion encoding=currentEncoding, FormatType format=FormatType::CompactFormat, StringConverterPtr stringConverter=nullptr, WstringConverterPtr wstringConverter=nullptr)
Constructs an OutputStream over an application-supplied buffer.
void write(const std::string &v, bool convert=true)
Writes a string to the stream.
void endSlice()
Marks the end of a class instance or exception slice.
void writeSize(std::int32_t v)
Writes a size value.
std::size_t size_type
The size type for this byte buffer.
std::pair< const std::byte *, const std::byte * > finished()
Indicates that marshaling is complete.
void write(const char *vdata, size_t vsize, bool convert=true)
Writes a string to the stream.
void rewrite(std::int32_t v, size_type pos)
Overwrites a 32-bit integer value at the specified position in the stream.
void write(const char *vdata, bool convert=true)
Writes a string to the stream.
OutputStream(const CommunicatorPtr &communicator)
Constructs an OutputStream using the encoding, format, string converter and wstring converter provide...
void clear()
Releases any data retained by encapsulations.
void writeBlob(const std::byte *v, Container::size_type sz)
Copies the specified blob of bytes to the stream without modification.
void write(const std::byte *start, const std::byte *end)
Writes a byte sequence to the stream.
OutputStream & operator=(OutputStream &&other) noexcept
Move assignment operator.
Abstract base class for all Ice exceptions defined in Slice.
std::shared_ptr< Communicator > CommunicatorPtr
A shared pointer to a Communicator.
std::shared_ptr< StringConverter > StringConverterPtr
A shared pointer to a StringConverter.
OptionalFormat
The optional format, used for marshaling optional fields and arguments.
constexpr EncodingVersion currentEncoding
Identifies the latest encoding version.
std::shared_ptr< Value > ValuePtr
A shared pointer to a Value.
Definition ValueF.h:13
FormatType
Specifies the format for marshaling classes and exceptions with the Slice 1.1 encoding.
Definition Format.h:12
@ CompactFormat
Favors compactness, but does not support slicing-off unknown slices during unmarshaling.
Definition Format.h:14
std::shared_ptr< SlicedData > SlicedDataPtr
A shared pointer to a SlicedData.
Definition SlicedDataF.h:22
std::shared_ptr< WstringConverter > WstringConverterPtr
A shared pointer to a WstringConverter.
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...