1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #ifndef COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_
5 #define COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_
7 #include "DBusMessage.h"
10 #include <CommonAPI/OutputStream.h>
22 * Used to mark the position of a pointer within an array of bytes.
24 typedef uint32_t position_t;
28 * @class DBusOutputMessageStream
30 * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing
31 * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed
32 * to match the actual data that is inserted via the #DBusOutputMessageStream.
34 class DBusOutputStream: public OutputStream {
36 virtual OutputStream& writeValue(const bool& boolValue) { return writeBasicTypeValue<uint32_t>(boolValue); }
38 virtual OutputStream& writeValue(const int8_t& int8Value) { return writeBasicTypeValue(int8Value); }
39 virtual OutputStream& writeValue(const int16_t& int16Value) { return writeBasicTypeValue(int16Value); }
40 virtual OutputStream& writeValue(const int32_t& int32Value) { return writeBasicTypeValue(int32Value); }
41 virtual OutputStream& writeValue(const int64_t& int64Value) { return writeBasicTypeValue(int64Value); }
43 virtual OutputStream& writeValue(const uint8_t& uint8Value) { return writeBasicTypeValue(uint8Value); }
44 virtual OutputStream& writeValue(const uint16_t& uint16Value) { return writeBasicTypeValue(uint16Value); }
45 virtual OutputStream& writeValue(const uint32_t& uint32Value) { return writeBasicTypeValue(uint32Value); }
46 virtual OutputStream& writeValue(const uint64_t& uint64Value) { return writeBasicTypeValue(uint64Value); }
48 virtual OutputStream& writeValue(const float& floatValue) { return writeBasicTypeValue((double) floatValue); }
49 virtual OutputStream& writeValue(const double& doubleValue) { return writeBasicTypeValue(doubleValue); }
51 virtual OutputStream& writeValue(const std::string& stringValue) { return writeString(stringValue.c_str(), stringValue.length()); }
53 inline virtual OutputStream& writeValue(const ByteBuffer& byteBufferValue);
55 virtual OutputStream& writeEnumValue(const int8_t& int8BackingTypeValue) { return writeValue(int8BackingTypeValue); }
56 virtual OutputStream& writeEnumValue(const int16_t& int16BackingTypeValue) { return writeValue(int16BackingTypeValue); }
57 virtual OutputStream& writeEnumValue(const int32_t& int32BackingTypeValue) { return writeValue(int32BackingTypeValue); }
58 virtual OutputStream& writeEnumValue(const int64_t& int64BackingTypeValue) { return writeValue(int64BackingTypeValue); }
59 virtual OutputStream& writeEnumValue(const uint8_t& uint8BackingTypeValue) { return writeValue(uint8BackingTypeValue); }
60 virtual OutputStream& writeEnumValue(const uint16_t& uint16BackingTypeValue) { return writeValue(uint16BackingTypeValue); }
61 virtual OutputStream& writeEnumValue(const uint32_t& uint32BackingTypeValue) { return writeValue(uint32BackingTypeValue); }
62 virtual OutputStream& writeEnumValue(const uint64_t& uint64BackingTypeValue) { return writeValue(uint64BackingTypeValue); }
64 virtual void beginWriteBoolVector(uint32_t sizeOfVector) {
65 beginWriteGenericVector();
66 rememberCurrentStreamPosition();
68 virtual void beginWriteInt8Vector(uint32_t sizeOfVector) {
69 beginWriteGenericVector();
70 rememberCurrentStreamPosition();
72 virtual void beginWriteInt16Vector(uint32_t sizeOfVector) {
73 beginWriteGenericVector();
74 rememberCurrentStreamPosition();
76 virtual void beginWriteInt32Vector(uint32_t sizeOfVector) {
77 beginWriteGenericVector();
78 rememberCurrentStreamPosition();
80 virtual void beginWriteInt64Vector(uint32_t sizeOfVector) {
81 beginWriteGenericVector();
83 rememberCurrentStreamPosition();
85 virtual void beginWriteUInt8Vector(uint32_t sizeOfVector) {
86 beginWriteGenericVector();
87 rememberCurrentStreamPosition();
89 virtual void beginWriteUInt16Vector(uint32_t sizeOfVector) {
90 beginWriteGenericVector();
91 rememberCurrentStreamPosition();
93 virtual void beginWriteUInt32Vector(uint32_t sizeOfVector) {
94 beginWriteGenericVector();
95 rememberCurrentStreamPosition();
97 virtual void beginWriteUInt64Vector(uint32_t sizeOfVector) {
98 beginWriteGenericVector();
100 rememberCurrentStreamPosition();
102 virtual void beginWriteFloatVector(uint32_t sizeOfVector) {
103 beginWriteGenericVector();
105 rememberCurrentStreamPosition();
107 virtual void beginWriteDoubleVector(uint32_t sizeOfVector) {
108 beginWriteGenericVector();
110 rememberCurrentStreamPosition();
112 virtual void beginWriteStringVector(uint32_t sizeOfVector) {
113 beginWriteGenericVector();
114 rememberCurrentStreamPosition();
116 virtual void beginWriteByteBufferVector(uint32_t sizeOfVector) {
117 beginWriteGenericVector();
118 rememberCurrentStreamPosition();
120 virtual void beginWriteVersionVector(uint32_t sizeOfVector) {
121 beginWriteGenericVector();
123 rememberCurrentStreamPosition();
125 virtual void beginWriteVectorOfSerializableStructs(uint32_t sizeOfVector) {
126 beginWriteGenericVector();
128 rememberCurrentStreamPosition();
130 virtual void beginWriteVectorOfVectors(uint32_t sizeOfVector) {
131 beginWriteGenericVector();
132 rememberCurrentStreamPosition();
134 virtual void beginWriteVectorOfMaps(uint32_t sizeOfVector) {
135 beginWriteGenericVector();
137 rememberCurrentStreamPosition();
140 virtual void endWriteVector() {
141 uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition();
142 writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes);
145 virtual OutputStream& writeVersionValue(const Version& versionValue) {
147 writeValue(versionValue.Major);
148 writeValue(versionValue.Minor);
152 virtual void beginWriteSerializableStruct(const SerializableStruct& serializableStruct) { alignToBoundary(8); }
153 virtual void endWriteSerializableStruct(const SerializableStruct& serializableStruct) { }
155 virtual void beginWriteMap(size_t elementCount) {
156 alignToBoundary(sizeof(uint32_t));
157 rememberCurrentStreamPosition();
158 writeBasicTypeValue((uint32_t) 0);
160 rememberCurrentStreamPosition();
163 virtual void endWriteMap() {
164 uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition();
165 writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes);
168 virtual bool hasError() const {
173 * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream.
174 * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage.
176 * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to.
178 DBusOutputStream(DBusMessage dbusMessage);
181 * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the
182 * #DBusMessage outside of the stream if you intend to make further use of the message, e.g. in order to send it,
183 * now that you have written some payload into it.
185 virtual ~DBusOutputStream();
188 * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush()
189 * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is
190 * not deleted by calling flush().
195 * Marks the stream as erroneous.
197 inline void setError();
200 * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing.
201 * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing.
203 * @param numOfBytes The number of bytes that should be reserved for writing.
205 void reserveMemory(size_t numOfBytes);
208 * @return current data position where later writing is possible
210 size_t getCurrentPosition();
212 template<typename _BasicType>
213 DBusOutputStream& writeBasicTypeValue(const _BasicType& basicValue) {
214 if (sizeof(_BasicType) > 1)
215 alignToBoundary(sizeof(_BasicType));
217 writeRawData(reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType));
222 template<typename _BasicType>
223 bool writeBasicTypeValueAtPosition(size_t position, const _BasicType& basicValue) {
224 assert(position + sizeof(_BasicType) <= payload_.size());
226 return writeRawDataAtPosition(position, reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType));
229 DBusOutputStream& writeString(const char* cString, const uint32_t& length);
232 * Fills the stream with 0-bytes to make the next value be aligned to the boundary given.
233 * This means that as many 0-bytes are written to the buffer as are necessary
234 * to make the next value start with the given alignment.
236 * @param alignBoundary The byte-boundary to which the next value should be aligned.
238 virtual void alignToBoundary(const size_t alignBoundary);
241 * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing.
242 * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage.
244 * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example:
248 * outputMessageStream.alignForBasicType(sizeof(int32_t));
249 * const char* const reinterpreted = reinterpret_cast<const char*>(&val);
250 * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t));
254 * @param val The array of chars that should serve as input
255 * @param sizeInByte The number of bytes that should be written
256 * @return true if writing was successful, false otherwise.
258 * @see DBusOutputMessageStream()
261 bool writeRawData(const char* rawDataPtr, const size_t sizeInByte);
263 bool writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte);
266 std::string payload_;
269 inline void beginWriteGenericVector() {
270 alignToBoundary(sizeof(uint32_t));
271 rememberCurrentStreamPosition();
272 writeBasicTypeValue((uint32_t) 0);
275 inline void rememberCurrentStreamPosition() {
276 savedStreamPositions_.push(payload_.size());
279 inline size_t popRememberedStreamPosition() {
280 size_t val = savedStreamPositions_.top();
281 savedStreamPositions_.pop();
285 inline size_t getCurrentStreamPosition() {
286 return payload_.size();
289 DBusError dbusError_;
290 DBusMessage dbusMessage_;
292 std::stack<position_t> savedStreamPositions_;
296 //Additional 0-termination, so this is 8 byte of \0
297 static const char* eightByteZeroString = "\0\0\0\0\0\0\0";
299 inline void DBusOutputStream::alignToBoundary(const size_t alignBoundary) {
300 assert(alignBoundary > 0 && alignBoundary <= 8 && (alignBoundary % 2 == 0 || alignBoundary == 1));
302 size_t alignMask = alignBoundary - 1;
303 size_t necessaryAlignment = ((alignMask - (payload_.size() & alignMask)) + 1) & alignMask;
305 writeRawData(eightByteZeroString, necessaryAlignment);
308 inline bool DBusOutputStream::writeRawData(const char* rawDataPtr, const size_t sizeInByte) {
309 assert(sizeInByte >= 0);
311 payload_.append(rawDataPtr, sizeInByte);
316 inline bool DBusOutputStream::writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte) {
317 assert(sizeInByte >= 0);
319 payload_ = payload_.replace(position, sizeInByte, rawDataPtr, sizeInByte);
324 inline size_t DBusOutputStream::getCurrentPosition() {
325 return payload_.size();
329 OutputStream& DBusOutputStream::writeValue(const ByteBuffer& byteBufferValue) {
330 *this << byteBufferValue;
335 } // namespace CommonAPI
337 #endif // COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_