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