3#ifndef ICE_OUTPUT_STREAM_H
4#define ICE_OUTPUT_STREAM_H
7#include "CommunicatorF.h"
9#include "Ice/StringConverter.h"
10#include "Ice/Version.h"
12#include "SlicedDataF.h"
13#include "StreamableTraits.h"
74 std::pair<const std::byte*, const std::byte*> bytes,
93 if (_currentEncaps != &_preAllocatedEncaps)
110 [[nodiscard]]
void* getClosure()
const;
115 void* setClosure(
void* p);
117 void resetEncapsulation();
122 void resize(Container::size_type sz) { b.resize(sz); }
129 assert(_currentEncaps && _currentEncaps->encoder);
130 _currentEncaps->encoder->startInstance(ValueSlice, data);
136 assert(_currentEncaps && _currentEncaps->encoder);
137 _currentEncaps->encoder->endInstance();
143 assert(_currentEncaps && _currentEncaps->encoder);
144 _currentEncaps->encoder->startInstance(ExceptionSlice,
nullptr);
150 assert(_currentEncaps && _currentEncaps->encoder);
151 _currentEncaps->encoder->endInstance();
180 return _currentEncaps ? _currentEncaps->encoding : _encoding;
187 void startSlice(std::string_view typeId,
int compactId,
bool last)
189 assert(_currentEncaps && _currentEncaps->encoder);
190 _currentEncaps->encoder->startSlice(typeId, compactId, last);
196 assert(_currentEncaps && _currentEncaps->encoder);
197 _currentEncaps->encoder->endSlice();
212 write(std::uint8_t(255));
217 write(
static_cast<std::uint8_t
>(v));
230 *dest++ = std::byte{255};
235 *dest =
static_cast<std::byte
>(v);
245 write(std::int32_t(0));
260 void writeBlob(
const std::byte* v, Container::size_type sz)
264 Container::size_type position = b.size();
266 memcpy(&b[position], &v[0], sz);
280 template<
typename T>
void write(std::int32_t tag,
const std::optional<T>& v);
287 template<
size_t I = 0,
typename... Te>
void writeAll(std::tuple<Te...> tuple);
300 template<
typename T,
typename... Te>
void writeAll(
const T& v,
const Te&... ve)
310 template<
typename T>
void writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v)
312 write(*(tags.begin() + tags.size() - 1), v);
321 template<
typename T,
typename... Te>
323 writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v,
const std::optional<Te>&... ve)
325 size_t index = tags.size() -
sizeof...(ve) - 1;
326 write(*(tags.begin() + index), v);
337 assert(_currentEncaps);
338 if (_currentEncaps->encoder)
340 return _currentEncaps->encoder->writeOptional(tag, format);
344 return writeOptImpl(tag, format);
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)
367 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::
370 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::write(
this, *v);
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)
386 if (writeOptional(tag, OptionalFormat::FSize))
388 size_type pos = startSize();
397 template<
typename T>
void write(
const std::vector<T>& v)
405 write(&v[0], &v[0] + v.size());
413 template<
typename T>
void write(
const T* begin,
const T* end)
415 writeSize(
static_cast<std::int32_t
>(end - begin));
416 for (
const T* p = begin; p != end; ++p)
423 template<
size_t I = 0,
typename... Te> std::enable_if_t<I ==
sizeof...(Te),
void> writeAll(std::tuple<Te...>)
432 template<
size_t I = 0,
typename... Te>
433 std::enable_if_t < I<
sizeof...(Te),
void> writeAll(std::tuple<Te...> tuple)
435 write(std::get<I>(tuple));
436 writeAll<I + 1, Te...>(tuple);
441 void write(std::byte v) { b.push_back(v); }
445 void write(std::uint8_t v) { b.push_back(std::byte{v}); }
449 void write(
bool v) { b.push_back(
static_cast<std::byte
>(v)); }
453 void write(
const std::vector<bool>& v);
457 void write(std::int16_t v);
461 void write(std::int32_t v)
463 Container::size_type position = b.size();
464 resize(position +
sizeof(std::int32_t));
465 write(v, &b[position]);
470 void write(std::int64_t v);
478 void write(
double v);
482 void write(
const std::wstring& v) { write(std::wstring_view(v)); }
486 void write(std::wstring_view v);
494 void write(std::int32_t v, Container::iterator dest);
499 void write(
const std::byte* start,
const std::byte* end);
504 void write(
const std::uint8_t* start,
const std::uint8_t* end);
509 void write(
const bool* begin,
const bool* end);
514 void write(
const std::int16_t* begin,
const std::int16_t* end);
519 void write(
const std::int32_t* begin,
const std::int32_t* end);
524 void write(
const std::int64_t* begin,
const std::int64_t* end);
529 void write(
const float* begin,
const float* end);
534 void write(
const double* begin,
const double* end);
540 void write(
const std::string& v,
bool convert =
true) {
write(std::string_view(v), convert); }
546 void write(std::string_view v,
bool convert =
true)
548 auto sz =
static_cast<std::int32_t
>(v.size());
549 if (convert && sz > 0)
551 writeConverted(v.data(),
static_cast<size_t>(sz));
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));
570 void write(
const char* vdata,
size_t vsize,
bool convert =
true)
572 auto sz =
static_cast<std::int32_t
>(vsize);
573 if (convert && sz > 0)
575 writeConverted(vdata, vsize);
582 Container::size_type position = b.size();
583 resize(position +
static_cast<size_t>(sz));
584 memcpy(&b[position], vdata, vsize);
593 void write(
const char* vdata,
bool convert =
true) {
write(vdata, strlen(vdata), convert); }
600 void write(
const std::string* begin,
const std::string* end,
bool convert =
true);
605 void write(
const std::wstring* begin,
const std::wstring* end);
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)
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)
637 _currentEncaps->encoder->write(v);
668 std::pair<const std::byte*, const std::byte*>
finished();
680 void writeConverted(
const char*,
size_t);
688 write(std::uint8_t(0));
695 void endOneByteSize(size_type position)
697 auto size =
static_cast<std::int32_t
>(b.size() - position - 1);
698 assert(size >= 0 && size <= 254);
699 rewriteSize(size, b.begin() + position);
702 StringConverterPtr _stringConverter;
703 WstringConverterPtr _wstringConverter;
718 using ValueList = std::vector<ValuePtr>;
720 class ICE_API EncapsEncoder
723 EncapsEncoder(
const EncapsEncoder&) =
delete;
724 virtual ~EncapsEncoder();
726 EncapsEncoder& operator=(
const EncapsEncoder&) =
delete;
728 virtual void write(
const ValuePtr&) = 0;
729 virtual void write(
const UserException&) = 0;
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;
736 virtual bool writeOptional(std::int32_t, OptionalFormat) {
return false; }
738 virtual void writePendingValues() {}
741 EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps) {}
743 std::int32_t registerTypeId(std::string_view);
745 OutputStream* _stream;
748 using PtrToIndexMap = std::map<ValuePtr, std::int32_t>;
749 using TypeIdMap = std::map<std::string, std::int32_t, std::less<>>;
752 PtrToIndexMap _marshaledMap;
756 TypeIdMap _typeIdMap;
757 std::int32_t _typeIdIndex{0};
760 class ICE_API EncapsEncoder10 :
public EncapsEncoder
763 EncapsEncoder10(OutputStream* stream, Encaps* encaps) : EncapsEncoder(stream, encaps) {}
765 void write(
const ValuePtr&)
override;
766 void write(
const UserException&)
override;
768 void startInstance(SliceType,
const SlicedDataPtr&)
override;
769 void endInstance()
override;
770 void startSlice(std::string_view,
int,
bool)
override;
771 void endSlice()
override;
773 void writePendingValues()
override;
776 std::int32_t registerValue(
const ValuePtr&);
779 SliceType _sliceType{NoSlice};
782 Container::size_type _writeSlice{0};
785 std::int32_t _valueIdIndex{0};
786 PtrToIndexMap _toBeMarshaledMap;
789 class ICE_API EncapsEncoder11 :
public EncapsEncoder
792 EncapsEncoder11(OutputStream* stream, Encaps* encaps)
793 : EncapsEncoder(stream, encaps),
794 _preAllocatedInstanceData(nullptr)
798 void write(
const ValuePtr&)
override;
799 void write(
const UserException&)
override;
801 void startInstance(SliceType,
const SlicedDataPtr&)
override;
802 void endInstance()
override;
803 void startSlice(std::string_view,
int,
bool)
override;
804 void endSlice()
override;
806 bool writeOptional(std::int32_t, OptionalFormat)
override;
809 void writeSlicedData(
const SlicedDataPtr&);
810 void writeInstance(
const ValuePtr&);
814 InstanceData(InstanceData* p) : previous(p)
818 previous->next =
this;
831 SliceType sliceType{NoSlice};
832 bool firstSlice{
false};
835 std::uint8_t sliceFlags{0};
836 Container::size_type writeSlice{0};
837 Container::size_type sliceFlagsPos{0};
838 PtrToIndexMap indirectionMap;
839 ValueList indirectionTable;
841 InstanceData* previous{
nullptr};
842 InstanceData* next{
nullptr};
844 InstanceData _preAllocatedInstanceData;
845 InstanceData* _current{
nullptr};
847 std::int32_t _valueIdIndex{1};
854 Encaps(
const Encaps&) =
delete;
855 ~Encaps() {
delete encoder; }
856 Encaps& operator=(
const Encaps&) =
delete;
867 Container::size_type start;
868 EncodingVersion encoding;
871 EncapsEncoder* encoder{
nullptr};
873 Encaps* previous{
nullptr};
882 EncodingVersion _encoding;
886 Encaps* _currentEncaps;
890 Encaps _preAllocatedEncaps;
The base class for all Ice proxies.
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.
@ CompactFormat
Favors compactness, but does not support slicing-off unknown slices during unmarshaling.
std::shared_ptr< SlicedData > SlicedDataPtr
A shared pointer to a SlicedData.
std::shared_ptr< WstringConverter > WstringConverterPtr
A shared pointer to a WstringConverter.
Represents a version of the Slice encoding.
A helper template class for writing (marshaling) and reading (unmarshaling) values to and from a stre...