1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//#define COMMONAPI_DBUS_DEBUG_SERIALIZATION
#ifdef COMMONAPI_DBUS_DEBUG_SERIALIZATION
#include <iomanip>
#include <sstream>
#endif
#include <CommonAPI/DBus/DBusOutputStream.hpp>
namespace CommonAPI {
namespace DBus {
DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage)
: dbusMessage_(dbusMessage) {
}
// Internal
size_t DBusOutputStream::getPosition() {
return payload_.size();
}
void DBusOutputStream::pushPosition() {
positions_.push(payload_.size());
}
size_t DBusOutputStream::popPosition() {
size_t itsPosition = positions_.top();
positions_.pop();
return itsPosition;
}
// TODO Check where dbusError_ is set
bool DBusOutputStream::hasError() const {
return dbusError_;
}
// Writes the data that was buffered within this #DBusOutputMessageStream to
// the #DBusMessage that was given to the constructor. Each call to flush()
// will completely override the data that currently is contained in the
// #DBusMessage. The data that is buffered in this #DBusOutputMessageStream
// is not deleted by calling flush().
void DBusOutputStream::flush() {
const int toWrite = payload_.size();
dbusMessage_.setBodyLength(toWrite);
char* destinationDataPtr = dbusMessage_.getBodyData();
memcpy(destinationDataPtr, payload_.c_str(), toWrite);
}
void DBusOutputStream::setError() {
}
/**
* Reserves the given number of bytes for writing, thereby negating the need to
* dynamically allocate memory while writing. Use this method for optimization:
* If possible, reserve as many bytes as you need for your data before doing
* any writing.
*
* @param numOfBytes The number of bytes that should be reserved for writing.
*/
void DBusOutputStream::reserveMemory(size_t numOfBytes) {
assert(numOfBytes >= 0);
payload_.reserve(numOfBytes);
}
DBusOutputStream& DBusOutputStream::writeString(const char *_value, const uint32_t &_length) {
assert(_value != NULL);
assert(_value[_length] == '\0');
_writeValue(_length);
_writeRaw(_value, _length + 1);
return (*this);
}
// Additional 0-termination, so this is 8 byte of \0
static const char eightByteZeroString[] = "\0\0\0\0\0\0\0";
void DBusOutputStream::align(const size_t _boundary) {
assert(_boundary > 0 && _boundary <= 8 &&
(_boundary % 2 == 0 || _boundary == 1));
size_t mask = _boundary - 1;
size_t necessary = ((mask - (payload_.size() & mask)) + 1) & mask;
_writeRaw(eightByteZeroString, necessary);
}
void DBusOutputStream::_writeRaw(const char *_data, const size_t _size) {
payload_.append(_data, _size);
}
void DBusOutputStream::_writeRawAt(const char *_data, const size_t _size, size_t _position) {
payload_ = payload_.replace(_position, _size, _data, _size);
}
void DBusOutputStream::writeSignature(const std::string& signature) {
const auto& signatureLength = signature.length();
assert(signatureLength > 0 && signatureLength < 256);
const uint8_t wireLength = (uint8_t) signatureLength;
(*this) << wireLength;
_writeRaw(signature.c_str(), wireLength + 1);
}
} // namespace DBus
} // namespace CommonAPI
|