MODULE IBAN; IMPORT Out, Err, ADT:Dictionary, Object:Boxed, Object:BigInt, Object, Strings, IntStr; TYPE IBANLen = Boxed.LongInt; VAR nations: Dictionary.Dictionary(STRING,IBANLen); PROCEDURE Check*(iban: ARRAY OF CHAR): BOOLEAN; VAR country,ibanStr: Object.String; nLetter: ARRAY 3 OF CHAR; block: ARRAY 5 OF CHAR; numIban: ARRAY 256 OF CHAR; num,den,res: BigInt.BigInt; ibanLen: IBANLen; i: LONGINT; BEGIN ibanStr := Object.NewLatin1(iban); country := ibanStr.Substring(0,2); IF ~nations.HasKey(country) THEN Err.Object("Country " + country + " has not IBAN codes. "); RETURN FALSE; END; ibanLen := nations.Get(country); IF SHORT(ibanLen.value) # Strings.Length(iban) THEN Err.Object("IBAN length incorrect for " + country +". "); RETURN FALSE END; block[0] := 0X; Strings.Extract(iban,0,4,block); Strings.Delete(iban,0,4);Strings.Append(block,iban); numIban[0] := 0X; FOR i := 0 TO LEN(iban) - 1 DO nLetter[0] := 0X; IF (iban[i] >= 'A') & (iban[i] <= 'Z') THEN IntStr.IntToStr(ORD(iban[i]) - ORD('A') + 10,nLetter); ELSE nLetter[0] := iban[i]; nLetter[1] := 0X END; Strings.Append(nLetter,numIban); END; Strings.Append(0X,numIban); num := BigInt.New(Object.NewLatin1(numIban),10); den := BigInt.New("97",10); res := num.Mod(den); IF res.Equals(BigInt.one) THEN RETURN TRUE ELSE Err.String("IBAN code check failed. "); RETURN FALSE END END Check; PROCEDURE CodeLengthFor*(country: ARRAY OF CHAR): LONGINT; VAR countryStr: Object.String; ibanLen: IBANLen; BEGIN countryStr := Object.NewLatin1(country); ibanLen := Boxed.zeroLongInt; IF nations.HasKey(countryStr) THEN ibanLen := nations.Get(countryStr) END; RETURN ibanLen.value END CodeLengthFor; PROCEDURE Test*; PROCEDURE DoCheck(iban: ARRAY OF CHAR); BEGIN Out.String("IBAN[");Out.String(iban);Out.String("]=");Out.Bool(Check(iban)); Out.Ln END DoCheck; BEGIN DoCheck("CH9300762011623852957"); DoCheck("GB82WEST12345698765432"); DoCheck("SA0380000000608010167519"); DoCheck("XX0380000000608010167519"); END Test; BEGIN nations := NEW(Dictionary.Dictionary(STRING,Boxed.LongInt)); nations.Set("AL",NEW(IBANLen,28)); nations.Set("AD",NEW(IBANLen,24)); nations.Set("AT",NEW(IBANLen,20)); nations.Set("AZ",NEW(IBANLen,28)); nations.Set("BE",NEW(IBANLen,16)); nations.Set("BH",NEW(IBANLen,22)); nations.Set("BA",NEW(IBANLen,20)); nations.Set("BR",NEW(IBANLen,29)); nations.Set("BG",NEW(IBANLen,22)); nations.Set("CR",NEW(IBANLen,21)); nations.Set("HR",NEW(IBANLen,21)); nations.Set("CY",NEW(IBANLen,28)); nations.Set("CZ",NEW(IBANLen,24)); nations.Set("DK",NEW(IBANLen,18)); nations.Set("DO",NEW(IBANLen,28)); nations.Set("EE",NEW(IBANLen,20)); nations.Set("FO",NEW(IBANLen,18)); nations.Set("FI",NEW(IBANLen,18)); nations.Set("FR",NEW(IBANLen,27)); nations.Set("GE",NEW(IBANLen,22)); nations.Set("DE",NEW(IBANLen,22)); nations.Set("GI",NEW(IBANLen,23)); nations.Set("GR",NEW(IBANLen,27)); nations.Set("GL",NEW(IBANLen,18)); nations.Set("GT",NEW(IBANLen,28)); nations.Set("HU",NEW(IBANLen,28)); nations.Set("IS",NEW(IBANLen,26)); nations.Set("IE",NEW(IBANLen,22)); nations.Set("IL",NEW(IBANLen,23)); nations.Set("IT",NEW(IBANLen,27)); nations.Set("KZ",NEW(IBANLen,20)); nations.Set("KW",NEW(IBANLen,30)); nations.Set("LV",NEW(IBANLen,21)); nations.Set("LB",NEW(IBANLen,28)); nations.Set("LI",NEW(IBANLen,21)); nations.Set("LT",NEW(IBANLen,20)); nations.Set("LU",NEW(IBANLen,20)); nations.Set("MK",NEW(IBANLen,19)); nations.Set("MT",NEW(IBANLen,31)); nations.Set("MR",NEW(IBANLen,27)); nations.Set("MU",NEW(IBANLen,30)); nations.Set("MC",NEW(IBANLen,27)); nations.Set("MD",NEW(IBANLen,24)); nations.Set("ME",NEW(IBANLen,22)); nations.Set("NL",NEW(IBANLen,18)); nations.Set("NO",NEW(IBANLen,15)); nations.Set("PK",NEW(IBANLen,24)); nations.Set("PS",NEW(IBANLen,29)); nations.Set("PL",NEW(IBANLen,28)); nations.Set("PT",NEW(IBANLen,25)); nations.Set("RO",NEW(IBANLen,24)); nations.Set("SM",NEW(IBANLen,27)); nations.Set("SA",NEW(IBANLen,24)); nations.Set("RS",NEW(IBANLen,22)); nations.Set("SK",NEW(IBANLen,24)); nations.Set("SI",NEW(IBANLen,19)); nations.Set("ES",NEW(IBANLen,24)); nations.Set("SE",NEW(IBANLen,24)); nations.Set("CH",NEW(IBANLen,21)); nations.Set("TN",NEW(IBANLen,24)); nations.Set("TR",NEW(IBANLen,26)); nations.Set("AE",NEW(IBANLen,23)); nations.Set("GB",NEW(IBANLen,22)); nations.Set("VG",NEW(IBANLen,24)); Test; END IBAN.