Commit 866de9cf authored by Volker Krause's avatar Volker Krause
Browse files

Add BitVector for handling data that isn't byte-aligned

Will be needed for ASN.1 uPER decoding.

Also, rebase the JS bit array API on top of this.
parent b7944375
......@@ -24,7 +24,7 @@ ecm_add_test(uic9183parsertest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(vdvtickettest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(rct2parsertest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(jsapitest.cpp ../src/lib/jsapi/jsonld.cpp TEST_NAME jsapitest LINK_LIBRARIES Qt::Test KPim::Itinerary Qt${QT_MAJOR_VERSION}::Qml)
ecm_add_test(bitarraytest.cpp ../src/lib/jsapi/bitarray.cpp TEST_NAME bitarraytest LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(bitarraytest.cpp ../src/lib/jsapi/bitarray.cpp ../src/lib/asn1/bitvector.cpp TEST_NAME bitarraytest LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(structureddataextractortest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary)
ecm_add_test(pdfdocumenttest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary Qt${QT_MAJOR_VERSION}::Gui)
ecm_add_test(htmldocumenttest.cpp LINK_LIBRARIES Qt::Test KPim::Itinerary)
......
......@@ -9,6 +9,7 @@ add_library(KPim::Itinerary ALIAS KPimItinerary)
target_sources(KPimItinerary PRIVATE
asn1/berelement.cpp
asn1/bitvector.cpp
datatypes/action.cpp
datatypes/boattrip.cpp
......
/*
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "bitvector.h"
using namespace KItinerary;
BitVector::BitVector() = default;
BitVector::BitVector(const QByteArray& data)
: m_data(data)
{
}
BitVector::~BitVector() = default;
BitVector::size_type BitVector::size() const
{
return m_data.size() * 8;
}
uint8_t BitVector::at(BitVector::size_type index) const
{
const auto majIdx = index / 8;
const auto minIdx = 7 - (index % 8);
return (m_data.at(majIdx) & (1 << minIdx)) >> minIdx;
}
QByteArray BitVector::byteArrayAt(BitVector::size_type index, BitVector::size_type bytes) const
{
QByteArray result;
result.reserve(bytes);
for (size_type i = 0; i < bytes; ++i) {
const auto b = valueAtMSB<uint8_t>(index + i * 8, 8);
result.push_back(b);
}
return result;
}
/*
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KITINERARY_BITVECTOR_H
#define KITINERARY_BITVECTOR_H
#include <QByteArray>
#include <QDebug>
#include <cassert>
#include <type_traits>
namespace KItinerary {
/** Vector for working with data that isn't byte-aligned. */
class BitVector
{
public:
BitVector();
explicit BitVector(const QByteArray &data);
~BitVector();
using size_type = QByteArray::size_type;
/** Size of this vector in bits. */
size_type size() const;
/** Returns the bit value at @p index. */
uint8_t at(size_type index) const;
/** Read a big endian unsigned number at bit offset @p index
* and @p bits in length.
*/
template <typename T>
T valueAtMSB(size_type index, size_type bits) const
{
static_assert(std::is_integral_v<T>);
assert(size_type(sizeof(T) * 8) >= bits);
T result = {};
for (size_type i = 0; i < bits; ++i) {
result <<= 1;
result |= at(index + i);
}
return result;
}
/** Returns @p bytes starting at bit offset @p index. */
QByteArray byteArrayAt(size_type index, size_type bytes) const;
private:
QByteArray m_data;
};
}
#endif // KITINERARY_BITVECTOR_H
......@@ -22,27 +22,9 @@ BitArray::~BitArray() = default;
quint64 BitArray::readNumberMSB(int startBit, int size) const
{
const auto byteStart = startBit / 8;
const auto byteCount = ((size + (startBit % 8)) / 8) + (((startBit + size) % 8) ? 1 : 0);
if (m_data.size() < byteStart + byteCount || size < 0 || size > 64 || startBit < 0) {
if (m_data.size() < startBit + size || size < 0 || size > 64 || startBit < 0) {
return 0;
}
quint64 result = 0;
auto bitIdx = startBit % 8;
auto outIdx = size - 1;
for (auto byteIdx = byteStart; byteIdx < byteStart + byteCount; ++byteIdx) {
const uint8_t byte = m_data.at(byteIdx);
for (auto i = bitIdx; i < 8 && outIdx >= 0; ++i, --outIdx) {
const auto bit = (byte & (1 << (7 - i))) > 0;
if (bit) {
result |= (1ull << outIdx);
}
}
bitIdx = 0;
}
return result;
return m_data.valueAtMSB<quint64>(startBit, size);
}
......@@ -6,7 +6,7 @@
#pragma once
#include <QByteArray>
#include <asn1/bitvector.h>
#include <QMetaType>
namespace KItinerary {
......@@ -25,7 +25,7 @@ public:
Q_INVOKABLE quint64 readNumberMSB(int startBit, int size) const;
private:
QByteArray m_data;
BitVector m_data;
};
}}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment