Advertisement
Guest User

Untitled

a guest
Dec 14th, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.00 KB | None | 0 0
  1. /*Author: Rui Pedro Paiva
  2. Teoria da Informação, LEI, 2007/2008*/
  3.  
  4. #include <cstdlib>
  5. #include "gzip.h"
  6.  
  7.  
  8. //função principal, a qual gere todo o processo de descompactação
  9. int main()
  10. {
  11. //--- Gzip file management variables
  12. FILE *gzFile; //ponteiro para o ficheiro a abrir
  13. long fileSize;
  14. long origFileSize;
  15. int numBlocks = 0;
  16. gzipHeader gzh;
  17. unsigned char byte; //variável temporária para armazenar um byte lido directamente do ficheiro
  18. unsigned int rb = 0; //último byte lido (poderá ter mais que 8 bits, se tiverem sobrado alguns de leituras anteriores)
  19. char needBits = 0, availBits = 0;
  20. HuffmanTree* hft;
  21.  
  22.  
  23.  
  24. //--- obter ficheiro a descompactar
  25. //char fileName[] = "FAQ.txt.gz";
  26.  
  27. /* if (argc != 2)
  28. {
  29. printf("Linha de comando invalida!!!");
  30. return -1;
  31. }*/
  32. char *fileName = "FAQ.txt.gz";
  33.  
  34. //--- processar ficheiro
  35. gzFile = fopen(fileName, "rb");
  36. fseek(gzFile, 0L, SEEK_END);
  37. fileSize = ftell(gzFile);
  38. fseek(gzFile, 0L, SEEK_SET);
  39.  
  40. //ler tamanho do ficheiro original (acrescentar: e definir Vector com símbolos
  41. origFileSize = getOrigFileSize(gzFile);
  42.  
  43.  
  44. //--- ler cabeçalho
  45. int erro = getHeader(gzFile, &gzh);
  46. if (erro != 0)
  47. {
  48. printf ("Formato inválido!!!");
  49. return -1;
  50. }
  51.  
  52. //--- Para todos os blocos encontrados
  53. char BFINAL;
  54.  
  55. do
  56. {
  57. //--- ler o block header: primeiro byte depois do cabeçalho do ficheiro
  58. needBits = 3;
  59. if (availBits < needBits)
  60. {
  61. fread(&byte, 1, 1, gzFile);
  62. rb = (byte << availBits) | rb;
  63. availBits += 8;
  64. }
  65.  
  66. //obter BFINAL
  67. //ver se é o último bloco
  68. BFINAL = rb & 0x01; //primeiro bit é o menos significativo
  69. rb = rb >> 1; //descartar o bit correspondente ao BFINAL
  70. availBits -=1;
  71.  
  72. //analisar block header e ver se é huffman dinâmico
  73. if(!isDynamicHuffman(rb)) //ignorar bloco se não for Huffman dinâmico
  74. continue;
  75. rb = rb >> 2; //descartar os 2 bits correspondentes ao BTYPE
  76. availBits -= 2;
  77.  
  78. int HLIT, HDIST, HCLEN;
  79.  
  80. HLIT = read_data(5,&availBits,&rb,gzFile);
  81. printf("HLIT = %d\n", HLIT);
  82.  
  83. HDIST = read_data(5,&availBits,&rb,gzFile);
  84. printf("HDIST = %d\n", HDIST);
  85.  
  86. HCLEN = read_data(4,&availBits,&rb,gzFile);
  87. printf("HCLEN = %d\n", HCLEN);
  88.  
  89. unsigned int comps[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  90. int posi[19] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
  91. int auxiliar[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  92. int comp=0;
  93.  
  94. for(int i = 0; i<(HCLEN + 4) ; i++){
  95. auxiliar[i]+=read_data(3,&availBits,&rb,gzFile);
  96. }
  97. for(int i = 0; i<19; i++){
  98. comps[posi[i]]+=auxiliar[i];
  99. }
  100. for(int i = 0; i<19; i++){
  101. printf("%d ", comps[i]);
  102. }
  103.  
  104. HuffmanTree *hft;
  105. hft = compcode_to_huffman(comps,19);
  106.  
  107. //Semana 3 - pergunta 4
  108. unsigned int *length_codes1;
  109. int read_size =HLIT+257;
  110. length_codes1= (unsigned int*)malloc(read_size*sizeof(unsigned int));
  111. length_codes1 = get_length_codes(hft, &rb, &availBits, read_size, gzFile);
  112.  
  113. //Semana 4 - pergunta 5
  114. printf("\n\n");
  115. unsigned int *length_codes2;
  116. read_size= HDIST+1;
  117. length_codes2= (unsigned int*)malloc(read_size*sizeof(unsigned int));
  118. length_codes2 = get_length_codes(hft, &rb, &availBits, read_size, gzFile);
  119.  
  120. //Semana 5- pergunta 6
  121. HuffmanTree *hft_hlit , *hft_hdist;
  122.  
  123. hft_hlit = compcode_to_huffman(length_codes1,HLIT+257);
  124. hft_hdist= compcode_to_huffman(length_codes2,HDIST+1);
  125.  
  126. char *vetor_ficheiro;
  127. vetor_ficheiro= (char*)malloc(sizeof(char)*origFileSize);
  128. int pos_vetor=0, read_bits, copy_length, dist_node, back_dist, pos_aux;
  129. bool end_block=false;
  130. //pode haver mais blocos
  131. int array_bits_hlit[29]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
  132. int array_length_hlit[29]= {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258};
  133.  
  134. int array_bits_hdist[30]= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
  135. int array_distance_hdist[30]= {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
  136.  
  137. unsigned int bit;
  138. int i_node;
  139. i_node=findNode(hft_hlit, "1100111", 1);
  140. int n=0;
  141. bit=0;
  142. char bits[10];
  143. while(!end_block){
  144. while(1){
  145. bit= read_data(1, &availBits, &rb, gzFile);
  146. i_node= nextNode(hft_hlit, '0'+bit);
  147. if(i_node>=-1){
  148. if(i_node==256){
  149. end_block=true;
  150. break;
  151. }
  152. else if(i_node<256){
  153. vetor_ficheiro[pos_vetor++]=i_node;
  154. }
  155. else{
  156. pos_aux= i_node -257;
  157. if(i_node<=264 ||i_node== 285)
  158. copy_length= array_length_hlit[pos_aux];
  159. else{
  160. read_bits= array_bits_hlit[pos_aux];
  161. bit= read_data(read_bits, &availBits, &rb, gzFile);
  162.  
  163. copy_length= array_length_hlit[pos_aux]+bit;
  164. }
  165.  
  166. do{
  167. bit= read_data(1, &availBits, &rb, gzFile);
  168. dist_node= nextNode(hft_hdist, '0' + bit);
  169. }while(dist_node==-2);
  170.  
  171. read_bits= array_bits_hdist[dist_node];
  172.  
  173. bit=0;
  174. if(dist_node>=4)
  175. bit= read_data(read_bits, &availBits, &rb, gzFile);
  176.  
  177. back_dist= bit+array_distance_hdist[dist_node];
  178.  
  179. for(int i=0; i<copy_length; i++){
  180. vetor_ficheiro[pos_vetor+i]= vetor_ficheiro[pos_vetor-back_dist+i];
  181. }
  182. pos_vetor+=copy_length;
  183. printf("n-> %d\n",n);
  184. n++;
  185. }
  186.  
  187. resetCurNode(hft_hlit);
  188. resetCurNode(hft_hdist);
  189. break;
  190. }
  191. }
  192. }
  193. FILE *fp;
  194. fp= fopen("final.txt","w+");// ==NULL;
  195.  
  196. fprintf(fp,"%s",vetor_ficheiro);
  197. fclose(fp);
  198.  
  199.  
  200. //--- Se chegou aqui --> compactado com Huffman dinâmico --> descompactar
  201. //**************************************************
  202. //****** ADICIONAR PROGRAMA... *********************
  203. //**************************************************
  204.  
  205.  
  206. //actualizar número de blocos analisados
  207. numBlocks++;
  208.  
  209. }while(BFINAL == 0);
  210.  
  211.  
  212. //terminações
  213.  
  214. fclose(gzFile);
  215.  
  216. printf("End: %d bloco(s) analisado(s).\n", numBlocks);
  217.  
  218.  
  219. //teste da função bits2String: RETIRAR antes de criar o executável final
  220. //char str[9];
  221. //bits2String(str, 0x03, 3);
  222. //printf("%s\n", str);
  223.  
  224.  
  225. //RETIRAR antes de criar o executável final
  226. system("PAUSE");
  227. return EXIT_SUCCESS;
  228. }
  229.  
  230.  
  231. //---------------------------------------------------------------
  232. //Lê o cabeçalho do ficheiro gzip: devolve erro (-1) se o formato for inválidodevolve, ou 0 se ok
  233. int getHeader(FILE *gzFile, gzipHeader *gzh) //obtém cabeçalho
  234. {
  235. unsigned char byte;
  236.  
  237. //Identicação 1 e 2: valores fixos
  238. fread(&byte, 1, 1, gzFile);
  239. (*gzh).ID1 = byte;
  240. if ((*gzh).ID1 != 0x1f) return -1; //erro no cabeçalho
  241.  
  242. fread(&byte, 1, 1, gzFile);
  243. (*gzh).ID2 = byte;
  244. if ((*gzh).ID2 != 0x8b) return -1; //erro no cabeçalho
  245.  
  246. //Método de compressão (deve ser 8 para denotar o deflate)
  247. fread(&byte, 1, 1, gzFile);
  248. (*gzh).CM = byte;
  249. if ((*gzh).CM != 0x08) return -1; //erro no cabeçalho
  250.  
  251. //Flags
  252. fread(&byte, 1, 1, gzFile);
  253. unsigned char FLG = byte;
  254.  
  255. //MTIME
  256. char lenMTIME = 4;
  257. fread(&byte, 1, 1, gzFile);
  258. (*gzh).MTIME = byte;
  259. for (int i = 1; i <= lenMTIME - 1; i++)
  260. {
  261. fread(&byte, 1, 1, gzFile);
  262. (*gzh).MTIME = (byte << 8) + (*gzh).MTIME;
  263. }
  264.  
  265. //XFL (not processed...)
  266. fread(&byte, 1, 1, gzFile);
  267. (*gzh).XFL = byte;
  268.  
  269. //OS (not processed...)
  270. fread(&byte, 1, 1, gzFile);
  271. (*gzh).OS = byte;
  272.  
  273. //--- Check Flags
  274. (*gzh).FLG_FTEXT = (char)(FLG & 0x01);
  275. (*gzh).FLG_FHCRC = (char)((FLG & 0x02) >> 1);
  276. (*gzh).FLG_FEXTRA = (char)((FLG & 0x04) >> 2);
  277. (*gzh).FLG_FNAME = (char)((FLG & 0x08) >> 3);
  278. (*gzh).FLG_FCOMMENT = (char)((FLG & 0x10) >> 4);
  279.  
  280. //FLG_EXTRA
  281. if ((*gzh).FLG_FEXTRA == 1)
  282. {
  283. //ler 2 bytes XLEN + XLEN bytes de extra field
  284. //1º byte: LSB, 2º: MSB
  285. char lenXLEN = 2;
  286.  
  287. fread(&byte, 1, 1, gzFile);
  288. (*gzh).xlen = byte;
  289. fread(&byte, 1, 1, gzFile);
  290. (*gzh).xlen = (byte << 8) + (*gzh).xlen;
  291.  
  292. (*gzh).extraField = new unsigned char[(*gzh).xlen];
  293.  
  294. //ler extra field (deixado como está, i.e., não processado...)
  295. for (int i = 0; i <= (*gzh).xlen - 1; i++)
  296. {
  297. fread(&byte, 1, 1, gzFile);
  298. (*gzh).extraField[i] = byte;
  299. }
  300. }
  301. else
  302. {
  303. (*gzh).xlen = 0;
  304. (*gzh).extraField = 0;
  305. }
  306.  
  307. //FLG_FNAME: ler nome original
  308. if ((*gzh).FLG_FNAME == 1)
  309. {
  310. (*gzh).fName = new char[1024];
  311. unsigned int i = 0;
  312. do
  313. {
  314. fread(&byte, 1, 1, gzFile);
  315. if (i <= 1023) //guarda no máximo 1024 caracteres no array
  316. (*gzh).fName[i] = byte;
  317. i++;
  318. }while(byte != 0);
  319. if (i > 1023)
  320. (*gzh).fName[1023] = 0; //apesar de nome incompleto, garantir que o array termina em 0
  321. }
  322. else
  323. (*gzh).fName = 0;
  324.  
  325. //FLG_FCOMMENT: ler comentário
  326. if ((*gzh).FLG_FCOMMENT == 1)
  327. {
  328. (*gzh).fComment = new char[1024];
  329. unsigned int i = 0;
  330. do
  331. {
  332. fread(&byte, 1, 1, gzFile);
  333. if (i <= 1023) //guarda no máximo 1024 caracteres no array
  334. (*gzh).fComment[i] = byte;
  335. i++;
  336. }while(byte != 0);
  337. if (i > 1023)
  338. (*gzh).fComment[1023] = 0; //apesar de comentário incompleto, garantir que o array termina em 0
  339. }
  340. else
  341. (*gzh).fComment = 0;
  342.  
  343.  
  344. //FLG_FHCRC (not processed...)
  345. if ((*gzh).FLG_FHCRC == 1)
  346. {
  347. (*gzh).HCRC = new unsigned char[2];
  348. fread(&byte, 1, 1, gzFile);
  349. (*gzh).HCRC[0] = byte;
  350. fread(&byte, 1, 1, gzFile);
  351. (*gzh).HCRC[1] = byte;
  352. }
  353. else
  354. (*gzh).HCRC = 0;
  355.  
  356. return 0;
  357. }
  358.  
  359.  
  360. //---------------------------------------------------------------
  361. //Analisa block header e vê se é huffman dinâmico
  362. int isDynamicHuffman(unsigned char rb)
  363. {
  364. unsigned char BTYPE = rb & 0x03;
  365.  
  366. if (BTYPE == 0) //--> sem compressão
  367. {
  368. printf("Ignorando bloco: sem compactação!!!\n");
  369. return 0;
  370. }
  371. else if (BTYPE == 1)
  372. {
  373. printf("Ignorando bloco: compactado com Huffman fixo!!!\n");
  374. return 0;
  375. }
  376. else if (BTYPE == 3)
  377. {
  378. printf("Ignorando bloco: BTYPE = reservado!!!\n");
  379. return 0;
  380. }
  381. else
  382. return 1;
  383. }
  384.  
  385.  
  386. //---------------------------------------------------------------
  387. //Obtém tamanho do ficheiro original
  388. long getOrigFileSize(FILE * gzFile)
  389. {
  390. //salvaguarda posição actual do ficheiro
  391. long fp = ftell(gzFile);
  392.  
  393. //últimos 4 bytes = ISIZE;
  394. fseek(gzFile, -4, SEEK_END);
  395.  
  396. //determina ISIZE (só correcto se cabe em 32 bits)
  397. unsigned long sz = 0;
  398. unsigned char byte;
  399. fread(&byte, 1, 1, gzFile);
  400. sz = byte;
  401. for (int i = 0; i <= 2; i++)
  402. {
  403. fread(&byte, 1, 1, gzFile);
  404. sz = (byte << 8*(i+1)) + sz;
  405. }
  406.  
  407.  
  408. //restaura file pointer
  409. fseek(gzFile, fp, SEEK_SET);
  410.  
  411. return sz;
  412. }
  413.  
  414.  
  415. //---------------------------------------------------------------
  416. void bits2String(char *strBits, char byte, char len)
  417. {
  418. char mask = 0x01; //get LSbit
  419.  
  420. strBits[len] = 0;
  421. for (char bit, i = len-1; i >= 0; i--)
  422. {
  423. bit = byte & mask;
  424. strBits[i] = bit +48; //converter valor numérico para o caracter alfanumérico correspondente
  425. byte = byte >> 1;
  426. }
  427. }
  428.  
  429. int read_data(char needBits, char *availBits, unsigned int *rb, FILE *gzFile){
  430. int resultado;
  431. int mask;
  432. unsigned char byte;
  433.  
  434. mask = (1<<needBits)-1;
  435. if (*availBits < needBits){
  436. fread(&byte, 1, 1, gzFile);
  437. *rb = (byte << *availBits) | *rb;
  438. *availBits += 8;
  439. }
  440. resultado = *rb & mask;
  441. *rb = *rb >> needBits;
  442. *availBits -= needBits;
  443. return resultado;
  444. }
  445. //--------------------------------------------------------------
  446. HuffmanTree * compcode_to_huffman(unsigned int *comps, int tam){
  447. int mini=0, maxi=0;
  448. for(int i=0; i<tam; i++){
  449. if(mini == 0 || (comps[i]!=0 && comps[i]<mini))
  450. mini= comps[i];
  451. if(comps[i]>maxi)
  452. maxi= comps[i];
  453. }
  454. char * dec_codes;
  455. dec_codes= (char*)malloc(tam*sizeof(char));
  456. int entrou;
  457. int comprimento =0;
  458. for(int k=mini; k<=maxi; k++){
  459. entrou=0;
  460. for(int i=0; i<(tam); i++){
  461. if(comps[i]==k){
  462. entrou=1;
  463. dec_codes[i]=comprimento;
  464. for(int j=i+1; j<(tam); j++){
  465. if(comps[j]==k){
  466. comprimento= comprimento+1;
  467. dec_codes[j]=comprimento;
  468. }
  469. }
  470. comprimento= (1+comprimento)*2;
  471. break;
  472. }
  473. }
  474. if(entrou==0){
  475. printf("entrou 0 com k= %d\n",k);
  476. comprimento= comprimento*2;
  477. }
  478. }
  479.  
  480. for(int i=0; i<tam; i++){
  481. if(comps[i]==0)
  482. dec_codes[i]=0;
  483. }
  484.  
  485. char codigos[tam][256];
  486. // codigos = (char *)malloc(sizeof(char));
  487. for(int i = 0; i<tam; i++){
  488. bits2String(codigos[i], dec_codes[i],comps[i]);
  489. printf("%s ", codigos[i]);
  490. }
  491.  
  492. printf("\n");
  493. HuffmanTree * hft;
  494. hft = createHFTree();
  495.  
  496. for(int i = 0; i<tam; i++){
  497. if(strlen(codigos[i])>0){
  498. addNode(hft, codigos[i], i, 1);
  499. }
  500. }
  501. printf("\n\n");
  502. /*for(int i = 0; i<tam; i++){
  503. if(strlen(codigos[i])>0){
  504. findNode(hft, codigos[i], 1);
  505. }
  506. }*/
  507. return hft;
  508.  
  509. }
  510.  
  511.  
  512.  
  513. unsigned int * get_length_codes(HuffmanTree *hft, unsigned int *rb, char *availBits, int read_size, FILE *gzfile){
  514. unsigned int bit;
  515. int i_node;
  516. int extra_bits;
  517. unsigned int * length_codes;
  518. length_codes= (unsigned int*)malloc(read_size*sizeof(unsigned int));
  519. int i=0;
  520. while(i<read_size){
  521. while(1){
  522. bit= read_data(1, availBits, rb, gzfile);
  523. i_node= nextNode(hft, '0' + bit);
  524. if(i_node>=-1){
  525. if(i_node==-1)
  526. length_codes[i++]=0;
  527.  
  528. else{
  529. if(i_node <16)
  530. length_codes[i++]= i_node;
  531. else if(i_node==16){
  532. bit= read_data(2, availBits, rb, gzfile);
  533. extra_bits= bit+3;
  534. for(int j=i; j<extra_bits+i;j++)
  535. length_codes[j]= length_codes[i-1];
  536. i+=extra_bits;
  537. }
  538. else if(i_node==17){
  539. bit= read_data(3, availBits, rb, gzfile);
  540. extra_bits= bit+3;
  541. for(int j=i; j<extra_bits+i; j++)
  542. length_codes[j]=0;
  543. i+=extra_bits;
  544.  
  545. }
  546. else if(i_node==18){
  547. bit= read_data(7, availBits, rb, gzfile);
  548. extra_bits= bit+11;
  549. for(int j=i; j<extra_bits+i;j++)
  550. length_codes[j]= 0;
  551. i+=extra_bits;
  552. }
  553. }
  554. resetCurNode(hft);
  555. break;
  556. }
  557. }
  558. }
  559. for(i=0; i<read_size;i++){
  560. printf("%d ",length_codes[i]);
  561. }
  562.  
  563. return length_codes;
  564. }
  565.  
  566.  
  567. /*void get_lengths(HuffmanTree* ht, unsigned int *rb, char *availBits, int siz, FILE *gzFile, unsigned int *codes) {
  568. memset(codes, 0, siz*sizeof(unsigned int));
  569. int i_node, i = 0, j = 0, extraBits;
  570. unsigned int bit;
  571. while(i<siz){
  572. while(1){
  573. bit= read_data(1, &availBits, &rb, gzFile);
  574. i_node = nextNode(ht, '0' + bit);
  575. if(i_node >= -1){
  576. int bits = 0;
  577. if(i_node == -1){ // não encontrou nó
  578. codes[i] = 0;
  579. i++;
  580. }
  581. else{
  582. if(i_node < 16){
  583. codes[i] = i_node;
  584. i++;
  585. }
  586. else if(i_node == 16){
  587. bit= read_data(2, &availBits, &rb, gzFile);
  588. extraBits = bit + 3; //repeat length
  589. for(j=i; j < i + extraBits; j++){
  590. codes[j] = codes[i-1]; //copia o codigo extraBits vezes
  591. }
  592. i+=extraBits;
  593.  
  594. }
  595. else if(i_node == 17){
  596. bit= read_data(3, &availBits, &rb, gzFile);
  597. extraBits = bit + 3;
  598. for(j=i; j < i + extraBits; j++){ //acrescenta extraBits zero
  599. codes[j] = 0;
  600. }
  601. i+=extraBits;
  602. }
  603. else if(i_node == 18){
  604. bit= read_data(7, &availBits, &rb, gzFile);
  605.  
  606. extraBits = bit + 11;
  607. for(j=i; j < i + extraBits; j++){
  608. codes[j] = 0;
  609. }
  610. i+=extraBits;
  611. }
  612. }
  613. resetCurNode (ht);
  614. break;
  615. }
  616. }
  617. }
  618. for(i = 0; i<siz; i++) {
  619. printf("[%d] - %d\n", i, codes[i]);
  620. }
  621. }
  622. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement