45template <
typename Message>
46inline void checkBinaryLength(
const Message&, MessageSize length, MessageSize minimalRequiredLength)
48 if ONIXS_CMEMDH_UNLIKELY (length < minimalRequiredLength)
50 throwBinaryBlockIsTooSmall(length, minimalRequiredLength, Message::className());
65template <
class Container,
class BlockLength>
70 const Container& container()
const noexcept
72 return *
static_cast<const Container*
>(
this);
82 template <
class Value>
84 Value
ordinary(BlockLength offset)
const noexcept
87 container().blockLength() >= (offset + size<Value>())
88 &&
"The requested field exceeds provided block boundaries."
91 const void*
const location = advanceByBytes(container().block(), offset);
92 return getValue<Value>(location);
96 template <
class Value>
100 if ONIXS_CMEMDH_UNLIKELY (since > container().version())
101 throwDisallowedField();
110 template <
class Value,
class NullValue>
112 bool ordinary(Value& value, BlockLength offset, NullValue null)
const noexcept
116 return (null != value);
123 template <
class Value,
class NullValue>
127 return (since <= container().version() &&
ordinary(value, offset, null));
131 template <
class Enumeration>
133 typename Enumeration::Enum
enumeration(BlockLength offset)
const noexcept
135 typedef typename Enumeration::Base Base;
136 typedef typename Enumeration::Enum Enum;
142 template <
class Enumeration,
class NullValue>
144 bool enumeration(
typename Enumeration::Enum& value, BlockLength offset, NullValue null)
const noexcept
146 typedef typename Enumeration::Base Base;
147 typedef typename Enumeration::Enum Enum;
150 return null != value;
154 template <
class Enumeration,
class NullValue>
162 template <
class Value>
173 template <
class NullValue>
177 typedef typename NullValue::Value Value;
181 return null != optional;
188 template <
class Value,
class NullValue>
192 return (since <= container().version() &&
decimal(value, offset, null));
196 template <BlockLength Length>
201 container().blockLength() >= (offset + Length) &&
"The requested field exceeds provided block boundaries."
204 const Char*
const text =
reinterpret_cast<const Char*
>(advanceByBytes(container().block(), offset));
205 return StrRef(text, strnlen(text, Length));
212 template <BlockLength Length>
217 return !value.empty();
224 template <BlockLength Length>
236template <
class Container,
class BlockLength>
244 return *
static_cast<Container*
>(
this);
251 const BlockLength encodedBlockLength =
container().blockLength();
253 assert(encodedBlockLength >= offset);
255 const size_t paddingLength = encodedBlockLength - offset;
256 std::memset(advanceByBytes(
container().block(), offset), 0, paddingLength);
260 template <
class FieldValue>
265 container().blockLength() >= (offset + size<FieldValue>())
266 &&
"The requested field exceeds provided block boundaries."
269 void*
const fieldPos = advanceByBytes(
container().block(), offset);
270 setValue(fieldPos, value);
274 template <
class FieldValue>
278 if ONIXS_CMEMDH_UNLIKELY (since >
container().version())
280 throwDisallowedField();
287 template <
class Enumeration>
289 void setEnumeration(BlockLength offset,
typename Enumeration::Enum value)
noexcept
291 typedef typename Enumeration::Base Base;
296 template <
class Enumeration>
300 typedef typename Enumeration::Base Base;
301 setOrdinary(offset,
static_cast<Base
>(value), since);
305 template <BlockLength Size>
310 container().blockLength() >= (offset + Size) &&
"The requested field exceeds provided block boundaries."
312 assert(value.size() <= Size &&
"The string is truncated.");
314 void*
const fieldPos = advanceByBytes(
container().block(), offset);
315 const size_t sizeToCopy = (std::min)(Size,
static_cast<BlockLength
>(value.size()));
318 std::memcpy(fieldPos, value.data(), sizeToCopy);
320 std::memset(advanceByBytes(fieldPos, sizeToCopy), 0, Size - sizeToCopy);
324 template <BlockLength Size>
328 if ONIXS_CMEMDH_UNLIKELY (since >
container().version())
330 throwDisallowedField();
344template <
class BodySizeType>
373 return (encoded_ !=
nullptr);
433template <
class EntryType,
class BlockLength,
class NumInGroup,
class Length>
481 return (entry_ !=
nullptr);
490 return Entry(entry_, size_, version_);
502 return entry_ == other.entry_;
508 return entry_ != other.entry_;
514 return entry_ < other.entry_;
520 return entry_ > other.entry_;
528 entry_ = advanceByBytes(entry_, size_);
538 entry_ = advanceBackByBytes(entry_, size_);
549 return Iterator(advanceByBytes(entry_, distance * size_), size_, version_);
558 return Iterator(advanceBackByBytes(entry_, distance * size_), size_, version_);
579 , blockLength_(blockLength)
584 assert(blockLength > 0);
585 assert(version != 0);
591 return (
nullptr != encoded_);
609 return Iterator(
encoded(), blockLength_, version_);
623 assert(index < size_);
626 return Entry(advanceByBytes(encoded_,
static_cast<ptrdiff_t
>(index) * blockLength_), blockLength_, version_);
642 template <
class OtherEntry,
class OtherBlockLength,
class OtherNumInGroup,
class OtherLength>
644 : encoded_(other.encoded_)
645 , blockLength_(other.blockLength_)
647 , version_(other.version_)
652 assert(blockLength_ == other.blockLength_);
653 assert(size_ == other.size_);
656 template <
class OtherEntry,
class OtherBlockLength,
class OtherNumInGroup,
class OtherLength>
660 encoded_ = other.encoded_;
662 blockLength_ = other.blockLength_;
664 assert(blockLength_ == other.blockLength_);
668 assert(size_ == other.size_);
670 version_ = other.version_;
677 template <
class OtherEntry,
class OtherBlockLength,
class OtherNumInGroup,
class OtherLength>
681 BlockLength blockLength_;
687template <
class EntryType,
class DimensionType,
class GroupSizeType>
744 return (entries_ !=
nullptr);
792 assert(index <
size());
804 return Entries(entries_, header_->blockLength(), header_->numInGroup(), version_);
814 const void*
tail() const noexcept
846 void init(EntrySize entrySize)
noexcept
851 Dimension*
const group =
static_cast<Dimension*
>(header_);
852 group->setBlockLength(entrySize);
853 group->setNumInGroup(0);
857 Size allocate(Size entryCount,
const void* messageTail,
const void* blockEnd)
863 Dimension*
const group =
static_cast<Dimension*
>(header_);
865 const EntrySize entrySize = group->blockLength();
867 if ONIXS_CMEMDH_UNLIKELY (entrySize < EntryType::blockLength(version_))
869 throwBadBinaryBlock();
872 const Size oldEntryCount = group->numInGroup();
874 if (oldEntryCount == entryCount)
877 const ptrdiff_t memShift = (entryCount - oldEntryCount) *
static_cast<ptrdiff_t
>(entrySize);
879 const void*
const newMessageTail = advanceByBytes(messageTail, memShift);
881 if ONIXS_CMEMDH_UNLIKELY (byteDistance(blockEnd, newMessageTail) < 0)
883 throwNotEnoughSpace();
886 const void*
const oldEndOfGroup = advanceByBytes(entries_,
static_cast<ptrdiff_t
>(entrySize) * oldEntryCount);
888 void*
const newEndGroup = advanceByBytes(entries_,
static_cast<ptrdiff_t
>(entrySize) * entryCount);
890 std::memmove(newEndGroup, oldEndOfGroup, byteDistance(messageTail, oldEndOfGroup));
892 group->setNumInGroup(entryCount);
894 return oldEntryCount;
899 void setup(Size entryCount,
const void* messageTail,
const void* blockEnd)
905 const Size oldEntryCount = allocate(entryCount, messageTail, blockEnd);
907 for (Size index = oldEntryCount; index < entryCount; ++index)
908 zeroPaddingBytes((*
this)[index].resetVariableFields());
913 void construct(Size entryCount,
const void* messageTail,
const void* blockEnd)
919 const Size oldEntryCount = allocate(entryCount, messageTail, blockEnd);
921 for (Size index = oldEntryCount; index < entryCount; ++index)
922 zeroPaddingBytes((*
this)[index].reset());
926 static void zeroPaddingBytes(Entry& entry)
928 assert(entry.valid());
929 entry.zeroPaddingBytes(EntryType::minimalBlockLength(entry.version()));
941template <
class BinarySize>
961 template <
class BinaryVariableLengthFieldType>
962 BinaryVariableLengthFieldType&
head() const noexcept
964 return *
static_cast<BinaryVariableLengthFieldType*
>(binary_);
968 template <
class BinaryVariableLengthFieldType>
975 assert(headSize <= size_);
983 template <
class BinaryVariableLengthFieldType>
986 if ONIXS_CMEMDH_UNLIKELY (
empty() || (size_ < BinaryVariableLengthFieldType::Size))
988 throwBadBinaryBlock();
993 if ONIXS_CMEMDH_UNLIKELY (headSize > size_)
995 throwBadBinaryBlock();
1008template <
class BinarySize>
1025 return (0 == size_);
1029 template <
class Group>
1035 return Group(binary_, size_, version_);
1039 template <
class Group>
1044 const BinarySize headSize =
head<Group>().binarySize();
1046 assert(headSize <= size_);
1048 return SbeGroupList(advanceByBytes(binary_, headSize), size_ - headSize, version_);
1052 template <
class Group>
1057 const BinarySize headSize =
head<Group>().binarySize();
1059 assert(headSize <= size_);
1067 template <
class Group>
1070 const BinarySize headSize = checkHead<Group>();
1072 return SbeGroupList(advanceByBytes(binary_, headSize), size_ - headSize, version_);
1078 template <
class Group>
1081 const BinarySize headSize = checkHead<Group>();
1087 template <
class Group>
1088 BinarySize checkHead()
const
1090 if ONIXS_CMEMDH_UNLIKELY (size_ < Group::Dimension::Size)
1092 throwBadBinaryBlock();
1095 const Group group = head<Group>();
1097 const BinarySize headSize = group.binarySize();
1099 if ONIXS_CMEMDH_UNLIKELY (headSize > size_)
1101 throwBadBinaryBlock();
1106 const BinarySize entrySize = group.entrySize();
1107 const BinarySize expectedEntrySize = Group::Entry::minimalBlockLength(version_);
1109 if ONIXS_CMEMDH_UNLIKELY (entrySize < expectedEntrySize)
1111 throwBadBinaryBlock();
1124template <
typename Traits>
1127 if ONIXS_CMEMDH_UNLIKELY (version < Traits::MinimalVersion)
1129 throwBadMessageVersion(version, Traits::MinimalVersion);
1134template <
typename Traits>
1139 if ONIXS_CMEMDH_UNLIKELY (version < since)
1141 throwBadMessageVersion(version, since);
1146template <
typename Traits>
1149 if ONIXS_CMEMDH_UNLIKELY (
id != Traits::Id)
1151 throwBadSchemaId(Traits::Id,
id);
1156template <
typename Traits>
1247 return (
nullptr != header_);
1256 return header_->templateId();
1265 return header_->version();
1274 return header_->schemaId();
1301 return advanceByBytes(header_, size_);
1310 return advanceByBytes(header_, size_);
1335 return header_->blockLength();
1381 return GroupList(list, listSize, header_->version());
1394 return GroupList(
const_cast<void*
>(list), listSize, header_->version());
1398 template <
typename Group>
1401 assert(group.valid());
1402 group.init(entrySize);
1406 template <
typename Group>
1409 assert(messageTail);
1410 assert(group.valid());
1411 group.setup(entryCount, messageTail,
blockEnd());
1415 template <
typename Group>
1418 assert(messageTail);
1419 assert(group.valid());
1420 group.construct(entryCount, messageTail,
blockEnd());
1463 header_->setTemplateId(value);
1465 header_->setSchemaId(
id);
1475 const ptrdiff_t distance = byteDistance(tail,
binary());
1477 assert(distance > 0);
1479 assert(distance <= (std::numeric_limits<MessageSize>::max)());
1483 assert(size <= size_);
1489 template <
class Group,
class Callable,
class Owner>
1492 const typename Group::EntrySize entrySize = Group::Entry::blockLength(
version());
1494 Group grp = callable(owner);
1500 template <
class Callable,
class Owner>
1503 if ONIXS_CMEMDH_UNLIKELY (since >
version())
1512 template <
class Group,
class Callable,
class Owner>
1515 if ONIXS_CMEMDH_UNLIKELY (since >
version())
1524 template <
class Group,
class Callable,
class Owner>
1525 Group
getGroup(Callable callable, Owner& owner)
const noexcept
1527 static_assert(
noexcept(callable(owner)),
"");
1528 return callable(owner);
1532 template <
class Group,
class Callable,
class Owner>
1535 if ONIXS_CMEMDH_UNLIKELY (since >
version())
1545 template <
class Group,
class Callable,
class Owner>
1548 if ONIXS_CMEMDH_UNLIKELY (since >
version())
1558 template <
class Group,
class Callable,
class Owner>
1561 Group group = callable(owner);
1569 template <
class Group,
class Callable,
class Owner>
1572 if ONIXS_CMEMDH_UNLIKELY (since >
version())
1581 template <
class Group,
class Callable,
class Owner>
1582 Group
setupGroup(Callable callable,
typename Group::Size length, Owner& owner)
1584 Group group = callable(owner);
1605template <
class Message>
1610 typename std::enable_if<std::is_same<
typename std::remove_cv<Message>::type,
SbeMessage>::value>::type* =
nullptr)
1616template <
class Message>
1621 typename std::enable_if<std::is_base_of<
SbeMessage,
typename std::remove_cv<Message>::type>::value && !std::is_same<
typename std::remove_cv<Message>::type,
SbeMessage>::value>::type* =
nullptr)
1627template <
class Message>
1632 typename std::enable_if<std::is_same<
typename std::remove_cv<Message>::type,
SbeMessage>::value>::type* =
nullptr) noexcept
1634 return SbeMessage(toMutable(data), size, noCheck);
1638template <
class Message>
1643 typename std::enable_if<std::is_base_of<
SbeMessage,
typename std::remove_cv<Message>::type>::value && !std::is_same<
typename std::remove_cv<Message>::type,
SbeMessage>::value>::type* =
nullptr) noexcept
#define ONIXS_CMEMDH_MESSAGING_NAMESPACE_BEGIN
#define ONIXS_CMEMDH_MESSAGING_NAMESPACE_END
#define ONIXS_CMEMDH_LTWT_EXPORTED
#define ONIXS_CMEMDH_FORCEINLINE
#define ONIXS_CMEMDH_NODISCARD
#define ONIXS_CMEMDH_HOTPATH
#define ONIXS_CMEMDH_UNUSED
~BinaryBlockBase()=default
bool fixedStr(StrRef &value, BlockLength offset) const noexcept
Value ordinary(BlockLength offset) const noexcept
bool decimal(Decimal &value, BlockLength offset, NullValue null) const noexcept
Value ordinary(BlockLength offset, SchemaVersion since) const
bool fixedStr(StrRef &value, BlockLength offset, SchemaVersion since) const noexcept
bool ordinary(Value &value, BlockLength offset, NullValue null) const noexcept
bool decimal(Value &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
Enumeration::Enum enumeration(BlockLength offset) const noexcept
bool enumeration(typename Enumeration::Enum &value, BlockLength offset, NullValue null) const noexcept
Provides access to an optional field value.
BinaryBlock()=default
Initializes a blank instance.
bool ordinary(Value &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
StrRef fixedStr(BlockLength offset) const noexcept
Provides access to a string field value.
Decimal decimal(BlockLength offset) const
bool enumeration(typename Enumeration::Enum &value, BlockLength offset, NullValue null, SchemaVersion since) const noexcept
Provides access to an optional field value.
NumInGroup numInGroup() const noexcept
BlockLength blockLength() const noexcept
SbeFields()=default
Initializes a blank instance.
Container & container() noexcept
void zeroPaddingBytes(BlockLength offset) noexcept
If specified, the extra space is padded at the end of each entry and should be set to zeroes by encod...
void setFixedStr(BlockLength offset, StrRef value) noexcept
Sets the field value.
void setOrdinary(BlockLength offset, FieldValue value, SchemaVersion since)
Sets the field value.
void setEnumeration(BlockLength offset, typename Enumeration::Enum value, SchemaVersion since)
Sets the field value.
void setEnumeration(BlockLength offset, typename Enumeration::Enum value) noexcept
Sets the field value.
void setOrdinary(BlockLength offset, FieldValue value) noexcept
Sets the field value.
void setFixedStr(BlockLength offset, StrRef value, SchemaVersion since)
Sets the field value.
Iterator operator+(difference_type distance) const
Advances by given number of entries.
bool operator==(const Iterator &other) const noexcept
Compares iterators.
std::random_access_iterator_tag iterator_category
Iterator operator-(difference_type distance) const
Advances back by given number of entries.
Iterator() noexcept
Initializes the instance that refers to nothing.
bool valid() const noexcept
bool operator<(const Iterator &other) const noexcept
Established the order between two iterators.
bool operator!=(const Iterator &other) const noexcept
Compares iterators.
ptrdiff_t difference_type
Iterator & operator++()
Advances the next repeating group entry.
bool operator>(const Iterator &other) const noexcept
Established the order between two iterators.
Iterator & operator--()
Advances to the previous repeating group entry.
Iterator(void *entry, EncodedLength size, SchemaVersion version) noexcept
Initializes the instance to the given repeating group.
Operations over SBE-encoded repeating group entries.
SbeGroupEntries() noexcept
Initializes a blank instance referencing to nothing.
bool empty() const noexcept
SbeGroupEntries(void *encoded, BlockLength blockLength, Size groupSize, SchemaVersion version) noexcept
Initializes the instance referencing to data.
EntryType Entry
The type of the repeating group entry.
Iterator end() const
Returns the iterator pointing to the entry behind the end of the group.
Entry operator[](Size index) const
Size size() const noexcept
EncodedLength encodedLength() const noexcept
SbeGroupEntries(const SbeGroupEntries< OtherEntry, OtherBlockLength, OtherNumInGroup, OtherLength > &other) noexcept
Copy constructor.
bool valid() const noexcept
friend class SbeGroupEntries
Length EncodedLength
The length of the binary data occupied by the group entries.
NumInGroup Size
Number of entries in the collection.
SbeGroupEntries & operator=(const SbeGroupEntries< OtherEntry, OtherBlockLength, OtherNumInGroup, OtherLength > &other) noexcept
void * encoded() const noexcept
SbeGroupEntry()
Initializes a blank instance.
const void * block() const noexcept
SbeGroupEntry(void *encoded, BlockLength size, SchemaVersion version)
Initializes the instance from the memory block of the encoded message.
SchemaVersion version() const noexcept
bool valid() const noexcept
const void * encoded() const noexcept
BlockLength blockLength() const noexcept
void * encoded() noexcept
BodySizeType BlockLength
Type to present the length of binary data of the repeating group entry.
SbeVariableLengthFieldList< BinarySize > checkVariableLengthFields() const
Checks the variable length fields list consistency.
bool empty() const noexcept
SbeGroupList tail() const noexcept
SbeGroupList checkTail() const
Checks the list consistency.
Group head() const noexcept
SbeVariableLengthFieldList< BinarySize > variableLengthFields() const noexcept
SbeGroupList(void *binary, BinarySize size, SchemaVersion version) noexcept
Initializes the list over the memory block.
const void * tail() const noexcept
SbeGroup() noexcept
Initializes a blank instance referencing to nothing.
Entries::Size Size
Number of entries in the group.
GroupSizeType BinarySize
Length of group data.
EntrySize entrySize() const noexcept
BinarySize binarySize() const noexcept
bool empty() const noexcept
DimensionType::BlockLength EntrySize
Length of group entry data.
SbeGroup(void *data, BinarySize size, SchemaVersion version) noexcept
Initializes an instance referencing to a valid group of a given message.
Entries::Iterator Iterator
The iterator type for group entries.
Entries::Entry Entry
Group entry type.
Entries entries() const noexcept
void * binary() const noexcept
Entry operator[](Size index) const
Size size() const noexcept
Iterator end() const noexcept
bool valid() const noexcept
const void * encoded() const noexcept
SbeGroupEntries< EntryType, typename Dimension::BlockLength, typename Dimension::NumInGroup, GroupSizeType > Entries
Binary group blocks.
DimensionType Dimension
Repeating group dimension type.
Iterator begin() const noexcept
void clear() noexcept
Blank the instance.
const void * binary() const noexcept
MessageTemplateId templateId() const noexcept
SchemaId schemaId() const noexcept
Group setupGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner &owner)
Setups the repeating group with the given number of entries.
const void * blockEnd() noexcept
GroupList groups() const noexcept
Group setupGroup(Callable callable, typename Group::Size length, Owner &owner)
Setups the repeating group with the given number of entries.
const void * blockEnd() const noexcept
SbeMessage(void *data, MessageSize size)
Initializes the instance over the given memory block.
SbeVariableLengthFieldList< MessageSize > VariableLengthFieldList
Binary group list instantiation.
GroupList groups() noexcept
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.
const void * block() const noexcept
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 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.
MessageSize bufferSize() const noexcept
bool valid() const noexcept
static constexpr MessageSize getMaxMessageSize() noexcept
Maximal message size.
Group constructGroup(Callable callable, typename Group::Size length, Owner &owner)
Group constructGroup(Callable callable, typename Group::Size length, SchemaVersion since, Owner &owner)
void setVariableLengthFieldToNull(Callable callable, SchemaVersion since, Owner &owner) noexcept
Sets the variable length field to null.
BlockLength blockLength() const noexcept
void resetGroup(Callable callable, SchemaVersion since, Owner &owner)
Resets the repeating group.
SbeMessage() noexcept
Initializes a blank instance.
void init(MessageHeader::TemplateId value, MessageHeader::BlockLength minimalBlockLength, MessageHeader::BlockLength blockLength, SchemaId id) noexcept
VariableLengthFieldList variableLengthFields() noexcept
MessageSize BlockLength
Length of the message body representing a block of fixed-length fields.
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.
Variable-length fields list.
bool empty() const noexcept
SbeVariableLengthFieldList(void *binary, BinarySize size, SchemaVersion version) noexcept
Initializes the list over the given memory block.
SbeVariableLengthFieldList tail() const noexcept
BinaryVariableLengthFieldType & head() const noexcept
SbeVariableLengthFieldList checkTail() const
Checks the variable-length field list consistency.
void checkSchemaId(SchemaId id)
Checks the compatibility with the provided SBE Schema ID.
constexpr MessageSize MaxMessageSize
Maximum supported message size.
const SbeMessage constructFromImmutableBlock(const void *data, MessageSize size, typename std::enable_if< std::is_same< typename std::remove_cv< Message >::type, SbeMessage >::value >::type *=nullptr)
Constructs the given message from an immutable memory block.
MessageHeader::Version SchemaVersion
Aliases SBE-encoded data version type.
char Char
Character type alias.
UInt16 MessageSize
Message length type.
std::basic_string_view< Char > StrRef
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.
FloatingPointDecimal< DecimalMantissa, DecimalExponent > Decimal
Universal decimal type.
MessageHeader::TemplateId MessageTemplateId
Message type (template) identification.