File indexing completed on 2024-05-19 05:57:13
0001 /* 0002 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #include "mecardparser.h" 0007 0008 #include <QDebug> 0009 0010 MeCardParser::MeCardParser() = default; 0011 MeCardParser::~MeCardParser() = default; 0012 0013 bool MeCardParser::Element::operator<(QStringView other) const 0014 { 0015 return key < other; 0016 } 0017 0018 bool MeCardParser::parse(const QString &data) 0019 { 0020 m_header = {}; 0021 m_elements.clear(); 0022 m_data = data; 0023 0024 const auto idx = data.indexOf(QLatin1Char(':')); 0025 if (idx <= 0 || idx >= data.size() - 1) { 0026 return false; 0027 } 0028 m_header = QStringView(data).left(idx); 0029 0030 auto remaining = QStringView(data).mid(idx + 1); 0031 while (remaining.size() > 0) { 0032 const auto keyIdx = remaining.indexOf(QLatin1Char(':')); 0033 if (keyIdx <= 0 || keyIdx + 2 >= remaining.size()) { 0034 break; 0035 } 0036 0037 QString value; 0038 auto elemIdx = keyIdx + 1; 0039 bool inQuote = false; 0040 for (; elemIdx < remaining.size() - 1; ++elemIdx) { 0041 auto c = remaining.at(elemIdx); 0042 if (elemIdx == (keyIdx + 1) && c == QLatin1Char('"')) { // leading quote 0043 inQuote = true; 0044 continue; 0045 } 0046 if (inQuote && c == QLatin1Char('"') && remaining.at(elemIdx + 1) == QLatin1Char(';')) { // trailing quote 0047 break; 0048 } 0049 if (c == QLatin1Char(';')) { // end of element 0050 break; 0051 } 0052 if (c == QLatin1Char('\\')) { // quoted character 0053 ++elemIdx; 0054 c = remaining.at(elemIdx); 0055 } 0056 value.push_back(c); 0057 } 0058 0059 const auto key = remaining.left(keyIdx); 0060 auto it = std::lower_bound(m_elements.begin(), m_elements.end(), key); 0061 if (it == m_elements.end()) { 0062 m_elements.push_back(Element()); 0063 it = std::prev(m_elements.end()); 0064 } else if ((*it).key != key) { 0065 it = m_elements.insert(it, Element()); 0066 } 0067 (*it).key = key; 0068 (*it).values.push_back(value); 0069 0070 remaining = remaining.mid(elemIdx + 1); 0071 } 0072 0073 return !m_elements.empty(); 0074 } 0075 0076 QStringView MeCardParser::header() const 0077 { 0078 return m_header; 0079 } 0080 0081 QString MeCardParser::value(QStringView key) const 0082 { 0083 const auto it = std::lower_bound(m_elements.begin(), m_elements.end(), key); 0084 if (it != m_elements.end() && (*it).key == key && (*it).values.size() == 1) { 0085 return (*it).values.at(0); 0086 } 0087 return {}; 0088 } 0089 0090 QStringList MeCardParser::values(QStringView key) const 0091 { 0092 const auto it = std::lower_bound(m_elements.begin(), m_elements.end(), key); 0093 if (it != m_elements.end() && (*it).key == key) { 0094 return (*it).values; 0095 } 0096 return {}; 0097 }