#ifndef LISTA_INVERTIDA_H #define LISTA_INVERTIDA_H #include #include #include #include /* enum TIPO */ #include template class Lista_Invertida { public: Lista_Invertida(String arquivo, String campo, TIPO tcampo) { this->arquivo = arquivo; this->campo = campo; this->tcampo = tcampo; if ((fp = fopen(this->arquivo.Texto(),"r+")) == NULL) if ((fp = fopen(this->arquivo.Texto(),"w+")) == NULL) fprintf(stderr,"ERROR: could not open file '%s' to read and write. Check your permissions and disk space.\n",this->arquivo.Texto()); if (Le_Cabecalho() < 0) { Escreve_Cabecalho(); } } ~Lista_Invertida() { fclose(fp); } /** * Apaga: apaga o arquivo com a lista invertida */ void Apaga() { fclose(fp); fp = fopen(this->arquivo.Texto(),"w+"); Escreve_Cabecalho(); } /** * Insere: insere o 'valor' como cabeca da lista anteriormente encabecada com valor na posicao 'posicao_cabeca'. *@param valor valor a ser inserido *@param posicao_cabeca posicao do cabeca anterior no arquivo *@return posicao do registro atual */ long Insere(t_class1 valor, long posicao_cabeca) { Muda_Posicao(0,SEEK_END); // vai para o fim do arquivo long posicao = Pega_Posicao(); String linha; linha = valor; linha += delimitador; linha += posicao_cabeca; linha += delimitador_linha; fprintf(fp, "%s", linha.Texto()); fseek(fp,0L,SEEK_CUR); // Sincroniza return posicao; } /** * Pega_Lista: pega lista encabeçada por registro na 'posicao' *@param posicao posicao do cabeça *OBS: Memoria Dinamica. Liberar!!! */ Lista_Simples *Pega_Lista(long posicao) { Lista_Simples *lista = NULL; Lista_Simples *lista_aux = NULL; bool continua=true; t_class1 valor; String linha; while (continua) { Muda_Posicao(posicao); if ((linha=Le_Linha())!="") { Lista_Simples *aux = linha.Quebra(delimitador); switch (tcampo) { case INTEIRO: { valor = (t_class1) aux->Valor().Para_Int(); } break; case STRING: { valor = (t_class1) aux->Valor().Texto(); } break; case LONG: { valor = (t_class1) aux->Valor().Para_Long(); } break; case DOUBLE: { valor= (t_class1) aux->Valor().Para_Double(); } break; } if (aux->Proximo() != NULL) posicao = aux->Proximo()->Valor().Para_Long(); else continua = false; if (posicao < 0) continua = false; if (lista == NULL) { lista = new Lista_Simples(valor); lista_aux = lista; } else { lista_aux->Add_Depois(valor); lista_aux = lista_aux->Proximo(); } delete aux; } else { continua = false; } } return lista; } /** * Remove: remove elementos onde existe 'valor' *@param valor a ser removido */ bool Remove(t_class1 valor) { // O neucimar nao falou para fazer esta parte return false; } /** * Le_Linha: le uma linha do arquivo */ String Le_Linha() { char c; String linha(""); Muda_Posicao(0,SEEK_CUR); // assegura sincronia while (((c=fgetc(fp)) != EOF) && (c!=delimitador_linha)) { linha += c; } return linha; } /** * Escreve: nao faz nada. So retorna true. Pois a lista sempre eh escrita no arquivo *@return true, sempre */ bool Escreve() { return true; } /** * Le: lê lista invertida *@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() { int erros = Le_Cabecalho(); if (erros != 0) return erros; return 0; }; protected: /** * Muda_Posicao: muda posição no arquivo *@param posicao relativa à 'onde' *@param onde pode ser SEEK_SET=a partir do início, SEEK_CUR=a partir da posição atual, SEEK_END=a partir do fim do arquivo */ bool Muda_Posicao(long posicao, int onde) { return (fseek(fp,posicao,onde) == 0); } /** * Muda_Posicao: muda posição no arquivo *@param posicao relativa ao começo do arquivo */ bool Muda_Posicao(long posicao) { return Muda_Posicao(posicao,SEEK_SET); } /** * Pega_Posicao: retorna a posição atual no arquivo *@return posicao atual no arquivo */ long Pega_Posicao() { return ftell(fp); } /** * Escreve_Cabecalho: grava o cabecalho desta lista invertida em 'fp' *@param fp apontador para FILE, onde deve ser escrito o caceçalho */ void Escreve_Cabecalho() { fseek(fp,0,SEEK_SET); fprintf(fp,"%c%c%s%c%d%c",delimitador,delimitador_linha,campo.Texto(),delimitador,tcampo,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() { char c; String linha; Muda_Posicao(0); if (fscanf(fp,"%c%c",&delimitador,&delimitador_linha) == EOF) { delimitador=';'; delimitador_linha='\n'; 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) tcampo = (TIPO) aux->Proximo()->Valor().Para_Int(); delete aux; // conferência para ver se o que o usuário quer é o que existe no arquivo if ( ((!campo.Vazia()) && (campo != this->campo)) || (tcampo != this->tcampo) ) { fclose(fp); return -3; } return 0; }; FILE *fp; String arquivo; String campo; TIPO tcampo; char delimitador; char delimitador_linha; }; #endif