/*
This file is part of Anastasis
Copyright (C) 2021 Anastasis SARL
Anastasis is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with
Anastasis; see the file COPYING.GPL. If not, see
*/
/**
* @file reducer/validation_IT_CF.c
* @brief validation of Italian Code Fiscales
* @author Christian Grothoff
*/
#include
#include
#include
#include
struct MapEntry
{
char in;
unsigned int out;
};
static const struct MapEntry odd[] = {
{ '0', 1},
{ '9', 21},
{ 'I', 19 },
{ 'R', 8},
{ '1', 0},
{ 'A', 1},
{ 'J', 21},
{ 'S', 12},
{'2', 5},
{'B', 0},
{'K', 2},
{'T', 14},
{'3', 7},
{'C', 5},
{'L', 4},
{'U', 16},
{'4', 9},
{'D', 7},
{'M', 18},
{'V', 10},
{'5', 13},
{'E', 9},
{'N', 20},
{'W', 22},
{'6', 15},
{'F', 13},
{'O', 11},
{'X', 25},
{'7', 17},
{'G', 15},
{'P', 3},
{'Y', 24},
{'8', 19},
{'H', 17},
{'Q', 6},
{'Z', 23},
{'\0', 0}
};
static const struct MapEntry even[] = {
{ '0', 0},
{ '1', 1},
{ '2', 2 },
{ '3', 3},
{ '4', 4},
{ '5', 5},
{ '6', 6 },
{ '7', 7 },
{'8', 8},
{'9', 9},
{'A', 0},
{'B', 1},
{'C', 2},
{'D', 3},
{'E', 4},
{'F', 5},
{'G', 6},
{'H', 7},
{'I', 8},
{'J', 9},
{'K', 10},
{'L', 11},
{'M', 12},
{'N', 13},
{'O', 14},
{'P', 15},
{'Q', 16},
{'R', 17},
{'S', 18},
{'T', 19},
{'U', 20},
{'V', 21},
{'W', 22},
{'X', 23},
{'Y', 24},
{'Z', 25},
{'\0', 0}
};
static const struct MapEntry rem[] = {
{'A', 0},
{'B', 1},
{'C', 2},
{'D', 3},
{'E', 4},
{'F', 5},
{'G', 6},
{'H', 7},
{'I', 8},
{'J', 9},
{'K', 10},
{'L', 11},
{'M', 12},
{'N', 13},
{'O', 14},
{'P', 15},
{'Q', 16},
{'R', 17},
{'S', 18},
{'T', 19},
{'U', 20},
{'V', 21},
{'W', 22},
{'X', 23},
{'Y', 24},
{'Z', 25},
{'\0', 0}
};
/**
* Lookup @a in in @a map. Set @a fail to true if @a in is not found.
*
* @param map character map to search
* @param in character to search for
* @param[out] fail set to true on error
* @return map value, 0 on error
*/
static unsigned int
lookup (const struct MapEntry *map,
char in,
bool *fail)
{
for (unsigned int i = 0; '\0' != map[i].in; i++)
if (in == map[i].in)
return map[i].out;
*fail = true;
return 0;
}
/**
* Function to validate an italian code fiscale number.
* See https://en.wikipedia.org/wiki/Italian_fiscal_code
*
* @param cf_number square number to validate (input)
* @return true if @a cf_number is a valid, else false
*/
bool
IT_CF_check (const char *cf_number)
{
unsigned int sum = 0;
bool fail = false;
if (strlen (cf_number) != 16)
return false;
for (unsigned int i = 0; i<15; i += 2)
sum += lookup (odd,
cf_number[i],
&fail);
for (unsigned int i = 1; i<15; i += 2)
sum += lookup (even,
cf_number[i],
&fail);
sum %= 26;
if (sum != lookup (rem,
cf_number[15],
&fail))
return false;
if (fail)
return false;
return true;
}