/*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N / D E C O M P R E S S I O N ' RLE ' M O N O D I M E N S I O N N E L L E : */ /* */ /* */ /* Nota : */ /* */ /* Ce programme a inspire 'v $xrC/CompressionDeCompressionRunLengthEncoding.11$vv$I' */ /* Il y a une petite difference au sujet du compte des repetitions : */ /* */ /* */ /* $xtc/CompressionDecompression_RLE_1D.01$c */ /* */ /* x --> x */ /* xx --> xx */ /* xxx --> xxx */ /* xxxx --> xxxx4 */ /* xxxxx --> xxxx5 */ /* xxxxxx --> xxxx6 */ /* (...) */ /* */ /* */ /* alors que : */ /* */ /* $xrC/CompressionDeCompressionRunLengthEncoding.11$vv$I */ /* */ /* x --> x */ /* xx --> xx */ /* xxx --> xxx */ /* xxxx --> xxxx0 */ /* xxxxx --> xxxx1 */ /* xxxxxx --> xxxx2 */ /* (...) */ /* */ /* ce qui est donc plus optimise... */ /* */ /* */ /* Author of '$xtc/CompressionDecompression_RLE_1D.01$c' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 20141208104225). */ /* */ /*************************************************************************************************************************************/ #include "INCLUDES.01.I" extern void *malloc(); #define CHAR \ unsigned char #define LONGUEUR_MAXIMALE_DES_BUFFERS \ (1000) \ /* Longueur maximale des buffers pour valider les 'malloc(...)'s. */ #define QUE_FAIRE(x) \ (0) #define NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS \ (1) #define BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS \ (256) #define BORNE_INFERIEURE_DE_REPETITIONS \ ((4)+QUE_FAIRE(NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS)) #define BORNE_SUPERIEURE_DE_REPETITIONS \ borne_superieure() /* Definitions des bornes : */ /* */ /* INFERIEUR a partir de laquelle on compacte, */ /* SUPERIEUR limite superieure du compactage a cause de la capacite d'un octet. */ /* */ /* On notera que si l'on utilise plus d'un octet pour stocker les nombres de repetitions, */ /* la borne inferieure doit etre augmentee, mais comment et de combien ? */ int borne_superieure() { int cumul=1; int compteur; for (compteur=1 ; compteur<=NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS ; compteur++) { cumul = BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS*cumul; } return(cumul-1); } int Editer=VRAI; /* Afin de controler toutes les editions (sauf les messages d'erreur evidemment...). */ #define PRINT(sequence) \ { \ if (Editer == VRAI) \ { \ sequence; \ } \ else \ { \ } \ } #define bSTORE(valeur) \ { \ *(chaineR+indexR) = (valeur); \ \ if (indexR < NombreVersIndex(LONGUEUR_MAXIMALE_DES_BUFFERS)) \ { \ indexR++; \ } \ else \ { \ fprintf(stderr,"Erreur de compression/decompression (debordement de capacite) -1-\n"); \ } \ } #define STORE(format,valeur,Lchaine) \ { \ bSTORE(valeur); \ \ Lchaine++; \ \ PRINT(printf(format,(valeur));); \ } #define STORE_REPETITION(nombre) \ { \ int compteur; \ int quotient=nombre; \ int reste; \ \ for (compteur=1 ; compteur<=NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS ; compteur++) \ { \ reste = quotient % BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS; \ quotient = quotient / BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS; \ STORE("=%d ",(CHAR)reste,LchaineC_); \ } \ \ if (quotient != 0) \ { \ fprintf(stderr,"Erreur de compression (debordement de capacite de repetition) -1-\n"); \ } \ else \ { \ } \ } #define GET_REPETITION(NombreDeCaracteres) \ { \ int compteur; \ int facteur=1; \ \ NombreDeCaracteres=0; \ \ for (compteur=1 ; compteur<=NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS ; compteur++) \ { \ CHAR caractere=*(chaineA+indexA); \ NombreDeCaracteres = NombreDeCaracteres+(caractere*facteur); \ facteur = BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS*facteur; \ \ if (compteur < NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS) \ { \ indexA++; \ } \ else \ { \ } \ } \ \ NombreDeCaracteres = NombreDeCaracteres-BORNE_INFERIEURE_DE_REPETITIONS; \ } int LchaineC_; CHAR *compression__(CHAR *chaineR,CHAR *chaineA,int LchaineA) { CHAR CaracterePrecedent; int CaracterePrecedentExiste=FAUX; int CompteurDeRepetitions=1; int indexA; int indexR=INDEX0; chaineR = malloc(MIN2(LchaineA,LONGUEUR_MAXIMALE_DES_BUFFERS)); LchaineC_ = 0; for (indexA=INDEX0 ; indexA<=NombreVersIndex(LchaineA) ; indexA++) { CHAR CaractereCourant=*(chaineA+indexA); if (CaracterePrecedentExiste == FAUX) { CaracterePrecedent = CaractereCourant; CaracterePrecedentExiste = VRAI; STORE("%c",CaractereCourant,LchaineC_); } else { if ( (CaractereCourant == CaracterePrecedent) && (CompteurDeRepetitions < BORNE_SUPERIEURE_DE_REPETITIONS) ) { CompteurDeRepetitions++; if ( (CompteurDeRepetitions > 1) && (CompteurDeRepetitions <= BORNE_INFERIEURE_DE_REPETITIONS) ) { STORE("%c",CaractereCourant,LchaineC_); } else { } if ( (CompteurDeRepetitions >= BORNE_INFERIEURE_DE_REPETITIONS) && (indexA == NombreVersIndex(LchaineA)) ) { STORE_REPETITION(CompteurDeRepetitions); } else { } } else { if (CompteurDeRepetitions >= BORNE_INFERIEURE_DE_REPETITIONS) { STORE_REPETITION(CompteurDeRepetitions); } else { } STORE("%c",CaractereCourant,LchaineC_); CaracterePrecedent = CaractereCourant; CompteurDeRepetitions = 1; } } } bSTORE(0); return(chaineR); } #define CARACTERE_PRECEDENT_INDEFINI \ -1000000000 int LchaineDC; CHAR *decompression(CHAR *chaineR,int LchaineR,CHAR *chaineA,int LchaineA) { int iterer=VRAI; int CaracterePrecedent=CARACTERE_PRECEDENT_INDEFINI; int CompteurDeRepetitions=1; int indexA; int indexR=INDEX0; chaineR = malloc(MIN2(LchaineR,LONGUEUR_MAXIMALE_DES_BUFFERS)); /* ATTENTION : combien en fait allouer d'octets ? */ LchaineDC = 0; indexA = INDEX0; while (iterer == VRAI) { CHAR CaractereCourant=*(chaineA+indexA); if (CompteurDeRepetitions <= BORNE_INFERIEURE_DE_REPETITIONS) { if (CompteurDeRepetitions == BORNE_INFERIEURE_DE_REPETITIONS) { int compteur; int NombreDeCaracteres_ADupliquer; GET_REPETITION(NombreDeCaracteres_ADupliquer); for (compteur=1 ; compteur <= NombreDeCaracteres_ADupliquer ; compteur++) { STORE("%c",CaracterePrecedent,LchaineDC); } CaracterePrecedent = CARACTERE_PRECEDENT_INDEFINI; CompteurDeRepetitions = 1; } else { if (CaractereCourant == CaracterePrecedent) { CompteurDeRepetitions++; } else { CaracterePrecedent = CaractereCourant; CompteurDeRepetitions = 1; } STORE("%c",CaractereCourant,LchaineDC); } } else { fprintf(stderr,"Erreur de decompression -1-\n"); } indexA++; if (indexA<=NombreVersIndex(LchaineA)) { } else { iterer = FAUX; } } bSTORE(0); return(chaineR); } #define COMPRESSION_DECOMPRESSION(chaine__) \ { \ if (BORNE_SUPERIEURE_DE_REPETITIONS <= MASKO) \ { \ int Lchaine__=strlen(chaine__); \ CHAR *chaineC_; \ CHAR *chaineDC; \ int index; \ \ PRINT(printf("%s\n",chaine__);); \ chaineC_ = compression__(chaineC_,chaine__,Lchaine__); \ /* On notera que 'strlen(...)' ne peut etre utilisee sur 'chaineC_' car, en effet, cette */ \ /* chaine peut contenir des octets nuls... */ \ PRINT(printf("\n");); \ PRINT(printf("longueur=%d -> %d\n",Lchaine__,LchaineC_);); \ chaineDC = decompression(chaineDC,Lchaine__,chaineC_,LchaineC_); \ PRINT(printf("\n\n");); \ \ if (LchaineDC != Lchaine__) \ { \ fprintf(stderr,"Erreur de decompression (incoherence des longueurs) -1-\n"); \ } \ else \ { \ } \ \ if (LchaineDC != strlen(chaineDC)) \ { \ fprintf(stderr,"Erreur de decompression (incoherence des longueurs) -2-\n"); \ } \ else \ { \ } \ \ for (index=INDEX0 ; index<=NombreVersIndex(LchaineDC) ; index++) \ { \ if ((*(chaineDC+index)) != (*(chaine__+index))) \ { \ fprintf(stderr,"Erreur de decompression (incoherence des contenus) -3-\n"); \ } \ else \ { \ } \ } \ } \ else \ { \ fprintf(stderr,"Erreur de compression/decompression -2-\n"); \ } \ } main() { COMPRESSION_DECOMPRESSION("_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhh"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhi"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhij"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhijj"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhijjkkkllllmmmmmnnnnnn"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhiiiiiiiiijjjjjjjjjjkkkkkkkkkkkk"); COMPRESSION_DECOMPRESSION("abbcccddddeeeeeffffffggggggghhhhhhhhiiiiiiiiijjjjjjjjjjkkkkkkkkkkkklmm"); COMPRESSION_DECOMPRESSION("a"); COMPRESSION_DECOMPRESSION("aa"); COMPRESSION_DECOMPRESSION("aaa"); COMPRESSION_DECOMPRESSION("aaaa"); COMPRESSION_DECOMPRESSION("aaaaa"); COMPRESSION_DECOMPRESSION("aaaaaa"); COMPRESSION_DECOMPRESSION("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); COMPRESSION_DECOMPRESSION("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); COMPRESSION_DECOMPRESSION("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!b"); COMPRESSION_DECOMPRESSION("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!b"); /* Le code hexadecimal de '!' est 0x21 (soit 31) et dans les chaines precedentes il y a */ /* une trentaine de 'a' et ce afin de voir s'il n'y a pas d'ambiguite... */ }