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 KItinerary;
16using namespace KItinerary::IataBcbpConstants;
17
18IataBcbp::IataBcbp() = default;
19
20IataBcbp::IataBcbp(const QString& data)
21{
22 if (data.size() < MinimumViableSize || data[0] != QLatin1Char('M') || !data[1].isDigit()) {
23 return;
24 }
25 const auto trimmed = QStringView(data).trimmed(); // tolerance against e.g. trailing newlines
26 if (std::any_of(trimmed.begin(), trimmed.end(), [](QChar c) { return c.row() != 0 || !c.isPrint(); })) {
27 return;
28 }
29 m_data = data;
30 auto resetOnInvalid = qScopeGuard([this] { m_data.clear(); });
31
32 if (!uniqueMandatorySection().isValid()) {
33 return;
34 }
35 if (hasUniqueConditionalSection() && !uniqueConditionalSection().isValid()) {
36 return;
37 }
38
39 const auto legCount = uniqueMandatorySection().numberOfLegs();
40 int offset = UniqueMandatorySize;
41 for (int i = 0; i < legCount; ++i) {
42 if (offset > m_data.size()) {
43 return;
44 }
45 auto rms = IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset));
46 if (!rms.isValid()) {
47 return;
48 }
49 offset += rms.variableFieldSize() + RepeatedMandatorySize;
50 }
51
52 resetOnInvalid.dismiss();
53}
54
55IataBcbp::~IataBcbp() = default;
56
57bool IataBcbp::isValid() const
58{
59 return !m_data.isEmpty();
60}
61
62IataBcbpUniqueMandatorySection IataBcbp::uniqueMandatorySection() const
63{
64 return IataBcbpUniqueMandatorySection(QStringView(m_data).left(UniqueMandatorySize));
65}
66
67bool IataBcbp::hasUniqueConditionalSection() const
68{
69 return (m_data.size() > (UniqueMandatorySize + RepeatedMandatorySize))
70 && (m_data.at(UniqueMandatorySize + RepeatedMandatorySize) == QLatin1Char('>'))
71 && repeatedMandatorySection(0).variableFieldSize() > MinimumUniqueConditionalSize;
72}
73
74IataBcbpUniqueConditionalSection IataBcbp::uniqueConditionalSection() const
75{
76 if (hasUniqueConditionalSection()) {
77 return IataBcbpUniqueConditionalSection(QStringView(m_data).mid(UniqueMandatorySize + RepeatedMandatorySize));
78 }
80}
81
83{
84 int offset = UniqueMandatorySize;
85 for (auto i = 0; i < leg; ++i) {
86 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
87 }
88 return IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset, RepeatedMandatorySize));
89}
90
92{
93 int offset = UniqueMandatorySize;
94 if (leg == 0 && hasUniqueConditionalSection()) {
95 offset += uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
96 }
97 for (auto i = 0; i < leg; ++i) {
98 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
99 }
100 return IataBcbpRepeatedConditionalSection(QStringView(m_data).mid(offset + RepeatedMandatorySize));
101}
102
104{
105 int offset = UniqueMandatorySize;
106 for (auto i = 0; i < leg; ++i) {
107 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
108 }
109 auto length = IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
110 if (leg == 0 && hasUniqueConditionalSection()) {
111 const auto s = uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
112 offset += uniqueConditionalSection().fieldSize() + MinimumUniqueConditionalSize;
113 length -= s;
114 }
115 if (leg == 0 && !hasUniqueConditionalSection()) { // Easyjet special case that has a airline use section right after the mandatory block
116 return m_data.mid(offset + RepeatedMandatorySize, length);
117 }
118 const auto offset2 = IataBcbpRepeatedConditionalSection(QStringView(m_data).mid(offset + RepeatedMandatorySize)).conditionalFieldSize() + 2 + RepeatedMandatorySize;
119 return m_data.mid(offset + offset2, length - offset2 + RepeatedMandatorySize);
120}
121
122bool IataBcbp::hasSecuritySection() const
123{
124 int offset = UniqueMandatorySize;
125 for (auto i = 0; i < uniqueMandatorySection().numberOfLegs(); ++i) {
126 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
127 }
128 return offset < m_data.size() && m_data[offset] == QLatin1Char('^');
129}
130
131IataBcbpSecuritySection IataBcbp::securitySection() const
132{
133 int offset = UniqueMandatorySize;
134 for (auto i = 0; i < uniqueMandatorySection().numberOfLegs(); ++i) {
135 offset += RepeatedMandatorySize + IataBcbpRepeatedMandatorySection(QStringView(m_data).mid(offset)).variableFieldSize();
136 }
137 return IataBcbpSecuritySection(QStringView(m_data).mid(offset));
138}
139
140QString IataBcbp::rawData() const
141{
142 return m_data;
143}
144
146{
147 return data.size() >= MinimumViableSize && data[0] == 'M' && std::isdigit(data[1]);
148}
149
150bool IataBcbp::maybeIataBcbp(const QString &data)
151{
152 return data.size() >= MinimumViableSize && data[0] == QLatin1Char('M') && data[1].isDigit();
153}
154
155#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:103
Q_INVOKABLE KItinerary::IataBcbpRepeatedConditionalSection repeatedConditionalSection(int leg) const
Conditional (optional) section of leg.
Definition iatabcbp.cpp:91
Q_INVOKABLE KItinerary::IataBcbpRepeatedMandatorySection repeatedMandatorySection(int leg) const
Mandatory section of leg.
Definition iatabcbp.cpp:82
static bool maybeIataBcbp(const QByteArray &data)
Fast checks whether this might be an IATA BCBP.
Definition iatabcbp.cpp:145
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 Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.