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
const QChar at(qsizetype position) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) 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 indexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const const
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 10 2024 11:43:48 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.