1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "addressformat_p.h"
7#include "addressformatparser_p.h"
8
9#include <QDebug>
10
11using namespace KContacts;
12
13struct {
14 char c;
15 AddressFormatField f;
16} static constexpr const field_map[] = {
17 {.c: 'A', .f: AddressFormatField::StreetAddress},
18 {.c: 'C', .f: AddressFormatField::Locality},
19 {.c: 'D', .f: AddressFormatField::DependentLocality},
20 {.c: 'N', .f: AddressFormatField::Name},
21 {.c: 'O', .f: AddressFormatField::Organization},
22 {.c: 'P', .f: AddressFormatField::PostOfficeBox},
23 {.c: 'R', .f: AddressFormatField::Country},
24 {.c: 'S', .f: AddressFormatField::Region},
25 {.c: 'X', .f: AddressFormatField::SortingCode},
26 {.c: 'Z', .f: AddressFormatField::PostalCode},
27};
28
29AddressFormatField AddressFormatParser::parseField(QChar c)
30{
31 const auto it = std::lower_bound(first: std::begin(arr: field_map), last: std::end(arr: field_map), val: c.cell(), comp: [](auto lhs, auto rhs) {
32 return lhs.c < rhs;
33 });
34 if (it == std::end(arr: field_map) || (*it).c != c.cell() || c.row() != 0) {
35 return AddressFormatField::NoField;
36 }
37 return (*it).f;
38}
39
40AddressFormatFields AddressFormatParser::parseFields(QStringView s)
41{
42 AddressFormatFields fields;
43 for (auto c : s) {
44 fields |= parseField(c);
45 }
46 return fields;
47}
48
49std::vector<AddressFormatElement> AddressFormatParser::parseElements(QStringView s)
50{
51 std::vector<AddressFormatElement> elements;
52 QString literal;
53 for (auto it = s.begin(); it != s.end(); ++it) {
54 if ((*it) == QLatin1Char('%') && std::next(x: it) != s.end()) {
55 if (!literal.isEmpty()) {
56 AddressFormatElement elem;
57 auto e = AddressFormatElementPrivate::get(elem);
58 e->literal = std::move(literal);
59 elements.push_back(x: elem);
60 }
61 ++it;
62 if ((*it) == QLatin1Char('n')) {
63 elements.push_back(x: AddressFormatElement{});
64 } else {
65 const auto f = parseField(c: *it);
66 if (f == AddressFormatField::NoField) {
67 qWarning() << "invalid format field element: %" << *it << "in" << s;
68 } else {
69 AddressFormatElement elem;
70 auto e = AddressFormatElementPrivate::get(elem);
71 e->field = f;
72 elements.push_back(x: elem);
73 }
74 }
75 } else {
76 literal.push_back(c: *it);
77 }
78 }
79 if (!literal.isEmpty()) {
80 AddressFormatElement elem;
81 auto e = AddressFormatElementPrivate::get(elem);
82 e->literal = std::move(literal);
83 elements.push_back(x: elem);
84 }
85 return elements;
86}
87

source code of kcontacts/src/addressformatparser.cpp