16 BerLongTypeMask = 0x1F,
17 BerExtendedTypeMask = 0x80,
18 BerExtendedLenghtMask = 0x80,
19 BerVariableLengthMarker = 0x80,
22BER::Element::Element() =
default;
24BER::Element::Element(
const QByteArray &data,
int offset,
int size)
27 , m_dataSize(size < 0 ? data.size() : std::min<int>(offset + size, data.size()))
29 assert(m_dataSize <= m_data.size());
37BER::Element::~Element() =
default;
41 if (m_offset < 0 || m_dataSize <= 0 || m_offset + 2 > m_dataSize) {
46 const auto ts = typeSize();
47 if (ts < 0 || ts >= 4 || m_offset + ts + 1 > m_dataSize) {
52 const auto ls = lengthSize();
53 if (ls <= 0 || ls >= 4 || m_offset + ts + ls > m_dataSize) {
59 return cs >= 0 && m_offset + ts + ls + cs <= m_dataSize;
62int BER::Element::typeSize()
const
64 assert(m_offset >= 0);
65 assert(m_offset + 1 < m_dataSize);
66 auto it = m_data.begin() + m_offset;
67 if (((*it) & BerLongTypeMask) != BerLongTypeMask) {
71 while (it != m_data.end() && std::distance(m_data.begin(), it) < m_dataSize) {
73 if (((*it) & BerExtendedTypeMask) == 0) {
74 return std::distance(m_data.begin(), it) - m_offset + 1;
83 const auto ts = typeSize();
89 for (
int i = 0; i < ts; ++i) {
91 result += (uint8_t)*(m_data.constData() + m_offset + i);
96int BER::Element::lengthSize()
const
98 const auto ts = typeSize();
99 const uint8_t firstLengthByte = *(m_data.constData() + m_offset + ts);
100 if (firstLengthByte == BerVariableLengthMarker) {
103 if (firstLengthByte & BerExtendedLenghtMask) {
104 return (firstLengthByte & ~BerExtendedLenghtMask) + 1;
111 const auto ts = typeSize();
112 const auto s = ts + lengthSize() + contentSize();
113 const uint8_t firstLengthByte = *(m_data.constData() + m_offset + ts);
114 if (firstLengthByte == BerVariableLengthMarker) {
122 return m_data.constData() + m_offset;
127 const auto ts = typeSize();
128 const uint8_t firstLengthByte = *(m_data.constData() + m_offset + ts);
129 if (firstLengthByte == BerVariableLengthMarker) {
130 const auto idx = m_data.indexOf(
QByteArray(
"\0\0", 2), m_offset + ts + 1);
131 if (idx + 1 > m_dataSize) {
134 return idx - m_offset - ts - 1;
136 if (firstLengthByte & BerExtendedLenghtMask) {
137 const auto ls = firstLengthByte & ~BerExtendedLenghtMask;
139 for (
int i = 0; i < ls; ++i) {
141 result += (uint8_t)*(m_data.constData() + m_offset + ts + 1 + i);
145 return firstLengthByte;
148int BER::Element::contentOffset()
const
150 return m_offset + typeSize() + lengthSize();
155 return reinterpret_cast<const uint8_t*
>(m_data.constData() + contentOffset());
160 return BER::Element(m_data, contentOffset(), contentSize());
165 const auto s = size();
166 if (m_dataSize <= m_offset + s) {
169 return BER::Element(m_data, m_offset + s, m_dataSize - m_offset - s);
175 while (e.isValid()) {
176 if (e.type() == type) {
186 const uint32_t beSize = qToBigEndian((uint32_t)(size));
187 constexpr auto maxBytes =
sizeof(size);
188 static_assert(maxBytes ==
sizeof(beSize),
"wrong size datatypes");
191 out->
write(((
const char*)&beSize) + maxBytes - 1, 1);
195 uint32_t mask = 0xff000000;
196 static_assert(maxBytes ==
sizeof(mask),
"wrong size datatypes");
197 for (
int i = maxBytes; i > 0; --i) {
199 uint8_t sizeTag = BerExtendedLenghtMask | i;
200 out->
write((
const char*)&sizeTag, 1);
201 out->
write(((
const char*)&beSize) + maxBytes - i, i);
An element in BER/DER/X.690 encoding.
int size() const
Size of the entire element (type, size and content).
int contentSize() const
Size of the value part of this element.
const uint8_t * contentData() const
Raw content data.
uint32_t type() const
Type, "right-aligned" in the returned 32bit value.
bool isValid() const
Returns true if this element has a valid structure and can be read from.
Element find(uint32_t type) const
Returns the first child element of the given type.
Element next() const
Next child element, for nested types.
const char * rawData() const
Raw data of this element.
static void writeSize(QIODevice *out, int size)
Writes the given size in BER encoding to out.
Element first() const
First child element, for nested types.
Classes for reservation/travel data models, data extraction and data augmentation.
bool isValid(QStringView ifopt)
qint64 write(const QByteArray &data)