#ifndef INDICE_H #define INDICE_H #include #include #include #include template class Elemento_Indice { public: t_chave chave; t_referencia referencia; Elemento_Indice() { chave = 0; referencia = 0; } ~Elemento_Indice() { } Elemento_Indice &operator=(Elemento_Indice elemento) { this->chave = elemento.chave; this->referencia = elemento.referencia; return *this; } bool operator==(Elemento_Indice elemento) { return (chave == elemento.chave); }; bool operator!=(Elemento_Indice elemento) { return !(chave == elemento.chave); }; bool operator<(Elemento_Indice elemento) { return (chave < elemento.chave); }; bool operator>(Elemento_Indice elemento) { return (chave > elemento.chave); }; bool operator<=(Elemento_Indice elemento) { return (chave <= elemento.chave); }; bool operator>=(Elemento_Indice elemento) { return (chave >= elemento.chave); }; }; enum TIPO {INTEIRO, STRING, LONG, DOUBLE}; /** * class Indice: use Indice, onde tipo do campo/referência deve ser, int, long ou String. * * OBS: Esta é uma classe base não implementada, use uma implementação dela, como a Indice_Lista, a qual usa uma estrutura de lista para manter os índices na memória */ template class Indice { public: /** * Construtor: monta a estrutura para ler o arquivo de índices na memória */ Indice(const char *arquivo, const char *campo, const char *referencia, TIPO tcampo, TIPO treferencia, const char *tipo_estrutura) { this->tcampo = tcampo; this->treferencia = treferencia; this->campo = campo; this->referencia = referencia; this->arquivo = arquivo; this->tipo_estrutura = tipo_estrutura; this->modificado = false; delimitador=':'; delimitador_linha='\n'; estrutura = NULL; Le(arquivo); }; virtual ~Indice() { if (estrutura != NULL) delete estrutura; }; /** * Apaga: apaga o indice da memoria. */ void Apaga() { if (estrutura != NULL) { delete estrutura; estrutura = NULL; }; FILE *fp = fopen(arquivo.Texto(),"w"); fclose(fp); }; /** * Le: lê o 'arquivo' que relaciona 'campo' com 'referencia', onde 'campo' é o nome do campo do banco de dados a qual este índice trata. Os delimitadores podem ser escolhidos, mas os padrões devem bastar. *@return 0=ok, -1 = não pode ler o arquivo, -2 = formato incorreto, -3 = dados não conferem com os pedidos(campo e referencia), -4=o arquivo de indice foi gerado para outra estrutura que nao a atual(Ex. foi escrito para lista e vai ser lido por arvore bin) */ int Le() { return Le(arquivo.Texto()); }; int Le(String arquivo) { this->arquivo = arquivo; FILE *fp; String linha(""); char c; t_class1 vchave; t_class2 vreferencia; if (arquivo.Vazia()) arquivo = this->arquivo; if ((fp=fopen(arquivo.Texto(),"r")) == NULL) { return -1; } if (estrutura != NULL) { delete estrutura; estrutura = NULL; } int erros = Le_Cabecalho(fp); if (erros != 0) return erros; while ((c=fgetc(fp)) != EOF) { if ( c != delimitador_linha ) { linha += c; } else { Lista_Simples *aux = linha.Quebra(delimitador); linha = ""; switch (tcampo) { case INTEIRO: { vchave = (t_class1) aux->Valor().Para_Int(); } break; case STRING: { vchave = (t_class1) aux->Valor().Texto(); } break; case LONG: { vchave = (t_class1) aux->Valor().Para_Long(); } break; case DOUBLE: { vchave= (t_class1) aux->Valor().Para_Double(); } break; } if (aux->Proximo() != NULL) switch (treferencia) { case INTEIRO: { vreferencia = (t_class2) aux->Proximo()->Valor().Para_Int(); } break; case STRING: { vreferencia = (t_class2) aux->Proximo()->Valor().Texto(); } break; case LONG: { vreferencia = (t_class2) aux->Proximo()->Valor().Para_Long(); } break; case DOUBLE: { vreferencia = (t_class2) aux->Proximo()->Valor().Para_Double(); } break; } delete aux; Insere(vchave, vreferencia); } } modificado = false; fclose(fp); return 0; }; /** * Escreve: Escreve o arquivo de Indice */ bool Escreve() { return Escreve(arquivo.Texto(), delimitador, delimitador_linha); } bool Escreve(String arquivo, char delimitador, char delimitador_linha) { FILE *fp; String linha(""); if (arquivo.Vazia()) arquivo = this->arquivo; if (modificado) { if ((fp=fopen(arquivo.Texto(),"w")) == NULL) { return false; } Escreve_Cabecalho(fp); Percorre_Estrutura_Escrevendo_Arquivo(fp); fclose(fp); } return true; } /** * Procura: procura pela chave primária no índice. *@return true=achou, false=não achou. A referência é retornada em 'referencia' */ bool Procura(t_class1 chave, t_class2 *referencia) { Elemento_Indice aux; t_class3 *resultado; aux.chave = chave; if (estrutura == NULL) return false; resultado=estrutura->Procura(aux); if (resultado != NULL) { if (referencia != NULL) *referencia = resultado->Valor().referencia; return true; } else { return false; } return false; } /** * Remove: remove o elemento do índice *@param chave do elemento o qual deve ser removido do indice *@param referencia a qual a chave faz referencia *@param true=ok, false=nao existia, nada foi removido */ bool Remove(t_class1 chave, t_class2 referencia) { Elemento_Indice elem; elem.chave = chave; elem.referencia = referencia; modificado = true; bool retorno = Remove_Elemento(elem); return retorno; } /** * Insere: insere ordenado no Indice *@param chave do elemento a ser inserido *@param referencia a qual a chave se refere */ void Insere(t_class1 chave, t_class2 referencia) { Elemento_Indice elem; elem.chave = chave; elem.referencia = referencia; modificado = true; Insere_Elemento(elem); } /** * Altera: altera valor da referencia do elemento de 'chave' e 'referencia' *@param chave chave do elemento atual a ser modificado *@param referencia do elemento atual a ser modificado *@param referencia_nova referencia nova do elemento *@return true=ok, false=provavelmente o valor nao existia */ bool Altera(t_class1 chave, t_class2 referencia, t_class2 referencia_nova) { Elemento_Indice elem; elem.chave = chave; elem.referencia = referencia; modificado = true; return Altera_Elemento(elem, referencia_nova); } protected: t_class3 *estrutura; String campo; String referencia; String arquivo; String tipo_estrutura; TIPO tcampo; TIPO treferencia; char delimitador; char delimitador_linha; bool modificado; /** * Escreve_Cabecalho: grava o cabeclho deste indice no arquivo apontado por 'fp' *@param fp apontador para FILE, onde deve ser escrito o caceçalho */ void Escreve_Cabecalho(FILE *fp) { fseek(fp,0,SEEK_SET); fprintf(fp,"%c%c%s%c%s%c",delimitador,delimitador_linha,campo.Texto(),delimitador,referencia.Texto(),delimitador_linha); fprintf(fp,"tipo_estrutura%c%s%c",delimitador,tipo_estrutura.Texto(),delimitador_linha); }; /** * Le_Cabecalho: lê o cabeçalho deste índice do arquivo apontado por 'fp' e retorna se é compatível ao índice atual. *@param fp apontador para FILE, onde deve ser lido o caceçalho */ int Le_Cabecalho(FILE *fp) { char c; String linha; if (fscanf(fp,"%c%c",&delimitador,&delimitador_linha) == EOF) { delimitador=';'; delimitador_linha='\n'; fclose(fp); return -2; } while (((c=fgetc(fp)) != delimitador_linha) && (c!=EOF)) { linha += c; } Lista_Simples *aux = linha.Quebra(delimitador); linha = ""; campo = aux->Valor().Texto(); if (aux->Proximo() != NULL) referencia = aux->Proximo()->Valor().Texto(); delete aux; // conferência para ver se o que o usuário quer é o que existe no arquivo if ( ((!campo.Vazia()) && (campo != this->campo)) || ((!referencia.Vazia()) && (referencia != this->referencia)) ) { fclose(fp); return -3; } while (((c=fgetc(fp)) != delimitador_linha) && (c!=EOF)) { linha += c; } aux = linha.Quebra(delimitador); if (aux->Proximo() != NULL) { linha = aux->Proximo()->Valor(); delete aux; } else { fclose(fp); delete aux; return -4; } if (Confere_Tipo_Estrutura(linha) == false) { fclose(fp); return -4; } return 0; }; /** * Confere_Tipo_Estrutura: verifica se as estruturas especificada e igual à atual */ bool Confere_Tipo_Estrutura(String tipo_estrutura) { return (this->tipo_estrutura == tipo_estrutura); }; /** * Percorre_Estrutura_Escrevendo_Arquivo: escreve a estrutura de modo apropriado no arquivo *@param fp apontador para o arquivo onde deve ser escrito */ virtual void Percorre_Estrutura_Escrevendo_Arquivo(FILE *fp) { }; /** * Insere_Elemento: deverá inserir o elemento 'elem' no indice *@param elem elemento a ser inserido *OBS: deve ser implementado de acordo com a estrutura */ virtual void Insere_Elemento(Elemento_Indice elem) { }; /** * Remove_Elemento: deverá remover o elemento 'elem' do indice *@param elem elemento a ser removido *OBS: deve ser implementado de acordo com a estrutura */ virtual bool Remove_Elemento(Elemento_Indice elem) { return false; }; /** * Altera_Elemento: altera elemento elem, trocando a referencia *@param elem elemento a ser removido *@param referencia_nova e´ a nova referencia para o elemento 'elem' *OBS: deve ser implementado de acordo com a estrutura */ virtual bool Altera_Elemento(Elemento_Indice elem, t_class2 referencia_nova) { return false; } }; #endif