OnixS C++ CME MDP Premium Market Data Handler 5.11.1
Users' manual and API documentation
Loading...
Searching...
No Matches
MessageBuilder.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 protected by copyright law
4// and international copyright treaties.
5//
6// Access to and use of the software is governed by the terms of the applicable OnixS Software
7// Services Agreement (the Agreement) and Customer end user license agreements granting
8// a non-assignable, non-transferable and non-exclusive license to use the software
9// for it's own data processing purposes under the terms defined in the Agreement.
10//
11// Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
12// of this source code or associated reference material to any other location for further reproduction
13// or redistribution, and any amendments to this copyright notice, are expressly prohibited.
14//
15// Any reproduction or redistribution for sale or hiring of the Software not in accordance with
16// the terms of the Agreement is a violation of copyright law.
17//
18
19#pragma once
20
21#include <cassert>
22#include <iterator>
23#include <limits>
24#include <stdexcept>
25#include <tuple>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30#include <OnixS/CME/MDH/ABI.h>
35
37
39namespace details
40{
41 using std::begin;
42 using std::end;
43
44 template <typename Holder>
45 using UnqualifiedMessageHolder = typename std::remove_cv<typename std::remove_reference<Holder>::type>::type;
46
47 template <typename ExpectedHolder, typename Holder, bool = IsMessageHolder<UnqualifiedMessageHolder<Holder>>::value>
48 struct HasExpectedMessageType : std::false_type
49 {};
50
51 template <typename ExpectedHolder, typename Holder>
52 struct HasExpectedMessageType<ExpectedHolder, Holder, true> : std::is_same<
53 typename ExpectedHolder::MessageHolderBase::MessageType, typename UnqualifiedMessageHolder<Holder>::MessageHolderBase::MessageType>
54 {};
55
56 template <typename ExpectedHolder, typename Holder>
57 struct IsMutableMessageHolder : std::integral_constant<bool,
58 HasExpectedMessageType<ExpectedHolder, Holder>::value && !std::is_const<typename std::remove_reference<Holder>::type>::value>
59 {};
60
61 template <typename ExpectedHolder, typename Holder>
62 using EnableMutableMessageHolder = typename std::enable_if<IsMutableMessageHolder<ExpectedHolder, Holder>::value, Holder&>::type;
63
64 template <typename ExpectedHolder>
66 {
67 template <typename Holder>
68 static auto apply(Holder& message, EventFlags::Bits eventIndicator, Messaging::Timestamp transactTime) noexcept
70 {
71 message->reset();
72 message->setMatchEventIndicator(Messaging::MatchEventIndicator(eventIndicator));
73 message->setTransactTime(transactTime);
74
75 return message;
76 }
77 };
78
79 template <typename ExpectedHolder, typename Holder>
80 auto initializeMessage(Holder& message, EventFlags::Bits eventIndicator, Messaging::Timestamp transactTime) noexcept
82 {
84 message, eventIndicator, transactTime);
85 }
86
87 template <
88 typename Holder, typename ExpectedHolder,
89 typename Operation = MessageInitializationOperation<ExpectedHolder>,
90 typename... Arguments>
91 auto makeInitializationRecipe(Arguments&&... arguments) -> typename std::enable_if<
94 makeMessageOperation<Operation>(std::forward<Arguments>(arguments)...)))>::type
95 {
97 makeMessageOperation<Operation>(std::forward<Arguments>(arguments)...));
98 }
99
100 template <typename EntryCount>
101 EntryCount checkedIncrementedEntryCount(EntryCount count)
102 {
103 if (count == (std::numeric_limits<EntryCount>::max)())
104 throw std::runtime_error("Entry count limit exceeded");
105
106 return static_cast<EntryCount>(count + 1);
107 }
108
109 template <typename Group, typename Resize>
110 typename Group::Entry appendGroupEntry(Group group, Resize resize)
111 {
112 const auto index = group.size();
113 const auto resizedGroup = resize(checkedIncrementedEntryCount(index));
114 return resizedGroup[index];
115 }
116
117 template <typename Range>
118 auto rangeBegin(Range& range) -> decltype(begin(range))
119 {
120 return begin(range);
121 }
122
123 template <typename Range>
124 auto rangeEnd(Range& range) -> decltype(end(range))
125 {
126 return end(range);
127 }
128
129 template <Messaging::UpdateAction::Enum Action, typename Holder, typename Tuple, std::size_t... Indices>
130 auto appendProjectedEntryArguments(Holder& message, Tuple&& arguments, IndexSequence<Indices...>)
131 -> decltype(ContextualEntryOperation<Action>::apply(message, std::get<Indices>(std::forward<Tuple>(arguments))...))
132 {
133 return ContextualEntryOperation<Action>::apply(message, std::get<Indices>(std::forward<Tuple>(arguments))...);
134 }
135
136 template <Messaging::UpdateAction::Enum Action, typename Holder, typename Tuple>
137 auto appendProjectedEntry(Holder& message, Tuple&& arguments)
138 -> decltype(appendProjectedEntryArguments<Action>(message, std::forward<Tuple>(arguments),
139 typename MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>::value>::Type()))
140 {
142 message, std::forward<Tuple>(arguments),
143 typename MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>::value>::Type());
144 }
145
146 template <Messaging::UpdateAction::Enum Action, typename Tuple, std::size_t... Indices>
147 auto makeProjectedEntryOperationArguments(Tuple&& arguments, IndexSequence<Indices...>)
149 std::get<Indices>(std::forward<Tuple>(arguments))...))
150 {
151 return makeContextualEntryOperation<Action>(std::get<Indices>(std::forward<Tuple>(arguments))...);
152 }
153
154 template <Messaging::UpdateAction::Enum Action, typename Tuple>
155 auto makeProjectedEntryOperation(Tuple&& arguments)
156 -> decltype(makeProjectedEntryOperationArguments<Action>(std::forward<Tuple>(arguments),
157 typename MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>::value>::Type()))
158 {
160 std::forward<Tuple>(arguments),
161 typename MakeIndexSequence<std::tuple_size<typename std::decay<Tuple>::type>::value>::Type());
162 }
163
164 template <typename Operation>
166 {
167 public:
168 explicit EntryRangeOperation(std::vector<Operation> operations)
169 : operations_(std::move(operations))
170 {
171 }
172
173 template <typename Holder>
174 auto apply(Holder& message) const
175 -> decltype(std::declval<const Operation&>().apply(message), std::declval<Holder&>())
176 {
177 for (const auto& operation : operations_)
178 operation.apply(message);
179
180 return message;
181 }
182
183 private:
184 std::vector<Operation> operations_;
185 };
186
187 template <Messaging::UpdateAction::Enum Action, typename Iterator, typename Sentinel, typename Projection>
188 auto makeEntryRangeOperationFromIterators(Iterator first, Sentinel last, Projection& projection)
190 {
191 using Operation = typename std::decay<decltype(makeProjectedEntryOperation<Action>(projection(*first)))>::type;
192
193 std::vector<Operation> operations;
194 for (; first != last; ++first)
195 operations.push_back(makeProjectedEntryOperation<Action>(projection(*first)));
196
197 return EntryRangeOperation<Operation>(std::move(operations));
198 }
199
200 template <Messaging::UpdateAction::Enum Action, typename Range, typename Projection>
201 auto makeEntryRangeOperation(Range& range, Projection& projection)
202 -> decltype(makeEntryRangeOperationFromIterators<Action>(rangeBegin(range), rangeEnd(range), projection))
203 {
204 auto first = rangeBegin(range);
205 auto last = rangeEnd(range);
206 return makeEntryRangeOperationFromIterators<Action>(std::move(first), std::move(last), projection);
207 }
208
209 template <Messaging::UpdateAction::Enum Action, typename Range, typename Projection>
211 {
212 public:
213 EntryRangeStage(Range& range, Projection& projection) noexcept
214 : range_(&range)
215 , projection_(&projection)
216 , consumed_(false)
217 {
218 }
219
222
224 : range_(other.range_)
225 , projection_(other.projection_)
226 , consumed_(other.consumed_)
227 {
228 other.consumed_ = true;
229 }
230
232 std::declval<Range&>(), std::declval<Projection&>()))
233 {
234 assert(!consumed_);
235 consumed_ = true;
236 return makeEntryRangeOperation<Action>(*range_, *projection_);
237 }
238
239 private:
240 Range* range_;
241 Projection* projection_;
242 bool consumed_;
243 };
244
245 template <Messaging::UpdateAction::Enum Action, typename Holder, typename Iterator, typename Sentinel, typename Projection>
246 auto addEntriesFromIterators(Holder& message, Iterator first, Sentinel last, Projection&& projection)
247 -> decltype(
248 static_cast<bool>(std::declval<Iterator&>() != std::declval<Sentinel&>()),
249 ++std::declval<Iterator&>(),
250 appendProjectedEntry<Action>(message, std::declval<Projection&>()(*std::declval<Iterator&>())),
251 std::declval<Holder&>()
252 )
253 {
254 for (; first != last; ++first)
255 appendProjectedEntry<Action>(message, projection(*first));
256
257 return message;
258 }
259}
260
281template <Messaging::UpdateAction::Enum Action, typename Holder, typename Range, typename Projection>
282auto addEntries(Holder& message, Range&& range, Projection&& projection)
284 message, details::rangeBegin(range), details::rangeEnd(range), std::forward<Projection>(projection)))
285{
286 auto first = details::rangeBegin(range);
287 auto last = details::rangeEnd(range);
288 return details::addEntriesFromIterators<Action>(message, std::move(first), std::move(last), std::forward<Projection>(projection));
289}
290
305template <Messaging::UpdateAction::Enum Action, typename Range, typename Projection>
307auto entries(Range&& range, Projection&& projection)
309 Action, typename std::remove_reference<Range>::type, typename std::remove_reference<Projection>::type>
310{
311 return {range, projection};
312}
313
326template <typename Holder, typename... Operations, Messaging::UpdateAction::Enum Action, typename Range, typename Projection>
328 -> decltype(recipe.append(std::move(stage).materialize()))
329{
330 auto operation = std::move(stage).materialize();
331 return recipe.append(std::move(operation));
332}
333
346template <typename Holder, typename... Operations, Messaging::UpdateAction::Enum Action, typename Range, typename Projection>
348 -> decltype(std::move(recipe).append(std::move(stage).materialize()))
349{
350 auto operation = std::move(stage).materialize();
351 return std::move(recipe).append(std::move(operation));
352}
353
#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
The time point without the time-zone information.
Definition Time.h:450
Owns a reusable recipe for constructing a held test message.
auto apply(Holder &message) const -> decltype(std::declval< const Operation & >().apply(message), std::declval< Holder & >())
EntryRangeOperation(std::vector< Operation > operations)
EntryRangeStage(Range &range, Projection &projection) noexcept
EntryRangeStage(EntryRangeStage &&other) noexcept
EntryRangeStage & operator=(const EntryRangeStage &)=delete
EntryRangeStage(const EntryRangeStage &)=delete
auto materialize() &&-> decltype(makeEntryRangeOperation< Action >(std::declval< Range & >(), std::declval< Projection & >()))
auto makeInitializationRecipe(Arguments &&... arguments) -> typename std::enable_if< IsMutableMessageHolder< ExpectedHolder, Holder >::value, decltype(makeMessageRecipe< typename std::decay< Holder >::type >(makeMessageOperation< Operation >(std::forward< Arguments >(arguments)...)))>::type
auto addEntriesFromIterators(Holder &message, Iterator first, Sentinel last, Projection &&projection) -> decltype(static_cast< bool >(std::declval< Iterator & >() !=std::declval< Sentinel & >()),++std::declval< Iterator & >(), appendProjectedEntry< Action >(message, std::declval< Projection & >()(*std::declval< Iterator & >())), std::declval< Holder & >())
typename std::enable_if< IsMutableMessageHolder< ExpectedHolder, Holder >::value, Holder & >::type EnableMutableMessageHolder
MessageRecipe< Holder, typename std::decay< Operation >::type > makeMessageRecipe(Operation &&operation)
typename std::remove_cv< typename std::remove_reference< Holder >::type >::type UnqualifiedMessageHolder
auto makeProjectedEntryOperationArguments(Tuple &&arguments, IndexSequence< Indices... >) -> decltype(makeContextualEntryOperation< Action >(std::get< Indices >(std::forward< Tuple >(arguments))...))
auto makeContextualEntryOperation(Arguments &&... arguments) -> decltype(makeMessageOperation< ContextualEntryOperation< Action > >(std::forward< Arguments >(arguments)...))
auto makeProjectedEntryOperation(Tuple &&arguments) -> decltype(makeProjectedEntryOperationArguments< Action >(std::forward< Tuple >(arguments), typename MakeIndexSequence< std::tuple_size< typename std::decay< Tuple >::type >::value >::Type()))
MessageOperation< Operation, typename std::decay< Arguments >::type... > makeMessageOperation(Arguments &&... arguments)
auto makeEntryRangeOperationFromIterators(Iterator first, Sentinel last, Projection &projection) -> EntryRangeOperation< typename std::decay< decltype(makeProjectedEntryOperation< Action >(projection(*first)))>::type >
auto appendProjectedEntry(Holder &message, Tuple &&arguments) -> decltype(appendProjectedEntryArguments< Action >(message, std::forward< Tuple >(arguments), typename MakeIndexSequence< std::tuple_size< typename std::decay< Tuple >::type >::value >::Type()))
auto appendProjectedEntryArguments(Holder &message, Tuple &&arguments, IndexSequence< Indices... >) -> decltype(ContextualEntryOperation< Action >::apply(message, std::get< Indices >(std::forward< Tuple >(arguments))...))
auto initializeMessage(Holder &message, EventFlags::Bits eventIndicator, Messaging::Timestamp transactTime) noexcept -> EnableMutableMessageHolder< ExpectedHolder, Holder >
auto makeEntryRangeOperation(Range &range, Projection &projection) -> decltype(makeEntryRangeOperationFromIterators< Action >(rangeBegin(range), rangeEnd(range), projection))
EntryCount checkedIncrementedEntryCount(EntryCount count)
auto rangeEnd(Range &range) -> decltype(end(range))
Group::Entry appendGroupEntry(Group group, Resize resize)
auto rangeBegin(Range &range) -> decltype(begin(range))
auto operator|(Holder &message, details::DeferredMessageOperation< Factory > &&deferredOperation) -> typename std::enable_if< !details::IsMessageRecipe< typename std::decay< Holder >::type >::value, decltype(std::move(deferredOperation).materialize().apply(message), message)>::type
Materializes and applies a deferred message operation to a named holder.
auto entries(Range &&range, Projection &&projection) -> details::EntryRangeStage< Action, typename std::remove_reference< Range >::type, typename std::remove_reference< Projection >::type >
Creates a reusable-recipe stage from projected range values.
auto addEntries(Holder &message, Range &&range, Projection &&projection) -> decltype(details::addEntriesFromIterators< Action >(message, details::rangeBegin(range), details::rangeEnd(range), std::forward< Projection >(projection)))
Appends entries projected from an input range.
STL namespace.
Messaging::MatchEventIndicator::Bits Bits
Protocol storage type for combined event flags.
Definition EventFlags.h:30
static auto apply(Holder &message, Arguments &&... arguments) -> decltype(EntryOperationSelector< typename std::decay< Holder >::type::MessageType >::template apply< Action >(message, std::forward< Arguments >(arguments)...))
static auto apply(Holder &message, EventFlags::Bits eventIndicator, Messaging::Timestamp transactTime) noexcept -> EnableMutableMessageHolder< ExpectedHolder, Holder >