OnixS C++ CME MDP Conflated TCP Handler 1.3.6
API Documentation
Loading...
Searching...
No Matches
SbeMessage.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
31
32#include <cassert>
33#include <limits>
34#include <stdexcept>
35
37
39typedef
40MessageHeader::TemplateId MessageTemplateId;
41
43template<typename Message> inline
44void checkBinaryLength(const Message&, MessageSize length, MessageSize minimalRequiredLength)
45{
46 if ONIXS_CONFLATEDTCP_UNLIKELY(length < minimalRequiredLength)
47 throwBinaryBlockIsTooSmall(length, minimalRequiredLength, Message::className());
48}
49
52{
53protected:
54 ~BinaryBlockBase() ONIXS_CONFLATEDTCP_DEFAULT;
55};
56
62template < class Container, class BlockLength >
64{
66 const Container& container() const ONIXS_CONFLATEDTCP_NOTHROW
67 {
68 return *static_cast <const Container*> (this);
69 }
70
71protected:
74
76
78 template < class Value > ONIXS_CONFLATEDTCP_HOTPATH
79 Value ordinary(BlockLength offset) const ONIXS_CONFLATEDTCP_NOTHROW
80 {
81 assert(container().blockLength() >= (offset + size<Value>()) &&
82 "The requested field exceeds provided block boundaries.");
83
84 const void* const location = advanceByBytes(container().block(), offset);
85 return getValue<Value>(location);
86 }
87
92 template <class Value, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
93 bool ordinary(Value& value, BlockLength offset, NullValue null) const ONIXS_CONFLATEDTCP_NOTHROW
94 {
95 value = ordinary<Value>(offset);
96
97 return (null != value);
98 }
99
104 template < class Value, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
105 bool ordinary(Value& value, BlockLength offset, NullValue null, SchemaVersion since) const ONIXS_CONFLATEDTCP_NOTHROW
106 {
107 return (since <= container().version() && ordinary (value, offset, null ) );
108 }
109
111 template < class Enumeration > ONIXS_CONFLATEDTCP_HOTPATH
112 typename Enumeration::Enum enumeration(BlockLength offset) const ONIXS_CONFLATEDTCP_NOTHROW
113 {
114 typedef typename Enumeration::Base Base;
115 typedef typename Enumeration::Enum Enum;
116
117 return static_cast<Enum>(ordinary<Base>(offset));
118 }
119
121 template < class Enumeration, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
122 bool enumeration(typename Enumeration::Enum& value, BlockLength offset, NullValue null) const ONIXS_CONFLATEDTCP_NOTHROW
123 {
124 typedef typename Enumeration::Base Base;
125 typedef typename Enumeration::Enum Enum;
126
127 value = static_cast <Enum>(ordinary<Base>(offset));
128 return null != value;
129 }
130
132 template < class Enumeration, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
133 bool enumeration(typename Enumeration::Enum& value, BlockLength offset, NullValue null, SchemaVersion since) const ONIXS_CONFLATEDTCP_NOTHROW
134 {
135 return (since <= container().version() && enumeration<Enumeration>(value, offset, null) );
136 }
137
139 template < class Value > ONIXS_CONFLATEDTCP_HOTPATH
140 Value decimal(BlockLength offset) const ONIXS_CONFLATEDTCP_NOTHROW
141 {
142 return ordinary<Value>(offset);
143 }
144
149 template < class Value, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
150 bool decimal(Value& value, BlockLength offset, NullValue null) const ONIXS_CONFLATEDTCP_NOTHROW
151 {
152 value = ordinary<Value>(offset);
153 return null != value;
154 }
155
160 template < class Value, class NullValue > ONIXS_CONFLATEDTCP_HOTPATH
161 bool decimal(Value& value, BlockLength offset, NullValue null, SchemaVersion since) const ONIXS_CONFLATEDTCP_NOTHROW
162 {
163 return (since <= container().version() && decimal(value, offset, null));
164 }
165
167 template < BlockLength Length > ONIXS_CONFLATEDTCP_HOTPATH
169 {
170 assert(container().blockLength() >= (offset + Length) && "The requested field exceeds provided block boundaries.");
171
172 const Char* const text = reinterpret_cast <const Char*> (advanceByBytes(container().block(), offset));
173
174 return StrRef(text, strnlen(text, Length));
175 }
176
181 template<BlockLength Length> ONIXS_CONFLATEDTCP_HOTPATH
182 bool fixedStr(StrRef& value, BlockLength offset) const ONIXS_CONFLATEDTCP_NOTHROW
183 {
184 value = fixedStr<Length>(offset);
185 return !value.empty();
186 }
187
192 template<BlockLength Length> ONIXS_CONFLATEDTCP_HOTPATH
193 bool fixedStr(StrRef& value, BlockLength offset, SchemaVersion since) const ONIXS_CONFLATEDTCP_NOTHROW
194 {
195 return (since <= container().version() && fixedStr<Length>(value, offset));
196 }
197};
198
203template <class Container, class BlockLength >
205{
206public:
209 {
210 return *static_cast<Container*>(this);
211 }
212
214 template<class FieldValue> ONIXS_CONFLATEDTCP_HOTPATH
215 void setOrdinary(BlockLength offset, FieldValue value) ONIXS_CONFLATEDTCP_NOTHROW
216 {
217 assert(container().blockLength() >= (offset + size<FieldValue>()) && "The requested field exceeds provided block boundaries.");
218
219 void* const fieldPos = advanceByBytes(container().block(), offset);
220 setValue(fieldPos, value);
221 }
222
224 template<class FieldValue> ONIXS_CONFLATEDTCP_HOTPATH
225 void setOrdinary(BlockLength offset, FieldValue value, SchemaVersion since)
226 {
227 if ONIXS_CONFLATEDTCP_UNLIKELY(since > container().version())
228 throwDisallowedField();
229
230 setOrdinary(offset, value);
231 }
232
234 template<class Enumeration> ONIXS_CONFLATEDTCP_HOTPATH
235 void setEnumeration(BlockLength offset, typename Enumeration::Enum value) ONIXS_CONFLATEDTCP_NOTHROW
236 {
237 typedef typename Enumeration::Base Base;
238 setOrdinary<Base>(offset, static_cast<Base>(value));
239 }
240
242 template<class Enumeration> ONIXS_CONFLATEDTCP_HOTPATH
243 void setEnumeration(BlockLength offset, typename Enumeration::Enum value, SchemaVersion since)
244 {
245 typedef typename Enumeration::Base Base;
246 setOrdinary(offset, static_cast<Base>(value), since);
247 }
248
250 template<BlockLength Size> ONIXS_CONFLATEDTCP_HOTPATH
251 void setFixedStr(BlockLength offset, StrRef value) ONIXS_CONFLATEDTCP_NOTHROW
252 {
253 assert(container().blockLength() >= (offset + Size) && "The requested field exceeds provided block boundaries.");
254 assert(value.size() <= Size && "The string is truncated.");
255
256 void* const fieldPos = advanceByBytes(container().block(), offset);
257 const size_t sizeToCopy = (std::min)(Size, static_cast<BlockLength>(value.size()));
258
259 if(sizeToCopy > 0)
260 std::memcpy(fieldPos, value.data(), sizeToCopy);
261
262 std::memset(advanceByBytes(fieldPos, sizeToCopy), 0, Size - sizeToCopy);
263 }
264
266 template<BlockLength Size> ONIXS_CONFLATEDTCP_HOTPATH
267 void setFixedStr(BlockLength offset, StrRef value, SchemaVersion since)
268 {
269 if ONIXS_CONFLATEDTCP_UNLIKELY(since > container().version())
270 throwDisallowedField();
271
272 setFixedStr<Size>(offset, value);
273 }
274
275 protected:
278
280};
281
283template <class BodySizeType>
285{
286public:
288 typedef BodySizeType BlockLength;
289
293 , size_(0)
294 , version_(0)
295 {
296 }
297
301 : encoded_(encoded)
302 , size_(size)
303 , version_(version)
304 {
305 assert(encoded);
306 }
307
310 {
311 return (encoded_ != ONIXS_CONFLATEDTCP_NULLPTR);
312 }
313
316 {
317 assert(valid());
318
319 return encoded_;
320 }
321
324 {
325 assert(valid());
326
327 return encoded_;
328 }
329
332 {
333 assert(valid());
334
335 return encoded_;
336 }
337
340 {
341 assert(valid());
342
343 return encoded_;
344 }
345
348 {
349 return size_;
350 }
351
354 {
355 return version_;
356 }
357
358 private:
359 void* encoded_;
360 BodySizeType size_;
361 SchemaVersion version_;
362};
363
365template <class EntryType, class BlockLength, class NumInGroup, class Length >
367{
368public:
370 typedef Length EncodedLength;
371
373 typedef EntryType Entry;
374
376 typedef NumInGroup Size;
377
380 {
381 public:
382 typedef EntryType Entry;
384
385 typedef Entry* pointer;
386 typedef Entry& reference;
387
388 typedef ptrdiff_t difference_type;
389
390 typedef std::random_access_iterator_tag iterator_category;
391
395 , size_(0)
396 , version_(0)
397 {
398 }
399
403 : entry_(entry)
404 , size_(size)
405 , version_(version)
406 {
407 assert(valid());
408 }
409
412 {
413 return (entry_ != ONIXS_CONFLATEDTCP_NULLPTR);
414 }
415
418 Entry get() const
419 {
420 assert(valid());
421
422 return Entry(entry_, size_, version_);
423 }
424
426 Entry operator *() const
427 {
428 return get();
429 }
430
432 bool operator == (const Iterator& other) const ONIXS_CONFLATEDTCP_NOTHROW
433 {
434 return entry_ == other.entry_;
435 }
436
438 bool operator !=(const Iterator& other) const ONIXS_CONFLATEDTCP_NOTHROW
439 {
440 return entry_ != other.entry_;
441 }
442
444 bool operator < (const Iterator& other) const ONIXS_CONFLATEDTCP_NOTHROW
445 {
446 return entry_ < other.entry_;
447 }
448
450 bool operator > (const Iterator& other) const ONIXS_CONFLATEDTCP_NOTHROW
451 {
452 return entry_ > other.entry_;
453 }
454
456 Iterator& operator ++()
457 {
458 assert(valid());
459
460 entry_ = advanceByBytes(entry_, size_);
461
462 return *this;
463 }
464
466 Iterator& operator --()
467 {
468 assert(valid());
469
470 entry_ = advanceBackByBytes(entry_, size_);
471
472 return *this;
473 }
474
477 Iterator operator +(difference_type distance) const
478 {
479 assert(valid());
480
481 return Iterator(advanceByBytes(entry_, distance * size_), size_, version_);
482 }
483
486 Iterator operator - (difference_type distance) const
487 {
488 assert(valid());
489
490 return Iterator(advanceBackByBytes(entry_, distance * size_), size_, version_);
491 }
492
493 private:
494 void* entry_;
495 Size size_;
496 SchemaVersion version_;
497 };
498
502 , blockLength_(0)
503 , size_(0)
504 , version_(0)
505 {
506 }
507
509 SbeGroupEntries(void* encoded, BlockLength blockLength, Size groupSize, SchemaVersion version) ONIXS_CONFLATEDTCP_NOTHROW
510 : encoded_(encoded)
511 , blockLength_(blockLength)
512 , size_(groupSize)
513 , version_(version)
514 {
515 assert(encoded_);
516 assert(blockLength > 0);
517 assert(version != 0);
518 }
519
522 {
523 return (ONIXS_CONFLATEDTCP_NULLPTR != encoded_);
524 }
525
528 {
529 return (0 == size_);
530 }
531
534 {
535 return size_;
536 }
537
539 Iterator begin() const
540 {
541 return Iterator(encoded(), blockLength_, version_);
542 }
543
545 Iterator end() const
546 {
547 return Iterator(advanceByBytes(encoded(), encodedLength()), blockLength_, version_);
548 }
549
553 Entry operator [](Size index) const
554 {
555 assert(index < size_);
556 assert(encoded_);
557
558 return Entry(advanceByBytes(encoded_, static_cast<ptrdiff_t>(index) * blockLength_), blockLength_, version_);
559 }
560
563 {
564 return encoded_;
565 }
566
569 {
570 return (static_cast<EncodedLength>(blockLength_) * static_cast<EncodedLength>(size_) );
571 }
572
574 template<class OtherEntry, class OtherBlockLength, class OtherNumInGroup, class OtherLength >
576 : encoded_(other.encoded_)
577 , blockLength_(other.blockLength_)
578 , size_(other.size_)
579 , version_(other.version_)
580 {
581 // Dimension types may vary for the different instantiations of the template.
582 // Therefore, truncation of the dimensions must be avoided.
583
584 assert(blockLength_ == other.blockLength_);
585 assert(size_ == other.size_);
586 }
587
588 template <class OtherEntry, class OtherBlockLength, class OtherNumInGroup, class OtherLength>
589 SbeGroupEntries& operator = (const SbeGroupEntries <OtherEntry, OtherBlockLength, OtherNumInGroup, OtherLength>& other) ONIXS_CONFLATEDTCP_NOTHROW
590 {
591 encoded_ = other.encoded_;
592
593 blockLength_ = other.blockLength_;
594
595 assert(blockLength_ == other.blockLength_);
596
597 size_ = other.size_;
598
599 assert(size_ == other.size_);
600
601 version_ = other.version_;
602
603 return *this;
604 }
605
606private:
607 // Allows coping and cloning for different instantiations.
608 template <class OtherEntry, class OtherBlockLength, class OtherNumInGroup, class OtherLength> friend class SbeGroupEntries;
609
610 void* encoded_;
611 BlockLength blockLength_;
612 NumInGroup size_;
613 SchemaVersion version_;
614};
615
617template < class EntryType, class DimensionType, class GroupSizeType >
619{
620public:
622 typedef DimensionType Dimension;
623
625 typedef GroupSizeType BinarySize;
626
629
631 typedef typename DimensionType::BlockLength EntrySize;
632
634 typedef SbeGroupEntries <EntryType, typename Dimension::BlockLength, typename Dimension::NumInGroup, GroupSizeType > Entries;
635
637 typedef typename Entries::Iterator Iterator;
638
640 typedef typename Entries::Entry Entry;
641
643 typedef typename Entries::Size Size;
644
650 , version_(0)
651 {
652 }
653
657 : header_(static_cast <Dimension*>(data))
658 , entries_(advanceByBytes(data, Dimension::Size))
659 , version_(version)
660 {
661 assert(header_);
662 assert(entries_);
663 assert(size >= Dimension::Size);
664
665 assert(valid());
666 }
667
670 {
671 return (entries_ != ONIXS_CONFLATEDTCP_NULLPTR);
672 }
673
675 bool empty() const
677 {
678 assert(valid());
679
680 return 0 == size();
681 }
682
686 {
687 assert(valid());
688 assert(header_);
689
690 const Dimension* const group = static_cast<const Dimension*>(header_);
691
692 return group->numInGroup();
693 }
694
698 {
699 assert(valid());
700
701 return Iterator(entries_, numericCast<Size>(entrySize()), version_);
702 }
703
707 {
708 assert(valid());
709
710 return Iterator(advanceByBytes(binary(), binarySize()), numericCast<Size>(entrySize()), version_);
711 }
712
717 Entry operator [](Size index) const
718 {
719 assert(valid());
720 assert(index < size());
721
722 return Entry(advanceByBytes(entries_, static_cast<ptrdiff_t>(index) * entrySize()), entrySize(), version_);
723 }
724
728 {
729 assert(valid());
730 assert(header_);
731
732 return Entries (entries_, header_->blockLength(), header_->numInGroup(), version_);
733 }
734
737 {
738 return header_;
739 }
740
743 {
744 return advanceByBytes(toByteBlock(encoded()), binarySize());
745 }
746
750 {
751 return header_;
752 }
753
757 {
758 return Dimension::Size + (static_cast<BinarySize>(entrySize()) * static_cast<BinarySize>(size()));
759 }
760
764 {
765 assert(valid());
766 assert(header_);
767
768 Dimension* const group = static_cast<Dimension*>(header_);
769 return group->blockLength();
770 }
771
772private:
774 void init(EntrySize entrySize) ONIXS_CONFLATEDTCP_NOTHROW
775 {
776 assert(valid());
777 assert(header_);
778
779 Dimension* const group = static_cast<Dimension*>(header_);
780 group->setBlockLength(entrySize);
781 group->setNumInGroup(0);
782 }
783
785 Size allocate(Size entryCount, const void* messageTail, const void* blockEnd)
786 {
787 assert(valid());
788 assert(blockEnd);
789 assert(messageTail);
790
791 Dimension* const group = static_cast<Dimension*>(header_);
792
793 const EntrySize entrySize = group->blockLength();
794
795 if ONIXS_CONFLATEDTCP_UNLIKELY(
796 entrySize < EntryType::blockLength(version_))
797 {
798 throwBadBinaryBlock();
799 }
800
801 const Size oldEntryCount = group->numInGroup();
802
803 if(oldEntryCount == entryCount)
804 return entryCount;
805
806 const ptrdiff_t memShift =
807 (entryCount - oldEntryCount) * static_cast<ptrdiff_t>(entrySize);
808
809 const void* const newMessageTail =
810 advanceByBytes(messageTail, memShift);
811
812 if ONIXS_CONFLATEDTCP_UNLIKELY(byteDistance(blockEnd, newMessageTail) < 0)
813 throwNotEnoughSpace();
814
815 const void* const oldEndOfGroup =
816 advanceByBytes(entries_, static_cast<ptrdiff_t>(entrySize) * oldEntryCount);
817
818 void* const newEndGroup =
819 advanceByBytes(entries_, static_cast<ptrdiff_t>(entrySize) * entryCount);
820
821 std::memmove(
822 newEndGroup,
823 oldEndOfGroup,
824 byteDistance(messageTail, oldEndOfGroup));
825
826 group->setNumInGroup(entryCount);
827
828 return oldEntryCount;
829 }
830
833 void setup(Size entryCount, const void* messageTail, const void* blockEnd)
834 {
835 assert(valid());
836 assert(blockEnd);
837 assert(messageTail);
838
839 const Size oldEntryCount = allocate(entryCount, messageTail, blockEnd);
840
841 for(Size index = oldEntryCount; index < entryCount; ++index)
842 (*this)[index].resetVariableFields();
843 }
844
847 void construct(Size entryCount, const void* messageTail, const void* blockEnd)
848 {
849 assert(valid());
850 assert(blockEnd);
851 assert(messageTail);
852
853 const Size oldEntryCount = allocate(entryCount, messageTail, blockEnd);
854
855 for(Size index = oldEntryCount; index < entryCount; ++index)
856 (*this)[index].reset();
857 }
858
859private:
860 Dimension* header_;
861 void* entries_;
862 SchemaVersion version_;
863
864 friend class SbeMessage;
865};
866
868template < class BinarySize >
870{
871public:
875 : binary_(binary)
876 , size_(size)
877 , version_(version)
878 {
879 }
880
883 {
884 return (0 == size_);
885 }
886
888 template<class BinaryVariableLengthFieldType>
889 BinaryVariableLengthFieldType& head() const ONIXS_CONFLATEDTCP_NOTHROW
890 {
891 return *static_cast<BinaryVariableLengthFieldType*>(binary_);
892 }
893
895 template<class BinaryVariableLengthFieldType> ONIXS_CONFLATEDTCP_HOTPATH
897 {
898 assert(!empty());
899
900 const BinarySize headSize = head<BinaryVariableLengthFieldType>().binarySize();
901
902 assert(headSize <= size_);
903
904 return SbeVariableLengthFieldList(advanceByBytes( binary_, headSize), size_ - headSize, version_);
905 }
906
910 template<class BinaryVariableLengthFieldType> ONIXS_CONFLATEDTCP_HOTPATH
912 {
913 if ONIXS_CONFLATEDTCP_UNLIKELY(empty() || (size_ < BinaryVariableLengthFieldType::Size))
914 {
915 throwBadBinaryBlock();
916 }
917
918 const BinarySize headSize = head<BinaryVariableLengthFieldType>().binarySize();
919
920 if ONIXS_CONFLATEDTCP_UNLIKELY(headSize > size_)
921 {
922 throwBadBinaryBlock();
923 }
924
925 return SbeVariableLengthFieldList(advanceByBytes(binary_, headSize), size_ - headSize, version_);
926 }
927
928 private:
929 void* binary_;
930 BinarySize size_;
931 SchemaVersion version_;
932
933};
934
936template <class BinarySize>
938{
939public:
942 SbeGroupList(void* binary, BinarySize size, SchemaVersion version) ONIXS_CONFLATEDTCP_NOTHROW
943 : binary_(binary)
944 , size_(size)
945 , version_(version)
946 {
947 }
948
951 {
952 return (0 == size_);
953 }
954
956 template<class Group> ONIXS_CONFLATEDTCP_HOTPATH
958 {
959 assert(!empty());
960
961 return Group(binary_, size_, version_);
962 }
963
965 template<class Group> ONIXS_CONFLATEDTCP_HOTPATH
967 {
968 assert(!empty());
969
970 const BinarySize headSize = head<Group>().binarySize();
971
972 assert(headSize <= size_);
973
974 return SbeGroupList(advanceByBytes(binary_, headSize), size_ - headSize, version_);
975 }
976
978 template <class Group> ONIXS_CONFLATEDTCP_HOTPATH
980 {
981 assert(!empty());
982
983 const BinarySize headSize = head<Group>().binarySize();
984
985 assert(headSize <= size_);
986
987 return SbeVariableLengthFieldList<BinarySize>(advanceByBytes(binary_, headSize), size_ - headSize, version_);
988 }
989
993 template<class Group> ONIXS_CONFLATEDTCP_HOTPATH
995 {
996 const BinarySize headSize = checkHead<Group>();
997
998 return SbeGroupList(advanceByBytes(binary_, headSize), size_ - headSize, version_);
999 }
1000
1004 template <class Group> ONIXS_CONFLATEDTCP_HOTPATH
1006 {
1007 const BinarySize headSize = checkHead<Group>();
1008
1009 return SbeVariableLengthFieldList<BinarySize>(advanceByBytes(binary_, headSize), size_ - headSize, version_);
1010 }
1011
1012private:
1013 template<class Group>
1014 BinarySize checkHead() const
1015 {
1016 if ONIXS_CONFLATEDTCP_UNLIKELY(size_ < Group::Dimension::Size)
1017 {
1018 throwBadBinaryBlock();
1019 }
1020
1021 const Group group = head<Group>();
1022
1023 const BinarySize headSize = group.binarySize();
1024
1025 if ONIXS_CONFLATEDTCP_UNLIKELY(headSize > size_)
1026 {
1027 throwBadBinaryBlock();
1028 }
1029
1030 if(!group.empty())
1031 {
1032 const BinarySize entrySize = group.entrySize();
1033 const BinarySize expectedEntrySize = Group::Entry::blockLength(version_);
1034
1035 if ONIXS_CONFLATEDTCP_UNLIKELY(entrySize < expectedEntrySize)
1036 {
1037 throwBadBinaryBlock();
1038 }
1039 }
1040
1041 return headSize;
1042 }
1043
1044 void* binary_;
1045 BinarySize size_;
1046 SchemaVersion version_;
1047};
1048
1050template<typename Traits>
1052{
1053 Int16 tmp = version;
1054 if ONIXS_CONFLATEDTCP_UNLIKELY (tmp < Traits::MinimalVersion)
1055 {
1056 throwBadMessageVersion(version, Traits::MinimalVersion);
1057 }
1058}
1059
1061template<typename Traits>
1063{
1064 checkVersion<Traits>(version);
1065
1066 if ONIXS_CONFLATEDTCP_UNLIKELY(version < since)
1067 {
1068 throwBadMessageVersion(version, since);
1069 }
1070}
1071
1073template<typename Traits>
1075{
1076 if ONIXS_CONFLATEDTCP_UNLIKELY(id != Traits::Id)
1077 {
1078 throwBadSchemaId(Traits::Id, id);
1079 }
1080}
1081
1083template<typename Traits>
1085{
1087 checkVersion<Traits>(version);
1088}
1089
1092{
1093public:
1096 struct NoInit{};
1097 struct NoCheck{};
1098
1101
1104
1108 , size_(0)
1109 {
1110 }
1111
1115 : header_(static_cast<MessageHeader*>(data))
1116 , size_(size)
1117 {
1118 assert(data);
1119 assert(size <= MaxConflatedTcpMessageSize);
1120
1121 if ONIXS_CONFLATEDTCP_UNLIKELY(size < MessageHeader::Size)
1122 throwBinaryBlockIsTooSmall(size, MessageHeader::Size);
1123
1124 this->version(version);
1125 }
1126
1129 SbeMessage(void* data, MessageSize size)
1130 : header_(static_cast<MessageHeader*>(data))
1131 , size_(size)
1132 {
1133 assert(data);
1134 assert(size <= MaxConflatedTcpMessageSize);
1135
1136 if ONIXS_CONFLATEDTCP_UNLIKELY(size < MessageHeader::Size)
1137 throwBinaryBlockIsTooSmall(size, MessageHeader::Size);
1138
1139 // Now it is safe to read header_.
1140 if ONIXS_CONFLATEDTCP_UNLIKELY(size < (MessageHeader::Size + header_->blockLength()))
1141 throwBinaryBlockIsTooSmall(size, MessageHeader::Size + header_->blockLength());
1142 }
1143
1149 : header_(static_cast<MessageHeader*>(data))
1150 , size_(size)
1151 {
1152 assert(data);
1153 assert(size <= MaxConflatedTcpMessageSize);
1154
1155 assert(size >= MessageHeader::Size);
1156 assert(size >= MessageHeader::Size + header_->blockLength());
1157 }
1158
1161 {
1162 *this = SbeMessage();
1163 assert(!valid());
1164 }
1165
1168 {
1169 return (ONIXS_CONFLATEDTCP_NULLPTR != header_);
1170 }
1171
1174 {
1175 assert(valid());
1176
1177 return header_->templateId();
1178 }
1179
1182 {
1183 assert(valid());
1184
1185 return header_->version();
1186 }
1187
1190 {
1191 assert(valid());
1192
1193 return header_->schemaId();
1194 }
1195
1198 {
1199 assert(valid());
1200
1201 return header_;
1202 }
1203
1206 {
1207 assert(valid());
1208
1209 return header_;
1210 }
1211
1212 // \return the end of the memory block.
1214 {
1215 assert(valid());
1216
1217 return advanceByBytes(header_, size_);
1218 }
1219
1220 // \return the end of the memory block.
1222 {
1223 assert(valid());
1224
1225 return advanceByBytes(header_, size_);
1226 }
1227
1230 {
1231 return size_;
1232 }
1233
1236 {
1237 assert(valid());
1238
1239 return advanceByBytes(header_, MessageHeader::Size);
1240 }
1241
1244 {
1245 assert(valid());
1246
1247 return header_->blockLength();
1248 }
1249
1252 {
1253 assert(valid());
1254
1255 return advanceByBytes(header_, MessageHeader::Size);
1256 }
1257
1260 {
1261 assert(valid());
1262
1263 return advanceByBytes(header_, MessageHeader::Size);
1264 }
1265
1266protected:
1269
1272 {
1273 assert(valid());
1274
1275 header_->setVersion(version);
1276
1277 return *this;
1278 }
1279
1283 {
1284 assert(header_);
1285
1286 void* list = advanceByBytes<void>(body(), blockLength());
1287
1288 const MessageSize listSize = size_ - MessageHeader::Size - header_->blockLength();
1289
1290 return GroupList(list, listSize, header_->version());
1291 }
1292
1296 {
1297 assert(header_);
1298
1299 const void* list = advanceByBytes(block(), blockLength());
1300
1301 const MessageSize listSize = size_ - MessageHeader::Size - header_->blockLength();
1302
1303 return GroupList(const_cast<void*>(list), listSize, header_->version());
1304 }
1305
1307 template<typename Group>
1309 void initGroup(Group& group, typename Group::EntrySize entrySize) ONIXS_CONFLATEDTCP_NOTHROW
1310 {
1311 assert(group.valid());
1312 group.init(entrySize);
1313 }
1314
1316 template<typename Group>
1318 void setupGroup(Group& group, typename Group::Size entryCount, const void* messageTail)
1319 {
1320 assert(messageTail);
1321 assert(group.valid());
1322 group.setup(entryCount, messageTail, blockEnd());
1323 }
1324
1326 template<typename Group>
1328 void constructGroup(Group& group, typename Group::Size entryCount, const void* messageTail)
1329 {
1330 assert(messageTail);
1331 assert(group.valid());
1332 group.construct(entryCount, messageTail, blockEnd());
1333 }
1334
1337
1341 {
1342 assert(header_);
1343
1344 void* list = advanceByBytes<void>(body(), blockLength());
1345
1346 const MessageSize listSize = size_ - MessageHeader::Size - header_->blockLength();
1347
1348 return VariableLengthFieldList(list, listSize, header_->version());
1349 }
1350
1354 {
1355 assert(header_);
1356
1357 const void* list = advanceByBytes(block(), blockLength());
1358
1359 const MessageSize listSize = size_ - MessageHeader::Size - header_->blockLength();
1360
1361 return VariableLengthFieldList(const_cast<void*>(list), listSize, header_->version());
1362 }
1363
1366 {
1367 assert(header_);
1368
1369 header_->setTemplateId(value);
1370 header_->setBlockLength(blockLength);
1371 header_->setSchemaId(id);
1372 }
1373
1377 {
1378 const BlockLength encodedBlockLength = container().blockLength();
1379
1380 assert(encodedBlockLength >= offset);
1381
1382 const size_t paddingLength = encodedBlockLength - offset;
1383 std::memset(advanceByBytes(container().block(), offset), 0, paddingLength);
1384 }
1385
1387 void init(
1389 MessageHeader::BlockLength minimalBlockLength,
1391 SchemaId id)
1392 {
1393 assert(header_);
1394 assert(blockLength >= minimalBlockLength);
1395
1396 header_->setTemplateId(value);
1397 header_->setBlockLength(blockLength);
1398 header_->setSchemaId(id);
1399
1400 zeroPaddingBytes(minimalBlockLength);
1401 }
1402
1405 {
1406 assert(tail);
1407
1408 const ptrdiff_t distance = byteDistance(tail, binary());
1409
1410 assert(distance > 0);
1411
1412 assert(distance <= (std::numeric_limits<MessageSize>::max)());
1413
1414 const MessageSize size = static_cast<MessageSize>(distance);
1415
1416 assert(size <= size_);
1417
1418 return size;
1419 }
1420
1422 template<class Callable, class Owner>
1423 void setVariableLengthField(Callable callable, StrRef value, Owner& owner)
1424 {
1425 setVarDataField(callable(owner), value, owner.tail());
1426 }
1427
1429 template<class Callable, class Owner>
1430 void setVariableLengthField(Callable callable, StrRef value, SchemaVersion since, Owner& owner)
1431 {
1432 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1433 throwDisallowedField();
1434
1435 setVariableLengthField(callable, value, owner);
1436 }
1437
1439 template<class Callable, class Owner>
1440 StrRef getVariableLengthField(Callable callable, const Owner& owner) const ONIXS_CONFLATEDTCP_NOTHROW
1441 {
1442 ONIXS_CONFLATEDTCP_CHECK_NOTHROW(callable(owner));
1443 return callable(owner).varData();
1444 }
1445
1447 template<class Callable, class Owner>
1448 StrRef getVariableLengthField(Callable callable, SchemaVersion since, Owner& owner) const ONIXS_CONFLATEDTCP_NOTHROW
1449 {
1450 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1451 return StrRef();
1452
1453 return getVariableLengthField(callable, owner);
1454 }
1455
1457 template<class Callable, class Owner>
1458 void setVariableLengthFieldToNull(Callable callable, Owner& owner) ONIXS_CONFLATEDTCP_NOTHROW
1459 {
1460 ONIXS_CONFLATEDTCP_CHECK_NOTHROW(callable(owner));
1461 callable(owner).length(0);
1462 }
1463
1465 template<class Group, class Callable, class Owner>
1466 void resetGroup(Callable callable, Owner& owner) ONIXS_CONFLATEDTCP_NOTHROW
1467 {
1468 const typename Group::EntrySize entrySize = Group::Entry::blockLength(version());
1469
1470 Group grp = callable(owner);
1471
1472 initGroup(grp, entrySize);
1473 }
1474
1476 template<class Callable, class Owner>
1477 void setVariableLengthFieldToNull(Callable callable, SchemaVersion since, Owner& owner) ONIXS_CONFLATEDTCP_NOTHROW
1478 {
1479 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1480 return;
1481
1482 setVariableLengthFieldToNull(callable, owner);
1483 }
1484
1486 template<class Group, class Callable, class Owner>
1487 void resetGroup(Callable callable, SchemaVersion since, Owner& owner)
1488 {
1489 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1490 return;
1491
1492 resetGroup<Group>(callable, owner);
1493 }
1494
1496 template<class Group, class Callable, class Owner>
1497 Group getGroup(Callable callable, Owner& owner) const ONIXS_CONFLATEDTCP_NOTHROW
1498 {
1499 return callable(owner);
1500 }
1501
1503 template<class Group, class Callable, class Owner>
1504 Group getGroup(Callable callable, SchemaVersion since, Owner& owner) const ONIXS_CONFLATEDTCP_NOTHROW
1505 {
1506 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1507 return Group();
1508
1509 return getGroup<Group>(callable, owner);
1510 }
1511
1513 template<class Group, class Callable, class Owner>
1514 Group constructGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner& owner)
1515 {
1516 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1517 return Group();
1518
1519 return constructGroup<Group>(callable, length, owner);
1520 }
1521
1523 template<class Group, class Callable, class Owner>
1524 Group constructGroup(Callable callable, typename Group::Size length, Owner& owner)
1525 {
1526 Group group = callable(owner);
1527
1528 constructGroup(group, length, owner.tail());
1529
1530 return group;
1531 }
1532
1534 template<class Group, class Callable, class Owner>
1535 Group setupGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner& owner)
1536 {
1537 if ONIXS_CONFLATEDTCP_UNLIKELY(since > version())
1538 return Group();
1539
1540 return setupGroup<Group>(callable, length, owner);
1541 }
1542
1544 template<class Group, class Callable, class Owner>
1545 Group setupGroup(Callable callable, typename Group::Size length, Owner& owner)
1546 {
1547 Group group = callable(owner);
1548
1549 setupGroup(group, length, owner.tail());
1550
1551 return group;
1552 }
1553
1563
1564private:
1565 MessageHeader* header_;
1566 MessageSize size_;
1567};
1568
#define ONIXS_CONFLATEDTCP_LTWT_EXPORTED
Definition ABI.h:92
#define ONIXS_CONFLATEDTCP_LTWT_CLASS
Definition ABI.h:84
#define ONIXS_CONFLATEDTCP_MESSAGING_NAMESPACE_BEGIN
Definition ABI.h:140
#define ONIXS_CONFLATEDTCP_MESSAGING_NAMESPACE_END
Definition ABI.h:143
#define ONIXS_CONFLATEDTCP_UNUSED
Definition Compiler.h:201
#define ONIXS_CONFLATEDTCP_CONSTEXPR
Definition Compiler.h:179
#define ONIXS_CONFLATEDTCP_NULLPTR
Definition Compiler.h:182
#define ONIXS_CONFLATEDTCP_NOTHROW
Definition Compiler.h:176
#define ONIXS_CONFLATEDTCP_NODISCARD
Definition Compiler.h:185
#define ONIXS_CONFLATEDTCP_HOTPATH
Definition Compiler.h:187
#define ONIXS_CONFLATEDTCP_DEFAULT
Definition Compiler.h:202
bool decimal(Value &value, BlockLength offset, NullValue null) const noexcept
Definition SbeMessage.h:150
bool fixedStr(StrRef &value, BlockLength offset) const noexcept
Provides access to an optional string field value.
Definition SbeMessage.h:182
Value ordinary(BlockLength offset) const noexcept
Definition SbeMessage.h:79
bool fixedStr(StrRef &value, BlockLength offset, SchemaVersion since) const noexcept
Provides access to an optional string field value.
Definition SbeMessage.h:193
bool ordinary(Value &value, BlockLength offset, NullValue null) const noexcept
Provides access to an optional field value.
Definition SbeMessage.h:93
bool decimal(Value &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
Definition SbeMessage.h:161
Value decimal(BlockLength offset) const noexcept
Definition SbeMessage.h:140
Enumeration::Enum enumeration(BlockLength offset) const noexcept
Definition SbeMessage.h:112
bool enumeration(typename Enumeration::Enum &value, BlockLength offset, NullValue null) const noexcept
Provides access to an optional field value.
Definition SbeMessage.h:122
BinaryBlock()=default
Initializes a blank instance.
bool ordinary(Value &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
Provides access to an optional field value.
Definition SbeMessage.h:105
StrRef fixedStr(BlockLength offset) const noexcept
Provides access to a string field value.
Definition SbeMessage.h:168
bool enumeration(typename Enumeration::Enum &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
Provides access to an optional field value.
Definition SbeMessage.h:133
NumInGroup numInGroup() const noexcept
Definition Composites.h:63
BlockLength blockLength() const noexcept
Definition Composites.h:48
Template ID and length of message root.
Definition Composites.h:145
UInt16 BlockLength
Type alias for the BlockLength.
Definition Composites.h:151
UInt16 TemplateId
Type alias for the TemplateId.
Definition Composites.h:154
SbeFields()=default
Initializes a blank instance.
void setFixedStr(BlockLength offset, StrRef value) noexcept
Sets the field value.
Definition SbeMessage.h:251
void setOrdinary(BlockLength offset, FieldValue value, SchemaVersion since)
Sets the field value.
Definition SbeMessage.h:225
void setEnumeration(BlockLength offset, typename Enumeration::Enum value, SchemaVersion since)
Sets the field value.
Definition SbeMessage.h:243
void setEnumeration(BlockLength offset, typename Enumeration::Enum value) noexcept
Sets the field value.
Definition SbeMessage.h:235
void setOrdinary(BlockLength offset, FieldValue value) noexcept
Sets the field value.
Definition SbeMessage.h:215
void setFixedStr(BlockLength offset, StrRef value, SchemaVersion since)
Sets the field value.
Definition SbeMessage.h:267
An iterator over SBE-encoded group entries.
Definition SbeMessage.h:380
Iterator(void *entry, Size size, SchemaVersion version) noexcept
Initializes the instance to the given repeating group.
Definition SbeMessage.h:402
Iterator() noexcept
Initializes the instance that refers to nothing.
Definition SbeMessage.h:393
SbeGroupEntries() noexcept
Initializes a blank instance referencing to nothing.
Definition SbeMessage.h:500
SbeGroupEntries(void *encoded, BlockLength blockLength, Size groupSize, SchemaVersion version) noexcept
Initializes the instance referencing to data.
Definition SbeMessage.h:509
EntryType Entry
The type of the repeating group entry.
Definition SbeMessage.h:373
Iterator end() const
Returns the iterator pointing to the entry behind the end of the group.
Definition SbeMessage.h:545
SbeGroupEntries(const SbeGroupEntries< OtherEntry, OtherBlockLength, OtherNumInGroup, OtherLength > &other) noexcept
Copy constructor.
Definition SbeMessage.h:575
Length EncodedLength
The length of the binary data occupied by the group entries.
Definition SbeMessage.h:370
NumInGroup Size
Number of entries in the collection.
Definition SbeMessage.h:376
SbeGroupEntry()
Initializes a blank instance.
Definition SbeMessage.h:291
SbeGroupEntry(void *encoded, BlockLength size, SchemaVersion version)
Initializes the instance from the memory block of the encoded message.
Definition SbeMessage.h:300
SbeVariableLengthFieldList< BinarySize > checkVariableLengthFields() const
Checks the variable length fields list consistency.
SbeGroupList checkTail() const
Checks the list consistency.
Definition SbeMessage.h:994
SbeVariableLengthFieldList< BinarySize > variableLengthFields() const noexcept
Definition SbeMessage.h:979
SbeGroupList(void *binary, BinarySize size, SchemaVersion version) noexcept
Initializes the list over the memory block.
Definition SbeMessage.h:942
const void * tail() const noexcept
Definition SbeMessage.h:742
SbeGroup() noexcept
Initializes a blank instance referencing to nothing.
Definition SbeMessage.h:646
SbeGroup(void *data, BinarySize size, SchemaVersion version) noexcept
Initializes an instance referencing to a valid group of a given message.
Definition SbeMessage.h:656
const void * encoded() const noexcept
Definition SbeMessage.h:736
SbeGroupEntries< SecurityGroupsEntry, typename Dimension::BlockLength, typename Dimension::NumInGroup, MessageSize > Entries
Definition SbeMessage.h:634
void clear() noexcept
Blank the instance.
MessageTemplateId templateId() const noexcept
Group setupGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner &owner)
Setups the repeating group with the given number of entries.
Group setupGroup(Callable callable, typename Group::Size length, Owner &owner)
Setups the repeating group with the given number of entries.
StrRef getVariableLengthField(Callable callable, SchemaVersion since, Owner &owner) const noexcept
void setVariableLengthField(Callable callable, StrRef value, SchemaVersion since, Owner &owner)
Sets the value of the variable length field.
SbeMessage(void *data, MessageSize size)
Initializes the instance over the given memory block.
SbeVariableLengthFieldList< MessageSize > VariableLengthFieldList
Binary group list instantiation.
SbeMessage & version(SchemaVersion version) noexcept
Sets the SBE Schema version.
Group getGroup(Callable callable, Owner &owner) const noexcept
Group getGroup(Callable callable, SchemaVersion since, Owner &owner) const noexcept
MessageSize EncodedLength
Length of the message binary data.
SbeMessage(void *data, MessageSize size, NoCheck) noexcept
Initializes the instance over the given memory block.
void initGroup(Group &group, typename Group::EntrySize entrySize) noexcept
Resets the group to the initial state.
void init(MessageHeader::TemplateId value, MessageHeader::BlockLength minimalBlockLength, MessageHeader::BlockLength blockLength, SchemaId id)
void setupGroup(Group &group, typename Group::Size entryCount, const void *messageTail)
Initializes the group header.
VariableLengthFieldList variableLengthFields() const noexcept
SchemaVersion version() const noexcept
SbeGroupList< MessageSize > GroupList
Binary group list instantiation.
SbeMessage(void *data, MessageSize size, SchemaVersion version)
Initializes the instance over the given memory block.
void initHeader(MessageHeader::TemplateId value, MessageHeader::BlockLength blockLength, SchemaId id) noexcept
static constexpr MessageSize getMaxMessageSize() noexcept
Maximal message size.
Group constructGroup(Callable callable, typename Group::Size length, Owner &owner)
Creates a repeating group with the given number of entries, sets all optional fields of the group ent...
Group constructGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner &owner)
Creates a repeating group with the given number of entries, sets all optional fields of the group ent...
void setVariableLengthFieldToNull(Callable callable, SchemaVersion since, Owner &owner) noexcept
Sets the variable length field to null.
void setVariableLengthFieldToNull(Callable callable, Owner &owner) noexcept
Resets the variable length field.
void resetGroup(Callable callable, SchemaVersion since, Owner &owner)
Resets the repeating group.
SbeMessage() noexcept
Initializes a blank instance.
void setVariableLengthField(Callable callable, StrRef value, Owner &owner)
Sets the value of the variable length field.
VariableLengthFieldList variableLengthFields() noexcept
MessageSize BlockLength
Length of the message body representing a block of fixed-length fields.
StrRef getVariableLengthField(Callable callable, const Owner &owner) const noexcept
void resetGroup(Callable callable, Owner &owner) noexcept
Sets the group to the initial state.
MessageSize calculateBinarySize(const void *tail) const noexcept
void constructGroup(Group &group, typename Group::Size entryCount, const void *messageTail)
Initializes the group header, sets all optional fields to null.
void zeroPaddingBytes(BlockLength offset)
If specified, the extra space is padded at the end of each entry and should be set to zeroes by encod...
SbeVariableLengthFieldList(void *binary, BinarySize size, SchemaVersion version) noexcept
Initializes the list over the given memory block.
Definition SbeMessage.h:874
SbeVariableLengthFieldList tail() const noexcept
Definition SbeMessage.h:896
BinaryVariableLengthFieldType & head() const noexcept
Definition SbeMessage.h:889
SbeVariableLengthFieldList checkTail() const
Checks the variable-length field list consistency.
Definition SbeMessage.h:911
void checkSchemaId(SchemaId id)
Checks the compatibility with the provided SBE Schema ID.
constexpr UInt16 MaxConflatedTcpMessageSize
Maximum supported message size.
MessageHeader::Version SchemaVersion
SBE-encoded data version type.
char Char
Character type alias.
Definition String.h:30
UInt16 MessageSize
Message length type.
Definition Aliases.h:29
void checkVersion(SchemaVersion version)
Checks the compatibility with the provided SBE Schema version.
MessageHeader::SchemaId SchemaId
void checkSchema(SchemaId id, SchemaVersion version)
Checks the compatibility with the provided SBE Schema version.
MessageHeader::TemplateId MessageTemplateId
Message type (template) identification.