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