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