parser: refine IBAN checking
Allow arbitrary spacing, minor optimizations... Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
b5984ea8f2
commit
613bba9e05
@ -205,11 +205,47 @@ namespace UnitTests
|
||||
Assert::IsTrue(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"SI56 0231 2001 5226 9720", 0, SIZE_MAX));
|
||||
Assert::IsFalse(p.is_valid);
|
||||
Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); // no-break space
|
||||
Assert::IsTrue(p.is_valid);
|
||||
|
||||
Assert::IsTrue(p.match(L"BE71 0961 2345 6769", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"BR15 0000 0000 0000 1093 2840 814 P2", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"CR99 0000 0000 0000 8888 88", 0, SIZE_MAX));
|
||||
Assert::IsFalse(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"FR76 3000 6000 0112 3456 7890 189", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"IE12 BOFI 9000 0112 3456 78", 0, SIZE_MAX));
|
||||
Assert::IsFalse(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"DE91 1000 0000 0123 4567 89", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"GR96 0810 0010 0000 0123 4567 890", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"MU43 BOMM 0101 1234 5678 9101 000 MUR", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"PK70 BANK 0000 1234 5678 9000", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"PL10 1050 0099 7603 1234 5678 9123", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"RO09 BCYP 0000 0012 3456 7890", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"LC14 BOSL 1234 5678 9012 3456 7890 1234", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"SA44 2000 0001 2345 6789 1234", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"ES79 2100 0813 6101 2345 6789", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"SE87 3000 0000 0101 2345 6789", 0, SIZE_MAX));
|
||||
Assert::IsFalse(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"CH56 0483 5012 3456 7800 9", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match(L"GB98 MIDL 0700 9312 3456 78", 0, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
}
|
||||
|
||||
{
|
||||
@ -322,7 +358,8 @@ namespace UnitTests
|
||||
Assert::IsTrue(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match("SI56 0231 2001 5226 9720", 0, SIZE_MAX));
|
||||
Assert::IsFalse(p.is_valid);
|
||||
Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match("...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
|
||||
Assert::IsTrue(p.is_valid);
|
||||
Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX));
|
||||
|
@ -4806,7 +4806,8 @@ namespace stdex
|
||||
{ { 'X', 'K' }, {}, 20 }, // Kosovo
|
||||
};
|
||||
const country_t* country_desc = nullptr;
|
||||
size_t n;
|
||||
size_t n, available, next, bban_length;
|
||||
uint32_t nominator;
|
||||
|
||||
this->interval.end = start;
|
||||
for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
|
||||
@ -4844,32 +4845,28 @@ namespace stdex
|
||||
(country_desc->check_digits[1] && this->check_digits[1] != country_desc->check_digits[1]))
|
||||
goto error; // unexpected check digits
|
||||
|
||||
for (n = 0; ;) {
|
||||
if (m_space && m_space->match(text, this->interval.end, end, flags))
|
||||
this->interval.end = m_space->interval.end;
|
||||
for (size_t j = 0; j < 4; ++j) {
|
||||
bban_length = country_desc->length - 4;
|
||||
for (n = 0; n < bban_length;) {
|
||||
if (this->interval.end >= end || !text[this->interval.end])
|
||||
goto out;
|
||||
goto error; // bban too short
|
||||
if (m_space && m_space->match(text, this->interval.end, end, flags)) {
|
||||
this->interval.end = m_space->interval.end;
|
||||
continue;
|
||||
}
|
||||
T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
|
||||
if (('0' <= chr && chr <= '9') || ('A' <= chr && chr <= 'Z')) {
|
||||
if (n >= _countof(this->bban) - 1)
|
||||
goto error; // bban overflow
|
||||
this->bban[n++] = chr;
|
||||
this->interval.end++;
|
||||
}
|
||||
else
|
||||
goto out;
|
||||
}
|
||||
goto error; // invalid bban
|
||||
}
|
||||
out:
|
||||
if (n < 11)
|
||||
goto error; // bban too short (shorter than Norwegian)
|
||||
this->bban[n] = 0;
|
||||
|
||||
if (n + 4 == country_desc->length) {
|
||||
// Normalize IBAN.
|
||||
T normalized[69];
|
||||
size_t available = 0;
|
||||
available = 0;
|
||||
for (size_t i = 0; ; ++i) {
|
||||
if (!this->bban[i]) {
|
||||
for (i = 0; i < 2; ++i) {
|
||||
@ -4908,21 +4905,17 @@ namespace stdex
|
||||
}
|
||||
|
||||
// Calculate modulo 97.
|
||||
size_t next;
|
||||
uint32_t nominator = stdex::strtou32(normalized, 9, &next, 10);
|
||||
nominator = stdex::strtou32(normalized, 9, &next, 10);
|
||||
for (;;) {
|
||||
nominator %= 97;
|
||||
if (!normalized[next]) {
|
||||
this->is_valid = nominator == 1;
|
||||
break;
|
||||
}
|
||||
size_t digit_count = nominator < 10 ? 1 : 2;
|
||||
size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
|
||||
for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
|
||||
nominator = nominator * 10 + (normalized[next] - '0');
|
||||
}
|
||||
}
|
||||
else
|
||||
this->is_valid = false;
|
||||
|
||||
this->interval.start = start;
|
||||
return true;
|
||||
@ -5074,7 +5067,7 @@ namespace stdex
|
||||
this->is_valid = nominator == 1;
|
||||
break;
|
||||
}
|
||||
size_t digit_count = nominator < 10 ? 1 : 2;
|
||||
size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
|
||||
for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
|
||||
nominator = nominator * 10 + (normalized[next] - '0');
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user