Rewrite code to be more efficient

This commit is contained in:
Yorick de Wid 2020-10-24 23:24:17 +02:00
parent 7a8dc557b7
commit 33b40f623c
3 changed files with 231 additions and 330 deletions

529
iban.cpp
View File

@ -28,12 +28,8 @@ extern "C"
} }
#include <string>
#include <regex> #include <regex>
#include "specification.h"
#include "validate.h"
extern "C" extern "C"
{ {
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
@ -41,9 +37,41 @@ extern "C"
using Iban = char; using Iban = char;
} }
void Validate::addSpecification(Specification* specPtr) { class Specification {
this->specifications[specPtr->countryCode] = specPtr; public:
} Specification(std::string structure, size_t length)
: structure{ structure }
, m_length{ length }
{
};
inline size_t getLength() const noexcept
{
return m_length;
}
std::string structure;
private:
size_t m_length;
};
class Validate {
public:
Validate();
bool isValid(std::string arg);
void addSpecification(std::string countryCode, size_t length, std::string structure) noexcept
{
specifications.emplace(countryCode, std::make_unique<Specification>(structure, length));
}
std::map<std::string, std::unique_ptr<Specification>> specifications;
};
/* Validator global instance. */
static Validate validator;
/** /**
* Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064. * Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064.
@ -51,7 +79,7 @@ void Validate::addSpecification(Specification* specPtr) {
* @param string iban * @param string iban
* @returns {bool} * @returns {bool}
*/ */
bool iso7064Mod97_10(std::string iBan) { static bool iso7064Mod97_10(std::string iBan) {
std::rotate(iBan.begin(), iBan.begin() + 4, iBan.end()); std::rotate(iBan.begin(), iBan.begin() + 4, iBan.end());
std::string numberstring;//will contain the letter substitutions std::string numberstring;//will contain the letter substitutions
@ -75,8 +103,9 @@ bool iso7064Mod97_10(std::string iBan) {
number = std::stol(prepended + numberstring.substr(segstart, step)); number = std::stol(prepended + numberstring.substr(segstart, step));
int remainder = number % 97; int remainder = number % 97;
prepended = std::to_string(remainder); prepended = std::to_string(remainder);
if (remainder < 10) if (remainder < 10) {
prepended = "0" + prepended; prepended = "0" + prepended;
}
segstart = segstart + step; segstart = segstart + step;
step = 7; step = 7;
} }
@ -93,7 +122,7 @@ bool iso7064Mod97_10(std::string iBan) {
* @param {string} structure the structure to parse * @param {string} structure the structure to parse
* @returns {regexp} * @returns {regexp}
*/ */
std::regex parseStructure(std::string structure) { static std::regex parseStructure(std::string structure) {
std::smatch match; std::smatch match;
std::string::const_iterator text_iter = structure.cbegin(); std::string::const_iterator text_iter = structure.cbegin();
@ -124,301 +153,205 @@ std::regex parseStructure(std::string structure) {
return std::regex(regex.c_str()); return std::regex(regex.c_str());
} }
bool Validate::isValid(std::string arg) { bool Validate::isValid(std::string account) {
Specification* spec = new Specification(arg);
/* Convert uppercase */ /* Convert uppercase */
std::transform(spec->example.begin(), spec->example.end(), std::transform(account.begin(), account.end(), account.begin(), toupper);
spec->example.begin(), toupper);
/* Reject anything too small */
if (account.length() < 3) {
return false;
}
/* Match on country */ /* Match on country */
spec->countryCode = spec->example.substr(0, 2); const std::string& countryCode = account.substr(0, 2);
spec->length = spec->example.length(); const std::string& shortened = account.substr(4);
Specification* specFound = this->specifications[spec->countryCode];
const std::unique_ptr<Specification>& specFound = this->specifications[countryCode];
if (!specFound) { if (!specFound) {
return false; return false;
} }
/* Test accountnumber */ /* Test accountnumber */
std::string shortened = spec->example.substr(4, spec->example.length()); return specFound->getLength() == account.length()
bool result = specFound->length == spec->length
&& specFound->countryCode.compare(spec->countryCode) == 0
&& std::regex_match(shortened, parseStructure(specFound->structure)) && std::regex_match(shortened, parseStructure(specFound->structure))
&& iso7064Mod97_10(spec->example); && iso7064Mod97_10(account);
delete spec;
return result;
}
Validate::~Validate() {
for (auto it = specifications.begin(); it != specifications.end(); it++) {
delete it->second;
}
} }
Validate::Validate() { Validate::Validate() {
addSpecification(new Specification( addSpecification(
"AD", 24, "F04F04A12", "AD", 24, "F04F04A12");
"AD1200012030200359100100")); addSpecification(
addSpecification(new Specification( "AE", 23, "F03F16");
"AE", 23, "F03F16", addSpecification(
"AE070331234567890123456")); "AL", 28, "F08A16");
addSpecification(new Specification( addSpecification(
"AL", 28, "F08A16", "AT", 20, "F05F11");
"AL47212110090000000235698741")); addSpecification(
addSpecification(new Specification( "AZ", 28, "U04A20");
"AT", 20, "F05F11", addSpecification(
"AT611904300234573201")); "BA", 20, "F03F03F08F02");
addSpecification(new Specification( addSpecification(
"AZ", 28, "U04A20", "BE", 16, "F03F07F02");
"AZ21NABZ00000000137010001944")); addSpecification(
addSpecification(new Specification( "BG", 22, "U04F04F02A08");
"BA", 20, "F03F03F08F02", addSpecification(
"BA391290079401028494")); "BH", 22, "U04A14");
addSpecification(new Specification( addSpecification(
"BE", 16, "F03F07F02", "BR", 29, "F08F05F10U01A01");
"BE68539007547034")); addSpecification(
addSpecification(new Specification( "CH", 21, "F05A12");
"BG", 22, "U04F04F02A08", addSpecification(
"BG80BNBG96611020345678")); "CR", 21, "F03F14");
addSpecification(new Specification( addSpecification(
"BH", 22, "U04A14", "CY", 28, "F03F05A16");
"BH67BMAG00001299123456")); addSpecification(
addSpecification(new Specification( "CZ", 24, "F04F06F10");
"BR", 29, "F08F05F10U01A01", addSpecification(
"BR9700360305000010009795493P1")); "DE", 22, "F08F10");
addSpecification(new Specification( addSpecification(
"CH", 21, "F05A12", "DK", 18, "F04F09F01");
"CH9300762011623852957")); addSpecification(
addSpecification(new Specification( "DO", 28, "U04F20");
"CR", 21, "F03F14", addSpecification(
"CR0515202001026284066")); "EE", 20, "F02F02F11F01");
addSpecification(new Specification( addSpecification(
"CY", 28, "F03F05A16", "ES", 24, "F04F04F01F01F10");
"CY17002001280000001200527600")); addSpecification(
addSpecification(new Specification( "FI", 18, "F06F07F01");
"CZ", 24, "F04F06F10", addSpecification(
"CZ6508000000192000145399")); "FO", 18, "F04F09F01");
addSpecification(new Specification( addSpecification(
"DE", 22, "F08F10", "FR", 27, "F05F05A11F02");
"DE89370400440532013000")); addSpecification(
addSpecification(new Specification( "GB", 22, "U04F06F08");
"DK", 18, "F04F09F01", addSpecification(
"DK5000400440116243")); "GE", 22, "U02F16");
addSpecification(new Specification( addSpecification(
"DO", 28, "U04F20", "GI", 23, "U04A15");
"DO28BAGR00000001212453611324")); addSpecification(
addSpecification(new Specification( "GL", 18, "F04F09F01");
"EE", 20, "F02F02F11F01", addSpecification(
"EE382200221020145685")); "GR", 27, "F03F04A16");
addSpecification(new Specification( addSpecification(
"ES", 24, "F04F04F01F01F10", "GT", 28, "A04A20");
"ES9121000418450200051332")); addSpecification(
addSpecification(new Specification( "HR", 21, "F07F10");
"FI", 18, "F06F07F01", addSpecification(
"FI2112345600000785")); "HU", 28, "F03F04F01F15F01");
addSpecification(new Specification( addSpecification(
"FO", 18, "F04F09F01", "IE", 22, "U04F06F08");
"FO6264600001631634")); addSpecification(
addSpecification(new Specification( "IL", 23, "F03F03F13");
"FR", 27, "F05F05A11F02", addSpecification(
"FR1420041010050500013M02606")); "IS", 26, "F04F02F06F10");
addSpecification(new Specification( addSpecification(
"GB", 22, "U04F06F08", "IT", 27, "U01F05F05A12");
"GB29NWBK60161331926819")); addSpecification(
addSpecification(new Specification( "KW", 30, "U04A22");
"GE", 22, "U02F16", addSpecification(
"GE29NB0000000101904917")); "KZ", 20, "F03A13");
addSpecification(new Specification( addSpecification(
"GI", 23, "U04A15", "LB", 28, "F04A20");
"GI75NWBK000000007099453")); addSpecification(
addSpecification(new Specification( "LC", 32, "U04F24");
"GL", 18, "F04F09F01", addSpecification(
"GL8964710001000206")); "LI", 21, "F05A12");
addSpecification(new Specification( addSpecification(
"GR", 27, "F03F04A16", "LT", 20, "F05F11");
"GR1601101250000000012300695")); addSpecification(
addSpecification(new Specification( "LU", 20, "F03A13");
"GT", 28, "A04A20", addSpecification(
"GT82TRAJ01020000001210029690")); "LV", 21, "U04A13");
addSpecification(new Specification( addSpecification(
"HR", 21, "F07F10", "MC", 27, "F05F05A11F02");
"HR1210010051863000160")); addSpecification(
addSpecification(new Specification( "MD", 24, "U02A18");
"HU", 28, "F03F04F01F15F01", addSpecification(
"HU42117730161111101800000000")); "ME", 22, "F03F13F02");
addSpecification(new Specification( addSpecification(
"IE", 22, "U04F06F08", "MK", 19, "F03A10F02");
"IE29AIBK93115212345678")); addSpecification(
addSpecification(new Specification( "MR", 27, "F05F05F11F02");
"IL", 23, "F03F03F13", addSpecification(
"IL620108000000099999999")); "MT", 31, "U04F05A18");
addSpecification(new Specification( addSpecification(
"IS", 26, "F04F02F06F10", "MU", 30, "U04F02F02F12F03U03");
"IS140159260076545510730339")); addSpecification(
addSpecification(new Specification( "NL", 18, "U04F10");
"IT", 27, "U01F05F05A12", addSpecification(
"IT60X0542811101000000123456")); "NO", 15, "F04F06F01");
addSpecification(new Specification( addSpecification(
"KW", 30, "U04A22", "PK", 24, "U04A16");
"KW81CBKU0000000000001234560101")); addSpecification(
addSpecification(new Specification( "PL", 28, "F08F16");
"KZ", 20, "F03A13", addSpecification(
"KZ86125KZT5004100100")); "PS", 29, "U04A21");
addSpecification(new Specification( addSpecification(
"LB", 28, "F04A20", "PT", 25, "F04F04F11F02");
"LB62099900000001001901229114")); addSpecification(
addSpecification(new Specification( "RO", 24, "U04A16");
"LC", 32, "U04F24", addSpecification(
"LC07HEMM000100010012001200013015")); "RS", 22, "F03F13F02");
addSpecification(new Specification( addSpecification(
"LI", 21, "F05A12", "SA", 24, "F02A18");
"LI21088100002324013AA")); addSpecification(
addSpecification(new Specification( "SE", 24, "F03F16F01");
"LT", 20, "F05F11", addSpecification(
"LT121000011101001000")); "SI", 19, "F05F08F02");
addSpecification(new Specification( addSpecification(
"LU", 20, "F03A13", "SK", 24, "F04F06F10");
"LU280019400644750000")); addSpecification(
addSpecification(new Specification( "SM", 27, "U01F05F05A12");
"LV", 21, "U04A13", addSpecification(
"LV80BANK0000435195001")); "ST", 25, "F08F11F02");
addSpecification(new Specification( addSpecification(
"MC", 27, "F05F05A11F02", "TL", 23, "F03F14F02");
"MC5811222000010123456789030")); addSpecification(
addSpecification(new Specification( "TN", 24, "F02F03F13F02");
"MD", 24, "U02A18", addSpecification(
"MD24AG000225100013104168")); "TR", 26, "F05F01A16");
addSpecification(new Specification( addSpecification(
"ME", 22, "F03F13F02", "VG", 24, "U04F16");
"ME25505000012345678951")); addSpecification(
addSpecification(new Specification( "XK", 20, "F04F10F02");
"MK", 19, "F03A10F02", addSpecification(
"MK07250120000058984")); "AO", 25, "F21");
addSpecification(new Specification( addSpecification(
"MR", 27, "F05F05F11F02", "BF", 27, "F23");
"MR1300020001010000123456753")); addSpecification(
addSpecification(new Specification( "BI", 16, "F12");
"MT", 31, "U04F05A18", addSpecification(
"MT84MALT011000012345MTLCAST001S")); "BJ", 28, "F24");
addSpecification(new Specification( addSpecification(
"MU", 30, "U04F02F02F12F03U03", "CI", 28, "U01F23");
"MU17BOMM0101101030300200000MUR")); addSpecification(
addSpecification(new Specification( "CM", 27, "F23");
"NL", 18, "U04F10", addSpecification(
"NL91ABNA0417164300")); "CV", 25, "F21");
addSpecification(new Specification( addSpecification(
"NO", 15, "F04F06F01", "DZ", 24, "F20");
"NO9386011117947")); addSpecification(
addSpecification(new Specification( "IR", 26, "F22");
"PK", 24, "U04A16", addSpecification(
"PK36SCBL0000001123456702")); "JO", 30, "A04F22");
addSpecification(new Specification( addSpecification(
"PL", 28, "F08F16", "MG", 27, "F23");
"PL61109010140000071219812874")); addSpecification(
addSpecification(new Specification( "ML", 28, "U01F23");
"PS", 29, "U04A21", addSpecification(
"PS92PALS000000000400123456702")); "MZ", 25, "F21");
addSpecification(new Specification( addSpecification(
"PT", 25, "F04F04F11F02", "QA", 29, "U04A21");
"PT50000201231234567890154")); addSpecification(
addSpecification(new Specification( "SN", 28, "U01F23");
"RO", 24, "U04A16", addSpecification(
"RO49AAAA1B31007593840000")); "UA", 29, "F25");
addSpecification(new Specification( addSpecification(
"RS", 22, "F03F13F02", "EG", 27, "F23");
"RS35260005601001611379")); addSpecification(
addSpecification(new Specification( "CG", 27, "F23");
"SA", 24, "F02A18", addSpecification(
"SA0380000000608010167519")); "GA", 27, "F23");
addSpecification(new Specification(
"SE", 24, "F03F16F01",
"SE4550000000058398257466"));
addSpecification(new Specification(
"SI", 19, "F05F08F02",
"SI56263300012039086"));
addSpecification(new Specification(
"SK", 24, "F04F06F10",
"SK3112000000198742637541"));
addSpecification(new Specification(
"SM", 27, "U01F05F05A12",
"SM86U0322509800000000270100"));
addSpecification(new Specification(
"ST", 25, "F08F11F02",
"ST68000100010051845310112"));
addSpecification(new Specification(
"TL", 23, "F03F14F02",
"TL380080012345678910157"));
addSpecification(new Specification(
"TN", 24, "F02F03F13F02",
"TN5910006035183598478831"));
addSpecification(new Specification(
"TR", 26, "F05F01A16",
"TR330006100519786457841326"));
addSpecification(new Specification(
"VG", 24, "U04F16",
"VG96VPVG0000012345678901"));
addSpecification(new Specification(
"XK", 20, "F04F10F02",
"XK051212012345678906"));
addSpecification(new Specification(
"AO", 25, "F21",
"AO69123456789012345678901"));
addSpecification(new Specification(
"BF", 27, "F23",
"BF2312345678901234567890123"));
addSpecification(new Specification(
"BI", 16, "F12",
"BI41123456789012"));
addSpecification(new Specification(
"BJ", 28, "F24",
"BJ39123456789012345678901234"));
addSpecification(new Specification(
"CI", 28, "U01F23",
"CI17A12345678901234567890123"));
addSpecification(new Specification(
"CM", 27, "F23",
"CM9012345678901234567890123"));
addSpecification(new Specification(
"CV", 25, "F21",
"CV30123456789012345678901"));
addSpecification(new Specification(
"DZ", 24, "F20",
"DZ8612345678901234567890"));
addSpecification(new Specification(
"IR", 26, "F22",
"IR861234568790123456789012"));
addSpecification(new Specification(
"JO", 30, "A04F22",
"JO15AAAA1234567890123456789012"));
addSpecification(new Specification(
"MG", 27, "F23",
"MG1812345678901234567890123"));
addSpecification(new Specification(
"ML", 28, "U01F23",
"ML15A12345678901234567890123"));
addSpecification(new Specification(
"MZ", 25, "F21",
"MZ25123456789012345678901"));
addSpecification(new Specification(
"QA", 29, "U04A21",
"QA30AAAA123456789012345678901"));
addSpecification(new Specification(
"SN", 28, "U01F23",
"SN52A12345678901234567890123"));
addSpecification(new Specification(
"UA", 29, "F25",
"UA511234567890123456789012345"));
addSpecification(new Specification(
"EG", 27, "F23",
"EG1100006001880800100014553"));
addSpecification(new Specification(
"CG", 27, "F23",
"CG5230011000202151234567890"));
addSpecification(new Specification(
"GA", 27, "F23",
"GA2140002000055602673300064"));
} }
/** /**
@ -430,15 +363,15 @@ Validate::Validate() {
* @returns {bool} * @returns {bool}
*/ */
namespace { namespace {
bool account_validate_text(text *iban) { bool account_validate_text(text *iban) {
char *ciban; char *ciban;
bool result; bool result;
Validate val;
ciban = text_to_cstring(iban); ciban = text_to_cstring(iban);
try { try {
result = val.isValid(std::string(ciban)); result = validator.isValid(ciban);
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -449,10 +382,9 @@ bool account_validate_text(text *iban) {
bool account_validate_str(char *iban) { bool account_validate_str(char *iban) {
bool result; bool result;
Validate val;
try { try {
result = val.isValid(std::string(iban)); result = validator.isValid(iban);
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -460,7 +392,8 @@ bool account_validate_str(char *iban) {
return result; return result;
} }
}
} // namespace
extern "C" extern "C"
{ {

View File

@ -1,18 +0,0 @@
#pragma once
#include <string>
class Specification {
public:
Specification(std::string countryCode, int length, std::string structure, std::string example) :
countryCode(countryCode),
length(length),
structure(structure),
example(example) {
};
Specification(std::string example) : example(example) {};
std::string countryCode;
int length;
std::string structure;
std::string example;
};

View File

@ -1,14 +0,0 @@
#pragma once
#include <memory>
#include <map>
#include "specification.h"
class Validate {
public:
Validate();
~Validate();
bool isValid(std::string arg);
void addSpecification(Specification* specPtr);
std::map<std::string, Specification*> specifications;
};