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();
179 return _currentEncaps ? _currentEncaps->encoding : _encoding;
186 void startSlice(std::string_view typeId,
int compactId,
bool last)
188 assert(_currentEncaps && _currentEncaps->encoder);
189 _currentEncaps->encoder->startSlice(typeId, compactId, last);
195 assert(_currentEncaps && _currentEncaps->encoder);
196 _currentEncaps->encoder->endSlice();
211 write(std::uint8_t(255));
216 write(
static_cast<std::uint8_t
>(v));
229 *dest++ = std::byte{255};
234 *dest =
static_cast<std::byte
>(v);
244 write(std::int32_t(0));
259 void writeBlob(
const std::byte* v, Container::size_type sz)
263 Container::size_type position = b.size();
265 memcpy(&b[position], &v[0], sz);
279 template<
typename T>
void write(std::int32_t tag,
const std::optional<T>& v);
286 template<
size_t I = 0,
typename... Te >>
writeAll(std::tuple<Te...> tuple);
299 template<
typename T,
typename... Te>
void writeAll(
const T& v,
const Te&... ve)
309 template<
typename T>
void writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v)
311 write(*(tags.begin() + tags.size() - 1), v);
320 template<
typename T,
typename... Te>
322 writeAll(std::initializer_list<std::int32_t> tags,
const std::optional<T>& v,
const std::optional<Te>&... ve)
324 size_t index = tags.size() -
sizeof...(ve) - 1;
325 write(*(tags.begin() + index), v);
336 assert(_currentEncaps);
337 if (_currentEncaps->encoder)
339 return _currentEncaps->encoder->writeOptional(tag, format);
343 return writeOptImpl(tag, format);
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)
366 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::
369 StreamOptionalHelper<T, StreamableTraits<T>::helper, StreamableTraits<T>::fixedLength>::write(
this, *v);
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)
385 if (writeOptional(tag, OptionalFormat::FSize))
387 size_type pos = startSize();
396 template<
typename T>
void write(
const std::vector<T>& v)
404 write(&v[0], &v[0] + v.size());
412 template<
typename T>
void write(
const T* begin,
const T* end)
414 writeSize(
static_cast<std::int32_t
>(end - begin));
415 for (
const T* p = begin; p != end; ++p)
422 template<
size_t I = 0,
typename... Te> std::enable_if_t<I ==
sizeof...(Te),
void> writeAll(std::tuple<Te...>)
431 template<
size_t I = 0,
typename... Te>
432 std::enable_if_t < I<
sizeof...(Te),
void> writeAll(std::tuple<Te...> tuple)
434 write(std::get<I>(tuple));
435 writeAll<I + 1, Te...>(tuple);
440 void write(std::byte v) { b.push_back(v); }
444 void write(std::uint8_t v) { b.push_back(std::byte{v}); }
448 void write(
bool v) { b.push_back(
static_cast<std::byte
>(v)); }
452 void write(
const std::vector<bool>& v);
456 void write(std::int16_t v);
460 void write(std::int32_t v)
462 Container::size_type position = b.size();
463 resize(position +
sizeof(std::int32_t));
464 write(v, &b[position]);
469 void write(std::int64_t v);
477 void write(
double v);
481 void write(
const std::wstring& v) { write(std::wstring_view(v)); }
485 void write(std::wstring_view v);
493 void write(std::int32_t v, Container::iterator dest);
498 void write(
const std::byte* start,
const std::byte* end);
503 void write(
const std::uint8_t* start,
const std::uint8_t* end);
508 void write(
const bool* begin,
const bool* end);
513 void write(
const std::int16_t* begin,
const std::int16_t* end);
518 void write(
const std::int32_t* begin,
const std::int32_t* end);
523 void write(
const std::int64_t* begin,
const std::int64_t* end);
528 void write(
const float* begin,
const float* end);
533 void write(
const double* begin,
const double* end);
539 void write(
const std::string& v,
bool convert =
true) {
write(std::string_view(v), convert); }
545 void write(std::string_view v,
bool convert =
true)
547 auto sz =
static_cast<std::int32_t
>(v.size());
548 if (convert && sz > 0)
550 writeConverted(v.data(),
static_cast<size_t>(sz));
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));
569 void write(
const char* vdata,
size_t vsize,
bool convert =
true)
571 auto sz =
static_cast<std::int32_t
>(vsize);
572 if (convert && sz > 0)
574 writeConverted(vdata, vsize);
581 Container::size_type position = b.size();
582 resize(position +
static_cast<size_t>(sz));
583 memcpy(&b[position], vdata, vsize);
592 void write(
const char* vdata,
bool convert =
true) {
write(vdata, strlen(vdata), convert); }
599 void write(
const std::string* begin,
const std::string* end,
bool convert =
true);
604 void write(
const std::wstring* begin,
const std::wstring* end);
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)
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)
636 _currentEncaps->encoder->write(v);
667 std::pair<const std::byte*, const std::byte*>
finished();
679 void writeConverted(
const char*,
size_t);
687 write(std::uint8_t(0));
694 void endOneByteSize(size_type position)
696 auto size =
static_cast<std::int32_t
>(b.size() - position - 1);
697 assert(size >= 0 && size <= 254);
698 rewriteSize(size, b.begin() + position);
701 StringConverterPtr _stringConverter;
702 WstringConverterPtr _wstringConverter;
717 using ValueList = std::vector<ValuePtr>;
719 class ICE_API EncapsEncoder
722 EncapsEncoder(
const EncapsEncoder&) =
delete;
723 virtual ~EncapsEncoder();
725 EncapsEncoder& operator=(
const EncapsEncoder&) =
delete;
727 virtual void write(
const ValuePtr&) = 0;
728 virtual void write(
const UserException&) = 0;
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;
735 virtual bool writeOptional(std::int32_t, OptionalFormat) {
return false; }
737 virtual void writePendingValues() {}
740 EncapsEncoder(OutputStream* stream, Encaps* encaps) : _stream(stream), _encaps(encaps) {}
742 std::int32_t registerTypeId(std::string_view);
744 OutputStream* _stream;
747 using PtrToIndexMap = std::map<ValuePtr, std::int32_t>;
748 using TypeIdMap = std::map<std::string, std::int32_t, std::less<>>;
751 PtrToIndexMap _marshaledMap;
755 TypeIdMap _typeIdMap;
756 std::int32_t _typeIdIndex{0};
759 class ICE_API EncapsEncoder10 :
public EncapsEncoder
762 EncapsEncoder10(OutputStream* stream, Encaps* encaps) : EncapsEncoder(stream, encaps) {}
764 void write(
const ValuePtr&)
override;
765 void write(
const UserException&)
override;
767 void startInstance(SliceType,
const SlicedDataPtr&)
override;
768 void endInstance()
override;
769 void startSlice(std::string_view,
int,
bool)
override;
770 void endSlice()
override;
772 void writePendingValues()
override;
775 std::int32_t registerValue(
const ValuePtr&);
778 SliceType _sliceType{NoSlice};
781 Container::size_type _writeSlice{0};
784 std::int32_t _valueIdIndex{0};
785 PtrToIndexMap _toBeMarshaledMap;
788 class ICE_API EncapsEncoder11 :
public EncapsEncoder
791 EncapsEncoder11(OutputStream* stream, Encaps* encaps)
792 : EncapsEncoder(stream, encaps),
793 _preAllocatedInstanceData(nullptr)
797 void write(
const ValuePtr&)
override;
798 void write(
const UserException&)
override;
800 void startInstance(SliceType,
const SlicedDataPtr&)
override;
801 void endInstance()
override;
802 void startSlice(std::string_view,
int,
bool)
override;
803 void endSlice()
override;
805 bool writeOptional(std::int32_t, OptionalFormat)
override;
808 void writeSlicedData(
const SlicedDataPtr&);
809 void writeInstance(
const ValuePtr&);
813 InstanceData(InstanceData* p) : previous(p)
817 previous->next =
this;
830 SliceType sliceType{NoSlice};
831 bool firstSlice{
false};
834 std::uint8_t sliceFlags{0};
835 Container::size_type writeSlice{0};
836 Container::size_type sliceFlagsPos{0};
837 PtrToIndexMap indirectionMap;
838 ValueList indirectionTable;
840 InstanceData* previous{
nullptr};
841 InstanceData* next{
nullptr};
843 InstanceData _preAllocatedInstanceData;
844 InstanceData* _current{
nullptr};
846 std::int32_t _valueIdIndex{1};
853 Encaps(
const Encaps&) =
delete;
854 ~Encaps() {
delete encoder; }
855 Encaps& operator=(
const Encaps&) =
delete;
866 Container::size_type start;
867 EncodingVersion encoding;
870 EncapsEncoder* encoder{
nullptr};
872 Encaps* previous{
nullptr};
881 EncodingVersion _encoding;
885 Encaps* _currentEncaps;
889 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.
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...