103 lines
2.5 KiB
C++
103 lines
2.5 KiB
C++
#include "common/Validation.h"
|
|
|
|
#include <array>
|
|
#include <cctype>
|
|
#include <regex>
|
|
|
|
namespace visione::validation
|
|
{
|
|
namespace
|
|
{
|
|
char normalizeFiscalCodeChar(char ch)
|
|
{
|
|
return static_cast<char>(
|
|
std::toupper(static_cast<unsigned char>(ch)));
|
|
}
|
|
|
|
int fiscalCodeControlValueForOdd(char ch)
|
|
{
|
|
static constexpr std::array<int, 26> letterValues{
|
|
1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18,
|
|
20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23};
|
|
static constexpr std::array<int, 10> digitValues{1, 0, 5, 7, 9,
|
|
13, 15, 17, 19, 21};
|
|
|
|
if (std::isdigit(static_cast<unsigned char>(ch)))
|
|
{
|
|
return digitValues[static_cast<size_t>(ch - '0')];
|
|
}
|
|
return letterValues[static_cast<size_t>(ch - 'A')];
|
|
}
|
|
|
|
int fiscalCodeControlValueForEven(char ch)
|
|
{
|
|
if (std::isdigit(static_cast<unsigned char>(ch)))
|
|
{
|
|
return ch - '0';
|
|
}
|
|
return ch - 'A';
|
|
}
|
|
} // namespace
|
|
|
|
bool hasString(const Json::Value &body, const std::string &key)
|
|
{
|
|
return body.isMember(key) && body[key].isString() &&
|
|
!body[key].asString().empty();
|
|
}
|
|
|
|
bool hasNumber(const Json::Value &body, const std::string &key)
|
|
{
|
|
return body.isMember(key) && body[key].isNumeric();
|
|
}
|
|
|
|
std::vector<std::string> missingStrings(
|
|
const Json::Value &body,
|
|
std::initializer_list<const char *> keys)
|
|
{
|
|
std::vector<std::string> missing;
|
|
for (const auto *key : keys)
|
|
{
|
|
if (!hasString(body, key))
|
|
{
|
|
missing.emplace_back(key);
|
|
}
|
|
}
|
|
return missing;
|
|
}
|
|
|
|
bool isValidEmail(const std::string &email)
|
|
{
|
|
static const std::regex pattern(R"(^[^@\s]+@[^@\s]+\.[^@\s]+$)");
|
|
return std::regex_match(email, pattern);
|
|
}
|
|
|
|
bool isValidFiscalCode(const std::string &fiscalCode)
|
|
{
|
|
static const std::regex pattern(
|
|
R"(^[A-Za-z]{6}[0-9]{2}[ABCDEHLMPRST]{1}[0-9]{2}[A-Za-z][0-9]{3}[A-Za-z]$)");
|
|
|
|
if (!std::regex_match(fiscalCode, pattern))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string normalized;
|
|
normalized.reserve(fiscalCode.size());
|
|
for (char ch : fiscalCode)
|
|
{
|
|
normalized.push_back(normalizeFiscalCodeChar(ch));
|
|
}
|
|
|
|
int sum = 0;
|
|
for (size_t i = 0; i < normalized.size() - 1; ++i)
|
|
{
|
|
sum += ((i + 1) % 2 == 0) ? fiscalCodeControlValueForEven(normalized[i])
|
|
: fiscalCodeControlValueForOdd(normalized[i]);
|
|
}
|
|
|
|
const char expectedControl =
|
|
static_cast<char>('A' + (sum % 26));
|
|
return normalized.back() == expectedControl;
|
|
}
|
|
} // namespace visione::validation
|