OnixS C++ CME iLink 3 Binary Order Entry Handler  1.9.0
API Documentation
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 <vector>
24 
29 
31 
32 /// The policy to create messages with null-initialized optional fields.
34 {
35  /// \private
36  template <typename SbeMessageType>
37  inline static SbeMessageType createMessage(
38  void* data, MessageSize length, SchemaVersion version)
39  {
40  return SbeMessageType(data, length, version);
41  }
42 
43  /// \private
44  inline static const char* name()
45  {
46  return "FieldsInitPolicy";
47  }
48 };
49 
50 /// The policy to create messages without initialized optional fields.
52 {
53  /// \private
54  template <typename SbeMessageType>
55  inline static SbeMessageType createMessage(
56  void* data, MessageSize length, SchemaVersion version)
57  {
58  return SbeMessageType(
59  data, length, SbeMessage::NoFieldsInit(), version);
60  }
61 
62  /// \private
63  inline static const char* name()
64  {
65  return "FieldsNoInitPolicy";
66  }
67 };
68 
69 /// \private
70 template
71 <
72  typename MessageType,
73  bool isFix =
74  IsBaseOf<TagBased::Message, MessageType>::value
75 >
76 struct HeldAdapter;
77 
78 template <typename MessageType>
79 struct HeldAdapter<MessageType, true> ONIXS_ILINK3_FINAL
80  : public MessageType
81 {
82  ONIXS_ILINK3_STATIC_ASSERT((
83  IsBaseOf<TagBased::Message, MessageType>::value));
84 
85  typedef typename
86  MessageType::Binary
88 
89  typedef typename
90  SbeType::EncodedLength
92 
93  HeldAdapter() ONIXS_ILINK3_DEFAULT;
94 
95  HeldAdapter(
96  void* data,
97  EncodedLength length,
98  SchemaVersion version)
99  : MessageType(SbeType(data, length, version))
100  {
101  }
102 
104  void* data,
105  EncodedLength length,
107  SchemaVersion version)
108  : MessageType(SbeType(data, length, version))
109  {
110  }
111 
113  void* data,
114  EncodedLength length,
116  : MessageType(SbeType(data, length))
117  {
118  }
119 
121  void* data,
122  EncodedLength length,
126  : MessageType(
127  SbeType(
128  data,
129  length,
130  SbeMessage::NoInit(),
131  SbeMessage::NoCheck()))
132  {
133  }
134 };
135 
136 template <typename MessageType>
137 struct HeldAdapter<MessageType, false> ONIXS_ILINK3_FINAL
138  : public MessageType
139 {
140  ONIXS_ILINK3_STATIC_ASSERT((
141  IsBaseOf<SbeMessage, MessageType>::value));
142 
143  typedef MessageType SbeType;
144 
145  typedef typename
146  SbeType::EncodedLength
148 
149  HeldAdapter() ONIXS_ILINK3_DEFAULT;
150 
151  HeldAdapter(
152  void* data,
153  EncodedLength length,
154  SchemaVersion version)
155  : MessageType(data, length, version)
156  {
157  }
158 
160  void* data,
161  EncodedLength length,
163  SchemaVersion version)
164  : MessageType(data, length, version)
165  {
166  }
167 
169  void* data,
170  EncodedLength length,
172  : MessageType(data, length)
173  {
174  }
175 
177  void* data,
178  EncodedLength length,
182  : MessageType(
183  data,
184  length,
185  SbeMessage::NoInit(),
186  SbeMessage::NoCheck())
187  {
188  }
189 };
190 
191 /// \return a human-readable presentation.
192 template <typename, size_t, typename>
194 template <
195  template <typename, size_t, typename> class HolderType,
196  typename MsgType,
197  size_t MaxMessageSize,
198  typename MessageInitializer>
199 inline void toStr(
200  std::string& str,
201  const HolderType<MsgType, MaxMessageSize, MessageInitializer>& holder)
202 {
203  str += "MessageHolder[";
204 
205  str += "BufferSize=";
206  toStr(str, holder.BufferSize);
207 
208  str += ", MessageInitializer=";
209  str += MessageInitializer::name();
210 
211  str += ", ";
212  toStr(str, *holder.header());
213 
214  str += ", ";
215  toStr(str, holder.message());
216 
217  str += "]";
218 }
219 
220 /// \private
221 ONIXS_ILINK3_CONST_OR_CONSTEXPR char magicDebugValue = 0x5A;
222 
223 /// Default maximum number of repeating group items.
225 
226 /**
227  * Contains the SimpleOpenFramingHeader, the SBE message, and the data buffer.
228  */
229 template <
230  typename MessageTypeT,
231  size_t MaxMessageSize =
232  GetMaxMessageSize<typename HeldAdapter<MessageTypeT>::SbeType, DefaultMaxGroupItems>::Size,
233  typename MessageInitializer = FieldsInitPolicy>
234 class MessageHolder
235 {
236  typedef typename HeldAdapter<MessageTypeT>::SbeType SbeType;
237 
238  ONIXS_ILINK3_STATIC_ASSERT_MSG(
239  (MaxMessageSize > sizeof(MessageHeader)),
240  "MaxMessageSize template parameter is too small");
241 
242  ONIXS_ILINK3_STATIC_ASSERT_MSG(
243  (MaxMessageSize >= GetMinMessageSize<SbeType>::Size),
244  "The buffer can not fit the message");
245 
246  ONIXS_ILINK3_STATIC_ASSERT_MSG(
247  (MaxMessageSize <= MaxILink3MessageSize),
248  "The buffer is too large.");
249 
250 public:
251  /// Message type.
252  typedef HeldAdapter<MessageTypeT> MessageType;
253 
254  /// Size of the data buffer.
255  enum
256  {
257  BufferSize = MaxMessageSize + sizeof(SimpleOpenFramingHeader)
258  };
259 
260  explicit MessageHolder(SchemaVersion version = SbeType::Schema::Version)
261  {
262 #ifdef ONIXS_ILINK3_MEMCHECK_DEBUG
263  std::memset(buffer_, magicDebugValue, BufferSize);
264 #endif
265  messageSize(0);
266 
267  message_ = MessageInitializer::template createMessage<MessageType>(
268  buffer_ + sizeof(SimpleOpenFramingHeader), MaxMessageSize, version);
269  }
270 
272  {
273  copyFrom(r);
274  }
275 
277  {
278  copyFrom(r);
279  return *this;
280  }
281 
282  /// \return the buffer.
283  const unsigned char* buffer() const
284  {
285  return buffer_;
286  }
287 
288  /// \return the used size of the buffer.
290  {
291  return header()->size();
292  }
293 
294  /// \return the SBE message.
295  MessageType& message()
296  {
297  return message_;
298  }
299 
300  /// \return the SBE message.
301  const MessageType& message() const
302  {
303  return message_;
304  }
305 
306  /// \return the SBE message size
308  {
309  return bufferSize() - sizeof(SimpleOpenFramingHeader);
310  }
311 
312  MessageType* operator->()
313  {
314  return &message();
315  }
316 
317  const MessageType* operator->() const
318  {
319  return &message();
320  }
321 
322  /// \return Simple Open Framing Header
324  {
325  return reinterpret_cast<const SimpleOpenFramingHeader*>(buffer_);
326  }
327 
328  /// \return Simple Open Framing Header
330  {
331  return reinterpret_cast<SimpleOpenFramingHeader*>(buffer_);
332  }
333 
334  /// Calculates the binary size of the message and updates
335  /// the Simple Open Framing Header accordingly.
336  ///
337  /// \return SBE message size
340  {
341  const MessageSize calculatedMessageSize =
342  message().calculateBinarySize();
343 
344  assert(calculatedMessageSize <= MaxMessageSize);
345 
346  assert(
347  calculatedMessageSize >=
348  SbeType::blockLength(message().version()) +
349  MessageHeaderBuilder::Size +
350  SbeType::getMinimalVariableFieldsSize(message().version()));
351 
352  messageSize(calculatedMessageSize);
353  return calculatedMessageSize;
354  }
355 
356  /// \return a human-readable presentation.
358  std::string toString() const
359  {
360  return toStr(*this);
361  }
362 
363 private:
364  void messageSize(UInt16 size)
365  {
366  header()->setup(
367  size + sizeof(SimpleOpenFramingHeader));
368  }
369 
370  void copyFrom(const MessageHolder& r)
371  {
372 #ifdef ONIXS_ILINK3_MEMCHECK_DEBUG
373  std::memset(buffer_, magicDebugValue, BufferSize);
374 #endif
375 
376  const size_t sizeToCopy = r.message_.MessageType::calculateBinarySize() + sizeof(SimpleOpenFramingHeader);
377 
378  assert(r.message_.calculateBinarySize() <= MaxMessageSize);
379 
380  std::memcpy(
381  buffer_,
382  r.buffer_,
383  sizeToCopy);
384 
385  message_ =
386  MessageType(
387  buffer_ + sizeof(SimpleOpenFramingHeader),
388  MaxMessageSize,
391  }
392 
393 private:
394  MessageType message_;
395  unsigned char buffer_[BufferSize];
396 };
397 
398 template <
399  template <typename, size_t, typename> class HolderType,
400  typename MsgType,
401  size_t MaxMessageSize,
402  typename MessageInitializer>
403 inline std::string toStr(
404  const HolderType<MsgType, MaxMessageSize, MessageInitializer>& holder)
405 {
406  std::string res;
407  toStr(res, holder);
408  return res;
409 }
410 
411 template <
412  template <typename, size_t, typename> class HolderType,
413  typename MsgType,
414  size_t MaxMessageSize,
415  typename MessageInitializer>
416 std::ostream& operator<<(
417  std::ostream& stream,
418  const HolderType<MsgType, MaxMessageSize, MessageInitializer>& rhs)
419 {
420  return stream << toStr(rhs);
421 }
422 
423 #if ONIXS_ILINK3_COMPILER_CXX_ALIAS_TEMPLATES
424 
425 template <
426  typename MessageTypeT,
427  size_t MaxMessageSize =
428  GetMaxMessageSize<typename HeldAdapter<MessageTypeT>::SbeType, DefaultMaxGroupItems>::Size,
429  typename MessageInitializer = FieldsInitPolicy>
430 using MessageHolders = std::vector<MessageHolder<MessageTypeT, MaxMessageSize, MessageInitializer> >;
431 
432 #endif
433 
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoFieldsInit, SchemaVersion version)
The policy to create messages without initialized optional fields.
Definition: MessageHolder.h:51
#define ONIXS_ILINK3_CONST_OR_CONSTEXPR
Definition: Compiler.h:166
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoInit, SbeMessage::NoCheck) noexcept
Contains the SimpleOpenFramingHeader, the SBE message, and the data buffer.
std::string toStr(const HolderType< MsgType, MaxMessageSize, MessageInitializer > &holder)
HeldAdapter< MessageTypeT > MessageType
Message type.
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoInit)
MessageHeader::Version SchemaVersion
SBE-encoded data version type.
Definition: SchemaTraits.h:30
Template ID and length of message root.
Definition: Composites.h:230
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoInit)
UInt16 UInt16
uInt16.
Definition: Fields.h:264
const MessageType * operator->() const
const SimpleOpenFramingHeader * header() const
MessageSize setHeader() noexcept
Calculates the binary size of the message and updates the Simple Open Framing Header accordingly...
constexpr UInt8 DefaultMaxGroupItems
Default maximum number of repeating group items.
#define ONIXS_ILINK3_MESSAGING_NAMESPACE_END
Definition: ABI.h:144
MessageHolder & operator=(const MessageHolder &r)
const unsigned char * buffer() const
#define ONIXS_ILINK3_FINAL
Definition: Compiler.h:169
UInt16 MessageSize
Message length type.
Definition: Aliases.h:29
std::ostream & operator<<(std::ostream &stream, const HolderType< MsgType, MaxMessageSize, MessageInitializer > &rhs)
constexpr UInt16 MaxILink3MessageSize
Maximum supported message size.
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoFieldsInit, SchemaVersion version)
The policy to create messages with null-initialized optional fields.
Definition: MessageHolder.h:33
#define ONIXS_ILINK3_MESSAGING_NAMESPACE_BEGIN
Definition: ABI.h:140
MessageHolder(SchemaVersion version=SbeType::Schema::Version)
#define ONIXS_ILINK3_NODISCARD
Definition: Compiler.h:173
#define ONIXS_ILINK3_NOTHROW
Definition: Compiler.h:164
const MessageType & message() const
HeldAdapter(void *data, EncodedLength length, SbeMessage::NoInit, SbeMessage::NoCheck) noexcept