KItinerary

uperdecoder.cpp
1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "uperdecoder.h"
7
8#include <bit>
9
10using namespace KItinerary;
11
12UPERDecoder::UPERDecoder(BitVectorView data)
13 : m_data(data)
14{
15}
16
17UPERDecoder::~UPERDecoder() = default;
18
19UPERDecoder::size_type UPERDecoder::offset() const
20{
21 return m_idx;
22}
23
24void UPERDecoder::seek(UPERDecoder::size_type index)
25{
26 m_idx = index;
27}
28
29int64_t UPERDecoder::readConstrainedWholeNumber(int64_t minimum, int64_t maximum)
30{
31 assert(minimum <= maximum);
32 const uint64_t range = maximum - minimum;
33 const size_type bits = 64 - std::countl_zero(range);
34 const auto result = m_data.valueAtMSB<int64_t>(m_idx, bits);
35 m_idx += bits;
36 return result + minimum;
37}
38
40{
41 const auto len = readLengthDeterminant();
42 if (len > 8) {
43 setError("Encountered INTEGER bigger than 64bit, not implemented.");
44 return 0;
45 }
46 int64_t result = m_data.valueAtMSB<int64_t>(m_idx, 8 * len);
47 m_idx += 8 * len;
48 return result; // TODO convert negative numbers
49}
50
51UPERDecoder::size_type UPERDecoder::readLengthDeterminant()
52{
53 size_type len = m_data.valueAtMSB<size_type>(m_idx, 8);
54 m_idx += 8;
55 if ((len & 0x80) == 0x00) {
56 return len;
57 }
58 if ((len & 0xc0) == 0x80) {
59 return ((len & 0x7f) << 8) | readConstrainedWholeNumber(0, 255);
60 }
61
62 switch (len) {
63 case 0xc1: return 16384;
64 case 0xc2: return 32768;
65 case 0xc3: return 49152;
66 case 0xc4: return 65536;
67 }
68
69 setError("Encountered invalid length determinant.");
70 return 0;
71}
72
74{
75 const auto len = readLengthDeterminant();
76 const auto res = QString::fromUtf8(m_data.byteArrayAt(m_idx, len));
77 m_idx += len * 8;
78 return res;
79}
80
82{
83 return m_data.at(m_idx++) != 0;
84}
85
86QByteArray UPERDecoder::readIA5StringData(size_type len)
87{
88 QByteArray result;
89 result.reserve(len);
90 for (size_type i = 0; i < len; ++i) {
91 const auto c = m_data.valueAtMSB<char>(m_idx, 7);
92 m_idx += 7;
93 result.push_back(c);
94 }
95 return result;
96}
97
99{
100 return readIA5StringData(readLengthDeterminant());
101}
102
103QByteArray UPERDecoder::readIA5String(size_type minLength, size_type maxLength)
104{
105 size_type len = 0;
106 if (minLength == maxLength) {
107 len = minLength;
108 } else {
109 len = readConstrainedWholeNumber(minLength, maxLength);
110 }
111 return readIA5StringData(len);
112}
113
115{
116 const auto len = readLengthDeterminant();
117 const auto res = m_data.byteArrayAt(m_idx, len);
118 m_idx += len * 8;
119 return res;
120}
121
122QList<int> UPERDecoder::readSequenceOfConstrainedWholeNumber(int64_t minimum, int64_t maximum)
123{
124 const auto size = readLengthDeterminant();
125 QList<int> result;
126 result.reserve(size);
127 for (size_type i = 0; i < size; ++i) {
128 result.push_back(readConstrainedWholeNumber(minimum, maximum));
129 }
130 return result;
131}
132
133QList<int> UPERDecoder::readSequenceOfUnconstrainedWholeNumber()
134{
135 const auto size = readLengthDeterminant();
136 QList<int> result;
137 result.reserve(size);
138 for (size_type i = 0; i < size; ++i) {
140 }
141 return result;
142}
143
144QList<QByteArray> UPERDecoder::readSequenceOfIA5String()
145{
146 const auto size = readLengthDeterminant();
147 QList<QByteArray> result;
148 result.reserve(size);
149 for (size_type i = 0; i < size; ++i) {
150 result.push_back(readIA5String());
151 }
152 return result;
153}
154
155QList<QString> UPERDecoder::readSequenceOfUtf8String()
156{
157 const auto size = readLengthDeterminant();
158 QList<QString> result;
159 result.reserve(size);
160 for (size_type i = 0; i < size; ++i) {
161 result.push_back(readUtf8String());
162 }
163 return result;
164}
165
167{
168 return !m_error.isEmpty();
169}
170
171QByteArray UPERDecoder::errorMessage() const
172{
173 return m_error;
174}
175
176void UPERDecoder::setError(const char *msg)
177{
178 m_error = "uPER decoding error at offset " + QByteArray::number((qint64)m_idx) + ": " + msg;
179}
Non-owning bit-level view for working with data that isn't byte-aligned.
uint8_t at(size_type index) const
Returns the bit value at index.
QByteArray byteArrayAt(size_type index, size_type bytes) const
Returns bytes starting at bit offset index.
T valueAtMSB(size_type index, size_type bits) const
Read a big endian unsigned number at bit offset index and bits in length.
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.
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
bool isEmpty() const const
QByteArray number(double n, char format, int precision)
void push_back(QByteArrayView str)
void reserve(qsizetype size)
void push_back(parameter_type value)
void reserve(qsizetype size)
QString fromUtf8(QByteArrayView str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:48 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.