/* * $Id: funcoes.c,v 1.2 2005/05/11 21:58:14 halleypo Exp $ */ #include "postgres.h" /* declarações gerais do PostgreSQL */ #include "fmgr.h" /* macros dos argumentos/resultados */ #define VALOR(char) ((char) - '0') #define DIGITO(val) ((val) + '0') #define VARLAST(__PTR) (VARDATA(__PTR) + VARSIZE(__PTR) - VARHDRSZ - 1) /* Protótipo para prevenir contra possíveis advertências do gcc. */ Datum dv11(PG_FUNCTION_ARGS); Datum dv11dig(PG_FUNCTION_ARGS); Datum dv10(PG_FUNCTION_ARGS); Datum dv10dig(PG_FUNCTION_ARGS); Datum cpf(PG_FUNCTION_ARGS); Datum cnpj(PG_FUNCTION_ARGS); Datum nie(PG_FUNCTION_ARGS); /* * Rotina para cálculo do dígito verificador módulo 11. * Recebe dois argumentos, número e dígito verificador. * Retorna verdade se o dígito verificador estiver * correto, ou falso caso contrário. */ PG_FUNCTION_INFO_V1(dv11); Datum dv11(PG_FUNCTION_ARGS) { int digito=0, fator=2; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número text *dv = PG_GETARG_TEXT_P(1); // Segundo argumento = dígito verificador /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar dígito verificador não dígito */ if (!isdigit(*VARDATA(dv))) PG_RETURN_NULL(); /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito digito += VALOR(*c) * fator; if (++fator > 9) fator = 2; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 dígito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*VARDATA(dv))); } /* * Rotina para cálculo do dígito verificador módulo 11. * Recebe um argumento, o número. Retorna o dígito verificador. */ PG_FUNCTION_INFO_V1(dv11dig); Datum dv11dig(PG_FUNCTION_ARGS) { int digito=0, fator=2; text *num = PG_GETARG_TEXT_P(0); // Único argumento = número /* Verificar o recebimento de argumento vazio */ if (VARATT_SIZEP(num) == VARHDRSZ) { PG_RETURN_NULL(); } /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito digito += VALOR(*c) * fator; if (++fator > 9) fator = 2; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 dígito = 0 /* Retornar o dígito verificador */ int32 tamanho = VARHDRSZ + sizeof(char); text *resultado = (text *) palloc(tamanho); memset((void *) resultado, 0, tamanho); VARATT_SIZEP(resultado) = tamanho; *VARDATA(resultado) = (char) DIGITO(digito); PG_RETURN_TEXT_P(resultado); } /* * Rotina para cálculo do dígito verificador módulo 10 - FEBRABAN * Recebe dois argumentos, número e dígito verificador. * Retorna verdade se o dígito verificador estiver * correto, ou falso caso contrário. */ PG_FUNCTION_INFO_V1(dv10); Datum dv10(PG_FUNCTION_ARGS) { int digito=0, fator=2, produto; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número text *dv = PG_GETARG_TEXT_P(1); // Segundo argumento = dígito verificador /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar dígito verificador não dígito */ if (!isdigit(*VARDATA(dv))) PG_RETURN_NULL(); /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito produto = VALOR(*c) * fator; digito+= produto/10 + produto%10; if (--fator < 1) fator = 2; } digito = 10 - ( digito % 10 ); if (digito == 10) digito = 0; /* Retornar verdade ou falso */ PG_RETURN_BOOL (digito == VALOR(*VARDATA(dv))); } /* * Rotina para cálculo do dígito verificador módulo 10 - FEBRABAN. * Recebe um argumento, o número. Retorna o dígito verificador. */ PG_FUNCTION_INFO_V1(dv10dig); Datum dv10dig(PG_FUNCTION_ARGS) { int digito=0, fator=2, produto; text *num = PG_GETARG_TEXT_P(0); // Único argumento = número /* Verificar o recebimento de argumento vazio */ if (VARATT_SIZEP(num) == VARHDRSZ) { PG_RETURN_NULL(); } /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito produto = VALOR(*c) * fator; digito+= produto/10 + produto%10; if (--fator < 1) fator = 2; } digito = 10 - ( digito % 10 ); if (digito == 10) digito = 0; /* Retornar o dígito verificador */ int32 tamanho = VARHDRSZ + sizeof(char); text *resultado = (text *) palloc(tamanho); memset((void *) resultado, 0, tamanho); VARATT_SIZEP(resultado) = tamanho; *VARDATA(resultado) = (char) DIGITO(digito); PG_RETURN_TEXT_P(resultado); } /* * Rotina para validação do CPF. * Recebe um argumento, o número do CPF com onze dígitos. * Retorna verdade se os dígitos verificadores do CPF * estiverem corretos, ou falso caso contrário. * Se o argumento for nulo, não tiver 11 dígitos, ou contiver * um dígito não numérico, retorna nulo. */ PG_FUNCTION_INFO_V1(cpf); Datum cpf(PG_FUNCTION_ARGS) { int fator, digito; char *c; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número do CPF /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar se o CPF tem 11 dígitos */ if ( (VARSIZE(num) - VARHDRSZ) != 11*sizeof(char) ) { PG_RETURN_NULL(); } /* Validar o primeiro dígito verificador */ for (c=VARDATA(num), digito=0, fator=10; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar falso se o primeiro dígito não estiver correto if (digito != VALOR(*c)) PG_RETURN_BOOL(false); /* Validar o segundo dígito verificador */ for (c=VARDATA(num), digito=0, fator=11; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*c)); } /* * Rotina para validação do CNPJ. * Recebe um argumento, o número do CNPJ com quatorze dígitos. * Retorna verdade se os dígitos verificadores do CNPJ * estiverem corretos, ou falso caso contrário. * Se o argumento for nulo, não tiver 14 dígitos, ou contiver * um dígito não numérico, retorna nulo. */ PG_FUNCTION_INFO_V1(cnpj); Datum cnpj(PG_FUNCTION_ARGS) { int fator, digito; char *c; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número do CNPJ /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar se o CNPJ tem 14 dígitos */ if ( (VARSIZE(num) - VARHDRSZ) != 14*sizeof(char) ) { PG_RETURN_NULL(); } /* Validar o primeiro dígito verificador */ for (c=VARDATA(num), digito=0, fator=13; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * (fator>9 ? fator-8 : fator); } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar falso se o primeiro dígito não estiver correto if (digito != VALOR(*c)) PG_RETURN_BOOL(false); /* Validar o segundo dígito verificador */ for (c=VARDATA(num), digito=0, fator=14; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * (fator>9 ? fator-8 : fator); } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*c)); } /* * Rotina para validação do número de inscrição eleitoral. * Recebe um argumento, o número de inscrição eleitoral com doze dígitos. * Retorna verdade se os dígitos verificadores do número de inscrição * eleitoral estiverem corretos, ou falso caso contrário. * Se o argumento for nulo, não tiver 12 dígitos, ou contiver * um dígito não numérico, retorna nulo. */ PG_FUNCTION_INFO_V1(nie); Datum nie(PG_FUNCTION_ARGS) { int fator, digito; char *c; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número de inscrição /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar se o número de inscrição tem 12 dígitos */ if ( (VARSIZE(num) - VARHDRSZ) != 12*sizeof(char) ) { PG_RETURN_NULL(); } /* Validar o primeiro dígito verificador */ for (c=VARDATA(num), digito=0, fator=9; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar falso se o primeiro dígito não estiver correto if (digito != VALOR(*(c+2*sizeof(char)))) PG_RETURN_BOOL(false); /* Validar o segundo dígito verificador */ for (digito=0, fator=4; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*c)); }