File indexing completed on 2024-10-06 03:38:09

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "addressformat_p.h"
0007 #include "addressformatparser_p.h"
0008 
0009 #include <QDebug>
0010 
0011 using namespace KContacts;
0012 
0013 struct {
0014     char c;
0015     AddressFormatField f;
0016 } static constexpr const field_map[] = {
0017     {'A', AddressFormatField::StreetAddress},
0018     {'C', AddressFormatField::Locality},
0019     {'D', AddressFormatField::DependentLocality},
0020     {'N', AddressFormatField::Name},
0021     {'O', AddressFormatField::Organization},
0022     {'P', AddressFormatField::PostOfficeBox},
0023     {'R', AddressFormatField::Country},
0024     {'S', AddressFormatField::Region},
0025     {'X', AddressFormatField::SortingCode},
0026     {'Z', AddressFormatField::PostalCode},
0027 };
0028 
0029 AddressFormatField AddressFormatParser::parseField(QChar c)
0030 {
0031     const auto it = std::lower_bound(std::begin(field_map), std::end(field_map), c.cell(), [](auto lhs, auto rhs) {
0032         return lhs.c < rhs;
0033     });
0034     if (it == std::end(field_map) || (*it).c != c.cell() || c.row() != 0) {
0035         return AddressFormatField::NoField;
0036     }
0037     return (*it).f;
0038 }
0039 
0040 AddressFormatFields AddressFormatParser::parseFields(QStringView s)
0041 {
0042     AddressFormatFields fields;
0043     for (auto c : s) {
0044         fields |= parseField(c);
0045     }
0046     return fields;
0047 }
0048 
0049 std::vector<AddressFormatElement> AddressFormatParser::parseElements(QStringView s)
0050 {
0051     std::vector<AddressFormatElement> elements;
0052     QString literal;
0053     for (auto it = s.begin(); it != s.end(); ++it) {
0054         if ((*it) == QLatin1Char('%') && std::next(it) != s.end()) {
0055             if (!literal.isEmpty()) {
0056                 AddressFormatElement elem;
0057                 auto e = AddressFormatElementPrivate::get(elem);
0058                 e->literal = std::move(literal);
0059                 elements.push_back(elem);
0060             }
0061             ++it;
0062             if ((*it) == QLatin1Char('n')) {
0063                 elements.push_back(AddressFormatElement{});
0064             } else {
0065                 const auto f = parseField(*it);
0066                 if (f == AddressFormatField::NoField) {
0067                     qWarning() << "invalid format field element: %" << *it << "in" << s;
0068                 } else {
0069                     AddressFormatElement elem;
0070                     auto e = AddressFormatElementPrivate::get(elem);
0071                     e->field = f;
0072                     elements.push_back(elem);
0073                 }
0074             }
0075         } else {
0076             literal.push_back(*it);
0077         }
0078     }
0079     if (!literal.isEmpty()) {
0080         AddressFormatElement elem;
0081         auto e = AddressFormatElementPrivate::get(elem);
0082         e->literal = std::move(literal);
0083         elements.push_back(elem);
0084     }
0085     return elements;
0086 }