OnixS C++ CME MDP Premium Market Data Handler 5.11.1
Users' manual and API documentation
Loading...
Searching...
No Matches
MessageHolder.h
Go to the documentation of this file.
1// Copyright Onix Solutions Limited [OnixS]. All rights reserved.
2//
3// This software owned by Onix Solutions Limited [OnixS] and is
4// protected by copyright law and international copyright treaties.
5//
6// Access to and use of the software is governed by the terms of the applicable
7// OnixS Software Services Agreement (the Agreement) and Customer end user license
8// agreements granting a non-assignable, non-transferable and non-exclusive license
9// to use the software for it's own data processing purposes under the terms defined
10// in the Agreement.
11//
12// Except as otherwise granted within the terms of the Agreement, copying or
13// reproduction of any part of this source code or associated reference material
14// to any other location for further reproduction or redistribution, and any
15// amendments to this copyright notice, are expressly prohibited.
16//
17// Any reproduction or redistribution for sale or hiring of the Software not in
18// accordance with the terms of the Agreement is a violation of copyright law.
19//
20
21#pragma once
22
23#include <cassert>
24#include <cstddef>
25#include <cstring>
26#include <new>
27#include <ostream>
28#include <string>
29#include <type_traits>
30#include <utility>
31
32#include <OnixS/CME/MDH/ABI.h>
38
40
41namespace details {
42
44template <typename MessageType, bool isFix = std::is_base_of<Messaging::FIX::Message, MessageType>::value> struct HeldAdapter;
45
46template <typename MessageType>
47struct HeldAdapter<MessageType, true> final : public MessageType
48{
49 static_assert(std::is_base_of<Messaging::FIX::Message, MessageType>::value, "Not a message.");
50
51 static constexpr bool isFix = true;
52
53 using SbeType = typename MessageType::Binary;
54
55 using EncodedLength = typename SbeType::EncodedLength;
56
57 HeldAdapter() = default;
58
60 : MessageType(SbeType(data, length, version))
61 {
62 }
63
68};
69
70template <typename MessageType>
71struct HeldAdapter<MessageType, false> final : public MessageType
72{
73 static_assert(std::is_base_of<Messaging::SbeMessage, MessageType>::value, "Not a message.");
74
75 static constexpr bool isFix = false;
76
77 using SbeType = MessageType;
78
79 using EncodedLength = typename SbeType::EncodedLength;
80
81 HeldAdapter() = default;
82
84 : MessageType(data, length, version)
85 {
86 }
87
92};
93
94} // namespace details
95
96template <typename, size_t> class MessageHolder;
97
106template <typename MessageType, size_t MaxMessageSize>
107inline void toStr(std::string& str, const MessageHolder<MessageType, MaxMessageSize>& holder)
108{
110 using Messaging::toStr;
111
112 str += "MessageHolder[";
113
114 str += "BufferSize=";
115 Messaging::toStr(str, holder.BufferSize);
116
117 str += ", ";
118 toStr(str, holder.header());
119
120 str += ", ";
121 toStr(str, holder.message());
122
123 str += "]";
124}
125
147template
148<
149 typename MessageTypeT,
150 size_t MaxMessageSize = Messaging::MaxMessageSize
151>
153{
154 using SbeType = typename details::HeldAdapter<MessageTypeT>::SbeType;
155
156public:
158 using MessageHolderBase = MessageHolder<MessageTypeT, MaxMessageSize>;
159
161 using MessageType = details::HeldAdapter<MessageTypeT>;
162
164 enum : Messaging::MessageSize { BufferSize = MaxMessageSize + sizeof(MessagePrefix) };
165
173 explicit MessageHolder(Messaging::SchemaVersion version = SbeType::Schema::Version)
174 {
175 Messaging::fromEmptyStorage<MessagePrefix>(buffer_);
176
177 messageSize(0);
178
179 message_ = MessageType(buffer_ + sizeof(MessagePrefix), MaxMessageSize, version);
180 }
181
187 const unsigned char* buffer() const noexcept
188 {
189 return buffer_;
190 }
191
198 {
199 return header().messageSize();
200 }
201
208 {
209 return message_;
210 }
211
216 const MessageType& message() const noexcept
217 {
218 return message_;
219 }
220
232 template <typename Callable>
233 auto operator%(Callable&& callable) & -> decltype(
234 std::forward<Callable>(callable)(std::declval<MessageType&>()), std::declval<MessageHolder&>())
235 {
236 std::forward<Callable>(callable)(message());
237 return *this;
238 }
239
246 {
247 return bufferSize() - sizeof(MessagePrefix);
248 }
249
255 {
256 return &message();
257 }
258
262 const MessageType* operator->() const noexcept
263 {
264 return &message();
265 }
266
271 const MessageType& operator* () const noexcept
272 {
273 return message();
274 }
275
281 MessageType& operator* () noexcept
282 {
283 return message();
284 }
285
290 const MessagePrefix& header() const noexcept
291 {
292 return *reinterpret_cast<const MessagePrefix*>(buffer_);
293 }
294
302 {
303 const auto calculatedMessageSize = message().calculateBinarySize();
304
305 assert(calculatedMessageSize <= MaxMessageSize);
306
307 messageSize(calculatedMessageSize);
308 return calculatedMessageSize;
309 }
310
319 {
320 setHeader();
321 return asSpan();
322 }
323
330 ByteSpan asSpan() const noexcept
331 {
332 return ByteSpan(buffer(), bufferSize());
333 }
334
340 std::string toString() const
341 {
342 return toStr(*this);
343 }
344
345private:
346 MessageHolder(const MessageHolder&) = delete;
347 MessageHolder& operator=(const MessageHolder&) = delete;
348 MessageHolder(MessageHolder&&) = delete;
349 MessageHolder& operator=(MessageHolder&&) = delete;
350
351 static_assert(std::is_nothrow_default_constructible<MessageType>::value, "MessageType must be nothrow default constructible.");
352 static_assert(std::is_nothrow_move_assignable<MessageType>::value, "MessageType must be nothrow move assignable.");
353 static_assert(MaxMessageSize >= sizeof(Messaging::MessageHeader), "MaxMessageSize template parameter is too small");
354 static_assert(MaxMessageSize >= Messaging::GetMinMessageSize<SbeType>::Size, "The buffer can not fit the message");
355 static_assert(MaxMessageSize <= Messaging::MaxMessageSize, "The buffer is too large.");
356 static_assert(Messaging::IsTriviallyCopyable<MessagePrefix>::value, "MessagePrefix must be trivially copiable.");
357 static_assert(std::is_nothrow_default_constructible<MessagePrefix>::value, "MessagePrefix must be nothrow default constructible.");
358 static_assert(std::is_trivially_destructible<MessagePrefix>::value, "MessagePrefix must be trivially destructible.");
359
360 MessagePrefix& mutableHeader() noexcept
361 {
362 return *reinterpret_cast<MessagePrefix*>(buffer_);
363 }
364
365 void messageSize(Messaging::MessageSize size) noexcept
366 {
367 mutableHeader().messageSize(size + sizeof(MessagePrefix));
368 }
369
370 MessageType message_;
371 alignas(MessagePrefix) Messaging::Byte buffer_[BufferSize] = {};
372};
373
381template <typename MessageType, size_t MaxMessageSize>
383{
384 std::string res;
385 toStr(res, holder);
386 return res;
387}
388
398template <typename MessageType, size_t MaxMessageSize>
399std::ostream& operator<<(std::ostream& stream, const MessageHolder<MessageType, MaxMessageSize>& rhs)
400{
401 return stream << toStr(rhs);
402}
403
#define ONIXS_CME_MDH_TESTING_NAMESPACE_END
Definition Bootstrap.h:84
#define ONIXS_CME_MDH_TESTING_NAMESPACE_BEGIN
Definition Bootstrap.h:83
#define ONIXS_CMEMDH_NODISCARD
Definition Compiler.h:165
Represents the length prefix preceding each message in an MDP packet.
Template ID and length of message root.
Definition Composites.h:308
Owns fixed-capacity storage for a prefixed CME message.
std::string toString() const
Creates a string containing the capacity, prefix, and message.
ByteSpan toNetworkBytes() noexcept
Commits the current payload size and returns the network-ready bytes.
MessageHolder(Messaging::SchemaVersion version=SbeType::Schema::Version)
Constructs an empty message for a schema version.
MessageType & message() noexcept
Provides mutable access to the stored message.
const MessageType & message() const noexcept
Provides read-only access to the stored message.
auto operator%(Callable &&callable) &-> decltype(std::forward< Callable >(callable)(std::declval< MessageType & >()), std::declval< MessageHolder & >())
Applies a callable customization to the stored message.
Messaging::MessageSize setHeader() noexcept
Commits the current encoded payload size to the message prefix.
const MessagePrefix & header() const noexcept
Provides read-only access to the message prefix.
const unsigned char * buffer() const noexcept
Provides read-only access to the prefixed message buffer.
const MessageType * operator->() const noexcept
Provides pointer-style read-only access to the stored message.
Messaging::MessageSize bufferSize() const noexcept
Returns the committed size of the prefixed message.
MessageType * operator->() noexcept
Provides pointer-style mutable access to the stored message.
void toStr(std::string &str, const Message &message)
Serializes into a tag=value format.
Definition Message.h:807
constexpr MessageSize MaxMessageSize
Maximum supported message size.
MessageHeader::Version SchemaVersion
Aliases SBE-encoded data version type.
UInt16 MessageSize
Message length type.
Definition Aliases.h:29
void toStr(std::string &, Int8)
Serializes given integer into a string.
void toStr(std::string &str, const MessageHolder< MessageType, MaxMessageSize > &holder)
Appends the holder's capacity, prefix, and message to a string.
std::ostream & operator<<(std::ostream &stream, const MessageHolder< MessageType, MaxMessageSize > &rhs)
Writes the holder's capacity, prefix, and message to a stream.
std::span< const std::uint8_t > ByteSpan
Provides a non-owning read-only view over contiguous byte storage.
Definition ByteSpan.h:44
HeldAdapter(void *data, EncodedLength length, Messaging::SbeMessage::NoInit, Messaging::SbeMessage::NoCheck) noexcept
HeldAdapter(void *data, EncodedLength length, Messaging::SchemaVersion version)
HeldAdapter(void *data, EncodedLength length, Messaging::SbeMessage::NoInit, Messaging::SbeMessage::NoCheck) noexcept
HeldAdapter(void *data, EncodedLength length, Messaging::SchemaVersion version)