KItinerary

iatabcbp.cpp
1/*
2 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "iatabcbp.h"
8#include "iatabcbpconstants_p.h"
9#include "logging.h"
10
11#include <QScopeGuard>
12
13#include <cctype>
14
15using namespace Qt::Literals::StringLiterals;
16using namespace KItinerary;
17using namespace KItinerary::IataBcbpConstants;
18
19IataBcbp::IataBcbp() = default;
20
21IataBcbp::IataBcbp(const QString& data)
22{
23 if (data.size() < MinimumViableSize || data[0] != 'M'_L1 || !data[1].isDigit()) {
24 return;
25 }
26 const auto trimmed = QStringView(data).trimmed(); // tolerance against e.g. trailing newlines
27 if (std::any_of(trimmed.begin(), trimmed.end(), [](QChar c) { return c.row() != 0 || !c.isPrint(); })) {
28 return;
29 }
30 m_data = data;
31 auto resetOnInvalid = qScopeGuard([this] { m_data.clear(); });
32
33 if (!uniqueMandatorySection().isValid()) {
34 return;
35 }
36 if (hasUniqueConditionalSection() && !uniqueConditionalSection().isValid()) {
37 return;
38 }
39
40 const auto legCount = uniqueMandatorySection().numberOfLegs();
41 int offset = UniqueMandatorySize;
42 for (int i = 0; i < legCount; ++i) {
43 if (offset > m_data.size()) {
44 return;
45 }
46 auto rms = IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset));
47 if (!rms.isValid()) {
48 return;
49 }
50 offset += rms.variableFieldSize() + RepeatedMandatorySize;
51 }
52
53 resetOnInvalid.dismiss();
54}
55
56IataBcbp::~IataBcbp() = default;
57
58bool IataBcbp::isValid() const
59{
60 return !m_data.isEmpty();
61}
62
63IataBcbpUniqueMandatorySection IataBcbp::uniqueMandatorySection() const
64{
65 return IataBcbpUniqueMandatorySection(QStringView(m_data).left(UniqueMandatorySize));
66}
67
68bool IataBcbp::hasUniqueConditionalSection() const
69{
70 return (m_data.size() > (UniqueMandatorySize + RepeatedMandatorySize))
71 && (m_data.at(UniqueMandatorySize + RepeatedMandatorySize) == '>'_L1)
72 && repeatedMandatorySection(0).variableFieldSize() > MinimumUniqueConditionalSize;
73}
74
75IataBcbpUniqueConditionalSection IataBcbp::uniqueConditionalSection() const
76{
77 if (hasUniqueConditionalSection()) {
78 return IataBcbpUniqueConditionalSection(QStringView(m_data).mid(UniqueMandatorySize + RepeatedMandatorySize));
79 }
81}
82
84{
85 int offset = UniqueMandatorySize;
86 for (auto i = 0; i < leg; ++i) {
87 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
88 }
89 return IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset, RepeatedMandatorySize));
90}
91
93{
94 int offset = UniqueMandatorySize;
95 if (leg == 0 && hasUniqueConditionalSection()) {
96 offset += uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
97 }
98 for (auto i = 0; i < leg; ++i) {
99 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
100 }
101 return IataBcbpRepeatedConditionalSection(QStringView(m_data).mid(offset + RepeatedMandatorySize));
102}
103
105{
106 int offset = UniqueMandatorySize;
107 for (auto i = 0; i < leg; ++i) {
108 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
109 }
110 auto length = IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
111 if (leg == 0 && hasUniqueConditionalSection()) {
112 const auto s = uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
113 offset += uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
114 length -= s;
115 }
116 if (leg == 0 && !hasUniqueConditionalSection()) { // Easyjet special case that has a airline use section right after the mandatory block
117 return m_data.mid(offset + RepeatedMandatorySize, length);
118 }
119 const auto offset2 = IataBcbpRepeatedConditionalSection(QStringView(m_data).mid(offset + RepeatedMandatorySize)).conditionalFieldSize() + 2 + RepeatedMandatorySize;
120 return m_data.mid(offset + offset2, length - offset2 + RepeatedMandatorySize);
121}
122
123bool IataBcbp::hasSecuritySection() const
124{
125 int offset = UniqueMandatorySize;
126 for (auto i = 0; i < uniqueMandatorySection().numberOfLegs(); ++i) {
127 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
128 }
129 return offset < m_data.size() && m_data[offset] == '^'_L1;
130}
131
132IataBcbpSecuritySection IataBcbp::securitySection() const
133{
134 int offset = UniqueMandatorySize;
135 for (auto i = 0; i < uniqueMandatorySection().numberOfLegs(); ++i) {
136 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
137 }
138 return IataBcbpSecuritySection(QStringView(m_data).mid(offset));
139}
140
141QString IataBcbp::rawData() const
142{
143 return m_data;
144}
145
147{
148 return data.size() >= MinimumViableSize && data[0] == 'M' && std::isdigit(data[1]);
149}
150
151bool IataBcbp::maybeIataBcbp(const QString &data)
152{
153 return data.size() >= MinimumViableSize && data[0] == 'M'_L1 && data[1].isDigit();
154}
155
156#include "moc_iatabcbp.cpp"
Conditional (optional) sections of an IATA BCBP, occurs once per leg.
Repeated mandatory sections of an IATA BCBP, occurs once per leg.
Security section of an IATA BCBP.
Unique conditional (optional) section of an IATA BCBP.
Unique mandatory section of an IATA BCBP.
Q_INVOKABLE QString airlineUseSection(int leg) const
Airline use (non-standard/vendor specific) section of leg.
Definition iatabcbp.cpp:104
Q_INVOKABLE KItinerary::IataBcbpRepeatedConditionalSection repeatedConditionalSection(int leg) const
Conditional (optional) section of leg.
Definition iatabcbp.cpp:92
Q_INVOKABLE KItinerary::IataBcbpRepeatedMandatorySection repeatedMandatorySection(int leg) const
Mandatory section of leg.
Definition iatabcbp.cpp:83
static bool maybeIataBcbp(const QByteArray &data)
Fast checks whether this might be an IATA BCBP.
Definition iatabcbp.cpp:146
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
qsizetype size() const const
const QChar at(qsizetype position) const const
void clear()
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
qsizetype size() const const
QStringView trimmed() const const
QTextStream & left(QTextStream &stream)
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.