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"
72 std::pair<const std::byte*, const std::byte*> bytes,
91 if (_currentEncaps != &_preAllocatedEncaps)
108 [[nodiscard]]
void* getClosure()
const;
113 void* setClosure(
void* p);
115 void resetEncapsulation();
120 void resize(Container::size_type sz) { b.resize(sz); }
127 assert(_currentEncaps && _currentEncaps->encoder);
128 _currentEncaps->encoder->startInstance(ValueSlice, data);
134 assert(_currentEncaps && _currentEncaps->encoder);
135 _currentEncaps->encoder->endInstance();
141 assert(_currentEncaps && _currentEncaps->encoder);
142 _currentEncaps->encoder->startInstance(ExceptionSlice,
nullptr);
148 assert(_currentEncaps && _currentEncaps->encoder);
149 _currentEncaps->encoder->endInstance();
177 return _currentEncaps ? _currentEncaps->encoding : _encoding;
184 void startSlice(std::string_view typeId,
int compactId,
bool last)
186 assert(_currentEncaps && _currentEncaps->encoder);
187 _currentEncaps->encoder->startSlice(typeId, compactId, last);
193 assert(_currentEncaps && _currentEncaps->encoder);
194 _currentEncaps->encoder->endSlice();
209 write(std::uint8_t(255));
214 write(
static_cast<std::uint8_t
>(v));
227 *dest++ = std::byte{255};
232 *dest =
static_cast<std::byte
>(v);
242 write(std::int32_t(0));
257 void writeBlob(
const std::byte* v, Container::size_type sz)
261 Container::size_type position = b.size();
263 memcpy(&b[position], &v[0], sz);
277 template<
typename T>
void write(std::int32_t tag,
const std::optional<T>& v);
284 template<
size_t I = 0,
typename... Te >>
writeAll(std::tuple<Te...> tuple);
297 template<
typename T,
typename... Te>
void writeAll(
const T& v,
const Te&... ve)
307 template<
typename T>
void writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v)
309 write(*(tags.begin() + tags.size() - 1), v);
318 template<
typename T,
typename... Te>
320 writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v,
const std::optional<Te>&... ve)
322 size_t index = tags.size() -
sizeof...(ve) - 1;
323 write(*(tags.begin() + index), v);
334 assert(_currentEncaps);
335 if (_currentEncaps->encoder)
337 return _currentEncaps->encoder->writeOptional(tag, format);
341 return writeOptImpl(tag, format);
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)
364 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::
367 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::write(
this, *v);
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)
383 if (writeOptional(tag, OptionalFormat::FSize))
385 size_type pos = startSize();
394 template<
typename T>
void write(
const std::vector<T>& v)
402 write(&v[0], &v[0] + v.size());
410 template<
typename T>
void write(
const T* begin,
const T* end)
412 writeSize(
static_cast<std::int32_t
>(end - begin));
413 for (
const T* p = begin; p != end; ++p)
420 template<
size_t I = 0,
typename... Te> std::enable_if_t<I ==
sizeof...(Te),
void> writeAll(std::tuple<Te...>)
429 template<
size_t I = 0,
typename... Te>
430 std::enable_if_t < I<
sizeof...(Te),
void> writeAll(std::tuple<Te...> tuple)
432 write(std::get<I>(tuple));
433 writeAll<I + 1, Te...>(tuple);
438 void write(std::byte v) { b.push_back(v); }
442 void write(std::uint8_t v) { b.push_back(std::byte{v}); }
446 void write(
bool v) { b.push_back(
static_cast<std::byte
>(v)); }
450 void write(
const std::vector<bool>& v);
454 void write(std::int16_t v);
458 void write(std::int32_t v)
460 Container::size_type position = b.size();
461 resize(position +
sizeof(std::int32_t));
462 write(v, &b[position]);
467 void write(std::int64_t v);
475 void write(
double v);
479 void write(
const std::wstring& v) { write(std::wstring_view(v)); }
483 void write(std::wstring_view v);
491 void write(std::int32_t v, Container::iterator dest);
496 void write(
const std::byte* start,
const std::byte* end);
501 void write(
const std::uint8_t* start,
const std::uint8_t* end);
506 void write(
const bool* begin,
const bool* end);
511 void write(
const std::int16_t* begin,
const std::int16_t* end);
516 void write(
const std::int32_t* begin,
const std::int32_t* end);
521 void write(
const std::int64_t* begin,
const std::int64_t* end);
526 void write(
const float* begin,
const float* end);
531 void write(
const double* begin,
const double* end);
537 void write(
const std::string& v,
bool convert =
true) {
write(std::string_view(v), convert); }
543 void write(std::string_view v,
bool convert =
true)
545 auto sz =
static_cast<std::int32_t
>(v.size());
546 if (convert && sz > 0)
548 writeConverted(v.data(),
static_cast<size_t>(sz));
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));
567 void write(
const char* vdata,
size_t vsize,
bool convert =
true)
569 auto sz =
static_cast<std::int32_t
>(vsize);
570 if (convert && sz > 0)
572 writeConverted(vdata, vsize);
579 Container::size_type position = b.size();
580 resize(position +
static_cast<size_t>(sz));
581 memcpy(&b[position], vdata, vsize);
590 void write(
const char* vdata,
bool convert =
true) {
write(vdata, strlen(vdata), convert); }
597 void write(
const std::string* begin,
const std::string* end,
bool convert =
true);
602 void write(
const std::wstring* begin,
const std::wstring* end);
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)
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)
634 _currentEncaps->encoder->write(v);
665 std::pair<const std::byte*, const std::byte*>
finished();
677 void writeConverted(
const char*,
size_t);
695 using ValueList = std::vector<ValuePtr>;
697 class ICE_API EncapsEncoder
700 EncapsEncoder(
const EncapsEncoder&) =
delete;
701 virtual ~EncapsEncoder();
703 EncapsEncoder& operator=(
const EncapsEncoder&) =
delete;
705 virtual void write(
const ValuePtr&) = 0;
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;
713 virtual bool writeOptional(std::int32_t,
OptionalFormat) {
return false; }
715 virtual void writePendingValues() {}
718 EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps) {}
720 std::int32_t registerTypeId(std::string_view);
722 OutputStream* _stream;
725 using PtrToIndexMap = std::map<ValuePtr, std::int32_t>;
726 using TypeIdMap = std::map<std::string, std::int32_t, std::less<>>;
729 PtrToIndexMap _marshaledMap;
733 TypeIdMap _typeIdMap;
734 std::int32_t _typeIdIndex{0};
737 class ICE_API EncapsEncoder10 :
public EncapsEncoder
740 EncapsEncoder10(OutputStream* stream, Encaps* encaps) : EncapsEncoder(stream, encaps) {}
742 void write(
const ValuePtr&)
override;
743 void write(
const UserException&)
override;
745 void startInstance(SliceType,
const SlicedDataPtr&)
override;
746 void endInstance()
override;
747 void startSlice(std::string_view,
int,
bool)
override;
748 void endSlice()
override;
750 void writePendingValues()
override;
753 std::int32_t registerValue(
const ValuePtr&);
756 SliceType _sliceType{NoSlice};
759 Container::size_type _writeSlice{0};
762 std::int32_t _valueIdIndex{0};
763 PtrToIndexMap _toBeMarshaledMap;
766 class ICE_API EncapsEncoder11 :
public EncapsEncoder
769 EncapsEncoder11(OutputStream* stream, Encaps* encaps)
770 : EncapsEncoder(stream, encaps),
771 _preAllocatedInstanceData(nullptr)
775 void write(
const ValuePtr&)
override;
776 void write(
const UserException&)
override;
778 void startInstance(SliceType,
const SlicedDataPtr&)
override;
779 void endInstance()
override;
780 void startSlice(std::string_view,
int,
bool)
override;
781 void endSlice()
override;
783 bool writeOptional(std::int32_t, OptionalFormat)
override;
786 void writeSlicedData(
const SlicedDataPtr&);
787 void writeInstance(
const ValuePtr&);
791 InstanceData(InstanceData* p) : previous(p)
795 previous->next =
this;
808 SliceType sliceType{NoSlice};
809 bool firstSlice{
false};
812 std::uint8_t sliceFlags{0};
813 Container::size_type writeSlice{0};
814 Container::size_type sliceFlagsPos{0};
815 PtrToIndexMap indirectionMap;
816 ValueList indirectionTable;
818 InstanceData* previous{
nullptr};
819 InstanceData* next{
nullptr};
821 InstanceData _preAllocatedInstanceData;
822 InstanceData* _current{
nullptr};
824 std::int32_t _valueIdIndex{1};
831 Encaps(
const Encaps&) =
delete;
832 ~Encaps() {
delete encoder; }
833 Encaps& operator=(
const Encaps&) =
delete;
844 Container::size_type start;
845 EncodingVersion encoding;
848 EncapsEncoder* encoder{
nullptr};
850 Encaps* previous{
nullptr};
859 EncodingVersion _encoding;
863 Encaps* _currentEncaps;
867 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 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.
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...