KItinerary

uperdecoder.h
1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#ifndef KITINERARY_UPERDECODER_H
7#define KITINERARY_UPERDECODER_H
8
9#include "bitvectorview.h"
10
11#include <QMetaEnum>
12
13#include <variant>
14
15namespace KItinerary {
16
17/** Decoder for data encoded according to X.691 ASN.1 Unaligned Packed Encoding Rules (UPER). */
18class UPERDecoder
19{
20public:
21 explicit UPERDecoder(BitVectorView data);
22 ~UPERDecoder();
23
24 using size_type = BitVectorView::size_type;
25
26 size_type offset() const;
27 void seek(size_type index);
28
29 /** Read constrained whole number from the current position.
30 * @see X.691 §11.5
31 */
32 int64_t readConstrainedWholeNumber(int64_t minimum, int64_t maximum);
33
34 /** Read unconstrained whole number.
35 * @see X.691 §11.8
36 */
38
39 /** Read length determinant.
40 * @see X.691 §11.9
41 */
42 size_type readLengthDeterminant();
43
44 /** Read UTF-8 string. */
46
47 /** Read boolean value. */
48 bool readBoolean();
49
50 /** Read an unconstrained IA5String (7 bit ASCII).
51 * @see X.691 §30
52 */
54
55 /** Read length-constrained IA5String (7 bit ASCII).
56 * @see X.691 §30
57 */
58 QByteArray readIA5String(size_type minLenght, size_type maxLength);
59
60 /** Read unconstrained octet string (8 bit data).
61 * @see X.691 §17
62 */
64
65 /** Read an @tparam N sized bitmap. */
66 template <std::size_t N>
67 inline std::bitset<N> readBitset()
68 {
69 auto result = m_data.bitsetAt<N>(m_idx);
70 m_idx += N;
71 return result;
72 }
73
74 /** Read a sequence-of field with unrestricted size.
75 * @see X.691 §20
76 */
77 template <typename T>
79 {
80 const auto size = readLengthDeterminant();
81 QList<T> result;
82 result.reserve(size);
83 for (size_type i = 0; i < size; ++i) {
84 T element;
85 element.decode(*this);
86 result.push_back(std::move(element));
87 }
88 return result;
89 }
90 QList<int> readSequenceOfConstrainedWholeNumber(int64_t minimum, int64_t maximum);
91 QList<int> readSequenceOfUnconstrainedWholeNumber();
92 QList<QByteArray> readSequenceOfIA5String();
93 QList<QString> readSequenceOfUtf8String();
94
95 /** Read an Object Identifier value.
96 * @see X.691 §24
97 */
99
100 /** Read enumerated value.
101 * @see X.691 §14
102 */
103 template <typename T>
104 inline T readEnumerated()
105 {
106 const auto me = QMetaEnum::fromType<T>();
107 const auto idx = readConstrainedWholeNumber(0, me.keyCount() - 1);
108 return static_cast<T>(me.value(idx));
109 }
110 template <typename T>
111 inline T readEnumeratedWithExtensionMarker()
112 {
113 if (readBoolean()) {
114 setError("CHOICE with extension marker set not implemented.");
115 return {};
116 }
117 return readEnumerated<T>();
118 }
119
120 /** Read a choice value.
121 * @tparam T a std::variant with the alternatives covered by the choice value.
122 * @see X.691 §23
123 */
124 template <typename T>
126 {
127 if (readBoolean()) {
128 setError("CHOICE with extension marker set not implemented.");
129 return {};
130 }
131 constexpr auto count = std::variant_size_v<T>;
132 const auto choiceIdx = readConstrainedWholeNumber(0, count - 1);
133 if (choiceIdx > (int)count) {
134 setError("Invalid CHOICE index.");
135 return {};
136 }
137 return readChoiceElement<T>(choiceIdx);
138 }
139
140 /** Reading at any point encountered an error.
141 * As uPER gives us no way to recover from that, everything
142 * read has to be considered invalid.
143 */
144 bool hasError() const;
145 QByteArray errorMessage() const;
146
147 /** Put the decoder into the error state. */
148 void setError(const char *msg);
149
150private:
151 QByteArray readIA5StringData(size_type len);
152 [[nodiscard]] uint64_t readObjectIdentifierComponent(size_type &numBytes);
153
154 template <typename T, std::size_t Index = 0>
155 T readChoiceElement(int choiceIdx)
156 {
157 if (choiceIdx == Index) {
158 std::variant_alternative_t<Index, T> value;
159 value.decode(*this);
160 return value;
161 }
162 if constexpr (Index + 1 < std::variant_size_v<T>) {
163 return readChoiceElement<T, Index + 1>(choiceIdx);
164 }
165 Q_UNREACHABLE();
166 }
167
168 BitVectorView m_data;
169 size_type m_idx = {};
170 QByteArray m_error;
171};
172
173}
174
175#endif // KITINERARY_UPERDECODER_H
Non-owning bit-level view for working with data that isn't byte-aligned.
QByteArray readObjectIdentifier()
Read an Object Identifier value.
QList< T > readSequenceOf()
Read a sequence-of field with unrestricted size.
Definition uperdecoder.h:78
T readChoiceWithExtensionMarker()
Read a choice value.
T readEnumerated()
Read enumerated value.
int64_t readUnconstrainedWholeNumber()
Read unconstrained whole number.
void setError(const char *msg)
Put the decoder into the error state.
QString readUtf8String()
Read UTF-8 string.
QByteArray readOctetString()
Read unconstrained octet string (8 bit data).
bool readBoolean()
Read boolean value.
bool hasError() const
Reading at any point encountered an error.
QByteArray readIA5String()
Read an unconstrained IA5String (7 bit ASCII).
size_type readLengthDeterminant()
Read length determinant.
std::bitset< N > readBitset()
Read an.
Definition uperdecoder.h:67
int64_t readConstrainedWholeNumber(int64_t minimum, int64_t maximum)
Read constrained whole number from the current position.
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
void push_back(parameter_type value)
void reserve(qsizetype size)
QMetaEnum fromType()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:54:58 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.