78 lines
3.0 KiB
C++
78 lines
3.0 KiB
C++
#include <string>
|
|
#include <iostream>
|
|
#include <boost/algorithm/string.hpp>
|
|
#include <map>
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
using namespace boost::algorithm ;
|
|
|
|
bool isValid ( const std::string &ibanstring )
|
|
{
|
|
static std::map<std::string, int> countrycodes
|
|
{ {"AL" , 28} , {"AD" , 24} , {"AT" , 20} , {"AZ" , 28 } ,
|
|
{"BE" , 16} , {"BH" , 22} , {"BA" , 20} , {"BR" , 29 } ,
|
|
{"BG" , 22} , {"CR" , 21} , {"HR" , 21} , {"CY" , 28 } ,
|
|
{"CZ" , 24} , {"DK" , 18} , {"DO" , 28} , {"EE" , 20 } ,
|
|
{"FO" , 18} , {"FI" , 18} , {"FR" , 27} , {"GE" , 22 } ,
|
|
{"DE" , 22} , {"GI" , 23} , {"GR" , 27} , {"GL" , 18 } ,
|
|
{"GT" , 28} , {"HU" , 28} , {"IS" , 26} , {"IE" , 22 } ,
|
|
{"IL" , 23} , {"IT" , 27} , {"KZ" , 20} , {"KW" , 30 } ,
|
|
{"LV" , 21} , {"LB" , 28} , {"LI" , 21} , {"LT" , 20 } ,
|
|
{"LU" , 20} , {"MK" , 19} , {"MT" , 31} , {"MR" , 27 } ,
|
|
{"MU" , 30} , {"MC" , 27} , {"MD" , 24} , {"ME" , 22 } ,
|
|
{"NL" , 18} , {"NO" , 15} , {"PK" , 24} , {"PS" , 29 } ,
|
|
{"PL" , 28} , {"PT" , 25} , {"RO" , 24} , {"SM" , 27 } ,
|
|
{"SA" , 24} , {"RS" , 22} , {"SK" , 24} , {"SI" , 19 } ,
|
|
{"ES" , 24} , {"SE" , 24} , {"CH" , 21} , {"TN" , 24 } ,
|
|
{"TR" , 26} , {"AE" , 23} , {"GB" , 22} , {"VG" , 24 } } ;
|
|
std::string teststring( ibanstring ) ;
|
|
erase_all( teststring , " " ) ; //defined in boost/algorithm/string.hpp
|
|
if ( countrycodes.find( teststring.substr(0 , 2 )) == countrycodes.end( ) )
|
|
return false ;
|
|
if ( teststring.length( ) != countrycodes[ teststring.substr( 0 , 2 ) ] )
|
|
return false ;
|
|
if (!all(teststring, is_alnum()))
|
|
return false ;
|
|
to_upper( teststring ) ;
|
|
std::rotate(teststring.begin(), teststring.begin() + 4, teststring.end());
|
|
|
|
std::string numberstring ;//will contain the letter substitutions
|
|
for (const auto& c : teststring)
|
|
{
|
|
if (std::isdigit(c))
|
|
numberstring += c ;
|
|
if (std::isupper(c))
|
|
numberstring += std::to_string(static_cast<int>(c) - 55);
|
|
}
|
|
//implements a stepwise check for mod 97 in chunks of 9 at the first time
|
|
// , then in chunks of seven prepended by the last mod 97 operation converted
|
|
//to a string
|
|
int segstart = 0 ;
|
|
int step = 9 ;
|
|
std::string prepended ;
|
|
long number = 0 ;
|
|
while ( segstart < numberstring.length( ) - step ) {
|
|
number = std::stol( prepended + numberstring.substr( segstart , step ) ) ;
|
|
int remainder = number % 97 ;
|
|
prepended = std::to_string( remainder ) ;
|
|
if ( remainder < 10 )
|
|
prepended = "0" + prepended ;
|
|
segstart = segstart + step ;
|
|
step = 7 ;
|
|
}
|
|
number = std::stol( prepended + numberstring.substr( segstart )) ;
|
|
return ( number % 97 == 1 ) ;
|
|
}
|
|
|
|
void SayValidity(const std::string& iban)
|
|
{
|
|
std::cout << iban << (isValid(iban) ? " is " : " is not ") << "valid\n";
|
|
}
|
|
|
|
int main( )
|
|
{
|
|
SayValidity("GB82 WEST 1234 5698 7654 32");
|
|
SayValidity("GB82TEST12345698765432");
|
|
return 0 ;
|
|
}
|