Prison

mecard.cpp
1/*
2 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
4 SPDX-License-Identifier: MIT
5*/
6
7#include "mecard.h"
8
9#include <vector>
10
11using namespace Prison;
12
13class Prison::MeCardPrivate
14{
15public:
16 QStringView header;
17 struct Element {
18 QStringView key;
19 QStringList values;
20 bool operator<(QStringView other) const;
21 };
22 std::vector<Element> elements;
23};
24
25bool MeCardPrivate::Element::operator<(QStringView other) const
26{
27 return key < other;
28}
29
30MeCard::MeCard()
31 : d(new MeCardPrivate())
32{
33}
34
35MeCard::MeCard(MeCard &&other) noexcept
36 : d(std::move(other.d))
37{
38 other.d.reset();
39}
40
42{
43 std::swap(d, other.d);
44 return *this;
45}
46
47MeCard::~MeCard() = default;
48
49std::optional<MeCard> MeCard::parse(const QString &data)
50{
51 const auto idx = data.indexOf(QLatin1Char(':'));
52 if (idx <= 0 || idx >= data.size() - 1) {
53 return std::nullopt;
54 }
55
56 MeCard m;
57 m.d->header = QStringView(data).left(idx);
58
59 auto remaining = QStringView(data).mid(idx + 1);
60 while (remaining.size() > 0) {
61 const auto keyIdx = remaining.indexOf(QLatin1Char(':'));
62 if (keyIdx <= 0 || keyIdx + 2 >= remaining.size()) {
63 break;
64 }
65
67 auto elemIdx = keyIdx + 1;
68 bool inQuote = false;
69 for (; elemIdx < remaining.size() - 1; ++elemIdx) {
70 auto c = remaining.at(elemIdx);
71 if (elemIdx == (keyIdx + 1) && c == QLatin1Char('"')) { // leading quote
72 inQuote = true;
73 continue;
74 }
75 if (inQuote && c == QLatin1Char('"') && remaining.at(elemIdx + 1) == QLatin1Char(';')) { // trailing quote
76 break;
77 }
78 if (c == QLatin1Char(';')) { // end of element
79 break;
80 }
81 if (c == QLatin1Char('\\')) { // quoted character
82 ++elemIdx;
83 c = remaining.at(elemIdx);
84 }
86 }
87
88 const auto key = remaining.left(keyIdx);
89 auto it = std::lower_bound(m.d->elements.begin(), m.d->elements.end(), key);
90 if (it == m.d->elements.end()) {
91 m.d->elements.push_back(MeCardPrivate::Element());
92 it = std::prev(m.d->elements.end());
93 } else if ((*it).key != key) {
94 it = m.d->elements.insert(it, MeCardPrivate::Element());
95 }
96 (*it).key = key;
97 (*it).values.push_back(value);
98
99 remaining = remaining.mid(elemIdx + 1);
100 }
101
102 if (m.d->elements.empty()) {
103 return std::nullopt;
104 }
105
106 return m;
107}
108
110{
111 return d->header.toString();
112}
113
115{
116 return d->header;
117}
118
120{
121 const auto it = std::lower_bound(d->elements.begin(), d->elements.end(), key);
122 if (it != d->elements.end() && (*it).key == key && (*it).values.size() == 1) {
123 return (*it).values.at(0);
124 }
125 return {};
126}
127
129{
130 const auto it = std::lower_bound(d->elements.begin(), d->elements.end(), key);
131 if (it != d->elements.end() && (*it).key == key) {
132 return (*it).values;
133 }
134 return {};
135}
136
137QVariantMap MeCard::toVariantMap() const
138{
139 QVariantMap map;
140 for (const auto &element : std::as_const(d->elements)) {
141 if (element.values.size() > 1) {
142 map.insert(element.key.toString(), element.values);
143 } else {
144 map.insert(element.key.toString(), element.values.at(0));
145 }
146 }
147 return map;
148}
Parser for the MeCard format.
Definition mecard.h:30
static std::optional< MeCard > parse(const QString &data)
Parse the given string.
Definition mecard.cpp:49
QStringView headerView() const
Get the MeCard header as a string view.
Definition mecard.cpp:114
~MeCard()
Destructor.
QVariantMap toVariantMap() const
Get the parsed data as QVariantMap.
Definition mecard.cpp:137
QStringList values(QStringView key) const
Get the list of values for a given key.
Definition mecard.cpp:128
MeCard & operator=(MeCard &&other) noexcept
Move assignment.
Definition mecard.cpp:41
QString value(QStringView key) const
Get the value for a given key.
Definition mecard.cpp:119
QString header() const
Get the MeCard header.
Definition mecard.cpp:109
Provides classes and methods for generating barcodes.
Definition barcode.h:24
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
void push_back(QChar ch)
qsizetype size() const const
QStringView left(qsizetype length) const const
QStringView mid(qsizetype start, qsizetype length) const const
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:12:04 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.