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

KDE's Doxygen guidelines are available online.