Added ability to format phone numbers in modern way.

This commit is contained in:
23rd 2021-08-27 17:07:04 +03:00
parent e5b85bbaf1
commit e4640590d0
2 changed files with 85 additions and 0 deletions

View file

@ -307,6 +307,81 @@ QString CountriesInstance::countryISO2ByPhone(const QString &phone) {
return (i != listByCode.cend()) ? (*i)->iso2 : QString(); return (i != listByCode.cend()) ? (*i)->iso2 : QString();
} }
FormatResult CountriesInstance::format(FormatArgs args) {
// Ported from TDLib.
const auto &phoneNumber = args.phone;
const Info *bestCountryPtr = nullptr;
const CallingCodeInfo *bestCallingCodePtr = nullptr;
auto bestLength = size_t(0);
auto isPrefix = false;
for (const auto &country : list()) {
for (auto &callingCode : country.codes) {
if (phoneNumber.startsWith(callingCode.callingCode)) {
const auto codeSize = callingCode.callingCode.size();
for (const auto &prefix : callingCode.prefixes) {
if (prefix.startsWith(phoneNumber.midRef(codeSize))) {
isPrefix = true;
}
if ((codeSize + prefix.size()) > bestLength &&
phoneNumber.midRef(codeSize).startsWith(prefix)) {
bestCountryPtr = &country;
bestCallingCodePtr = &callingCode;
bestLength = codeSize + prefix.size();
}
}
}
if (callingCode.callingCode.startsWith(phoneNumber)) {
isPrefix = true;
}
}
}
if (bestCountryPtr == nullptr) {
return FormatResult{ .formatted = phoneNumber };
}
const auto formattedPart = phoneNumber.mid(
bestCallingCodePtr->callingCode.size());
auto formattedResult = formattedPart;
auto maxMatchedDigits = size_t(0);
for (auto &pattern : bestCallingCodePtr->patterns) {
auto result = QString();
auto currentPatternPos = int(0);
auto isFailedMatch = false;
auto matchedDigits = size_t(0);
for (const auto &c : formattedPart) {
while ((currentPatternPos < pattern.size())
&& (pattern[currentPatternPos] != 'X')
&& !pattern[currentPatternPos].isDigit()) {
result += pattern[currentPatternPos++];
}
if (currentPatternPos == pattern.size()) {
result += ' ';
}
if ((currentPatternPos >= pattern.size())
|| (pattern[currentPatternPos] == 'X')) {
result += c;
currentPatternPos++;
} else {
if (c == pattern[currentPatternPos]) {
matchedDigits++;
result += c;
currentPatternPos++;
} else {
isFailedMatch = true;
break;
}
}
}
if (!isFailedMatch && matchedDigits >= maxMatchedDigits) {
maxMatchedDigits = matchedDigits;
formattedResult = std::move(result);
}
}
return FormatResult{ .formatted = formattedResult };
}
CountriesInstance &Instance() { CountriesInstance &Instance() {
return SingleInstance; return SingleInstance;
} }

View file

@ -25,6 +25,14 @@ struct Info {
bool isHidden = false; bool isHidden = false;
}; };
struct FormatResult {
QString formatted;
};
struct FormatArgs {
QString phone;
};
class CountriesInstance final { class CountriesInstance final {
public: public:
using Map = QHash<QString, const Info *>; using Map = QHash<QString, const Info *>;
@ -40,6 +48,8 @@ public:
[[nodiscard]] QString countryNameByISO2(const QString &iso); [[nodiscard]] QString countryNameByISO2(const QString &iso);
[[nodiscard]] QString countryISO2ByPhone(const QString &phone); [[nodiscard]] QString countryISO2ByPhone(const QString &phone);
[[nodiscard]] FormatResult format(FormatArgs args);
private: private:
std::vector<Info> _list; std::vector<Info> _list;