(C) Relatively high density file backups on paper. Cross-platform CLI port of Ollydbg's Paperback from Windows and Borland C.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Compress.cpp 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /* Author: David Bourgin, 1995 */
  2. #include <cstddef>
  3. #include <cstdlib>
  4. #include "Compress.h"
  5. // Write codelen bits to the output buffer.
  6. void Writecode(uint value) {
  7. wrvalue=(wrvalue << codelen)|value;
  8. wrbits+=codelen;
  9. while (wrbits>=NBITS) {
  10. wrbits-=NBITS;
  11. if (nout<nbout) // Check if buffer is not full first
  12. bout[nout++]=(uchar)(wrvalue>>wrbits);
  13. wrvalue&=(1<<wrbits)-1;
  14. };
  15. };
  16. // Compress the input buffer of length nbufin into the output buffer of length
  17. // nbufout. Function returns the length of the compressed data or -1 if some
  18. // error was detected during compression.
  19. int Compress(uchar *bufin,ulong nbufin,uchar *bufout,ulong nbufout) {
  20. t_centry *currnode,*newnode;
  21. int i;
  22. ushort symbol;
  23. if (bufin==NULL || bufout==NULL || nbufin<=0 || nbufout<=sizeof(long))
  24. return -1; // Bad input parameters
  25. cdict=(t_centry *)calloc((1<<DBITLEN)*sizeof(t_centry));
  26. if (cdict==NULL) return -1;
  27. for (i=0; i<(1<<DBITLEN); i++)
  28. cdict[i].code=(ushort)i;
  29. for (i=0; i<(1<<NBITS); i++)
  30. cdict[i].character=(ushort)i;
  31. ndict=1<<NBITS;
  32. codelen=NBITS+1;
  33. bout=bufout; nbout=nbufout;
  34. nin=0; nout=0;
  35. wrvalue=0; wrbits=0;
  36. currnode=cdict+bufin[nin++];
  37. while (nin<nbufin) {
  38. symbol=bufin[nin++];
  39. if (currnode->lptr==NULL)
  40. newnode=currnode;
  41. else {
  42. newnode=currnode->lptr;
  43. while ((newnode->character!=symbol) && (newnode->rptr!=NULL))
  44. newnode=newnode->rptr;
  45. ;
  46. };
  47. if ((newnode!=currnode) && (newnode->character==symbol))
  48. currnode=newnode;
  49. else {
  50. // Insert new node into the dictionary
  51. Writecode(currnode->code);
  52. cdict[ndict].character=(ushort)symbol;
  53. if (currnode==newnode)
  54. newnode->lptr=cdict+ndict;
  55. else
  56. newnode->rptr=cdict+ndict;
  57. ndict++;
  58. if (ndict==(1u<<codelen))
  59. codelen++;
  60. if (ndict==(1<<DBITLEN)) {
  61. // Reinitialize the dictionary
  62. for (i=0; i<(1<<DBITLEN); i++) {
  63. cdict[i].lptr=NULL;
  64. cdict[i].rptr=NULL; };
  65. ndict=1<<NBITS;
  66. codelen=NBITS+1;
  67. };
  68. currnode=cdict+symbol;
  69. };
  70. };
  71. Writecode(currnode->code);
  72. if (wrbits>0 && nout<nbout)
  73. bout[nout++]=(uchar)(wrvalue<<(NBITS-wrbits));
  74. free(cdict);
  75. return nout;
  76. };
  77. // Sends the string in the output stream given by the link of the LZW
  78. // dictionary. Variable character contains to the end of the routine the first
  79. // character of the string. Attention, danger of stack overflow!
  80. void Writelink(t_dentry *chain,uint *character) {
  81. if (chain->prev!=NULL) {
  82. Writelink(chain->prev,character);
  83. if (nout<nbout) bout[nout++]=(uchar)(chain->character); }
  84. else {
  85. if (nout<nbout) bout[nout++]=(uchar)(*character=chain->character);
  86. };
  87. };
  88. // Writes the string of bytes associated to current_node and returns the
  89. // first character of this string.
  90. uint Writestring(uint prevcode,uint currcode,uint firstchar) {
  91. uint character;
  92. if (currcode<ndict)
  93. Writelink(ddict+currcode,&character);
  94. else {
  95. Writelink(ddict+prevcode,&character);
  96. if (nout<nbout) bout[nout++]=(uchar)(firstchar); }
  97. return character;
  98. };
  99. // Get codelen bits from the input array
  100. uint Readcode(void) {
  101. uint read_code;
  102. while (rdbits<codelen && nin<nbin) {
  103. rdvalue=(rdvalue<<NBITS)| bin[nin++];
  104. rdbits+=NBITS; };
  105. rdbits-=codelen;
  106. read_code=rdvalue>>rdbits;
  107. rdvalue&=((1<<rdbits)-1);
  108. return read_code;
  109. };
  110. // Decompress the input buffer of length nbufin into the output buffer of length
  111. // nbufout. Function returns the length of the decompressed data or -1 if some
  112. // error was detected during decompression.
  113. int Decompress(uchar *bufin,ulong nbufin,uchar *bufout,ulong nbufout) {
  114. uint i;
  115. uint prevcode,currcode;
  116. uint firstchar;
  117. if (bufin==NULL || bufout==NULL || nbufin<=sizeof(long) || nbufout<=0)
  118. return -1; // Bad input parameters
  119. ddict=(t_dentry *)calloc((1<<DBITLEN)*sizeof(t_dentry));
  120. if (ddict==NULL) return -1;
  121. for (i=0; i<(1<<NBITS); i++) ddict[i].character=(ushort)i;
  122. ndict=1<<NBITS;
  123. codelen=NBITS+1;
  124. rdvalue=0; rdbits=0;
  125. bin=bufin; nbin=nbufin;
  126. bout=bufout; nbout=nbufout;
  127. nin=0; nout=0; firstchar=0;
  128. prevcode=currcode=Readcode();
  129. firstchar=Writestring(prevcode,currcode,firstchar);
  130. while (nin<nbin || rdbits>=codelen) {
  131. currcode=Readcode();
  132. if (currcode>ndict) {
  133. free(ddict); // Error: index outside dictionary
  134. return -1; };
  135. firstchar=Writestring(prevcode,currcode,firstchar);
  136. if (ndict==(1<<DBITLEN)-2) {
  137. for (i=1<<NBITS; i<(1<<DBITLEN); i++)
  138. ddict[i].prev=NULL;
  139. ndict=1<<NBITS;
  140. codelen=NBITS+1;
  141. if (nin<nbin || rdbits>=codelen) {
  142. prevcode=currcode=Readcode();
  143. firstchar=Writestring(prevcode,currcode,firstchar);
  144. }; }
  145. else {
  146. ddict[ndict].character=(ushort)firstchar;
  147. ddict[ndict].prev=ddict+prevcode;
  148. ndict++;
  149. if (ndict+1==(1u<<codelen)) codelen++; };
  150. prevcode=currcode; }
  151. free(ddict);
  152. return nout;
  153. };