validation_FR_INSEE.c (2333B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2022 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file reducer/validation_FR_INSEE.c 18 * @brief Validation for French INSEE Numbers 19 * @author Christian Grothoff 20 */ 21 #include <string.h> 22 #include <stdbool.h> 23 #include <stdio.h> 24 25 26 /** 27 * Function to validate a French INSEE number. 28 * 29 * See https://en.wikipedia.org/wiki/INSEE_code 30 * 31 * Note that we do not implement checks on the month 32 * and also allow non-binary prefixes. Corsican numbers carry 2A or 2B in 33 * the department field and are accepted. 34 * 35 * @param insee_number social security number to validate (input) 36 * @return true if validation passed, else false 37 */ 38 bool 39 FR_INSEE_check (const char *insee_number); 40 41 /* declaration to fix compiler warning */ 42 bool 43 FR_INSEE_check (const char *insee_number) 44 { 45 char pfx[14]; 46 unsigned long long num; 47 unsigned int cc; 48 char dum; 49 50 if (strlen (insee_number) != 15) 51 return false; 52 memcpy (pfx, 53 insee_number, 54 13); 55 pfx[13] = '\0'; 56 /* Corsica carries a letter in the department field (positions 5-6): the 57 official rule is to substitute 2A -> 19 and 2B -> 18 before the mod-97, 58 since the remaining digits alone would collide between the two. */ 59 if ('2' == pfx[5]) 60 { 61 if ('A' == pfx[6]) 62 { 63 pfx[5] = '1'; 64 pfx[6] = '9'; 65 } 66 else if ('B' == pfx[6]) 67 { 68 pfx[5] = '1'; 69 pfx[6] = '8'; 70 } 71 } 72 if (1 != 73 sscanf (pfx, 74 "%llu%c", 75 &num, 76 &dum)) 77 return false; 78 if (1 != 79 sscanf (&insee_number[13], 80 "%u%c", 81 &cc, 82 &dum)) 83 return false; 84 if (97 - cc != num % 97) 85 return false; 86 return true; 87 }