fork download
  1. #include <iostream>
  2. #include <string.h>
  3. using namespace std;
  4.  
  5.  
  6. //***************************************************************************
  7. //
  8. // Implementation of DecompressJCALG1 in C++ by Jeffrey Lim
  9. //
  10. // JCALG1 is copyright (C) Jeremy Collake
  11. //
  12. // Note: This code should work on any little-endian system that supports
  13. // mis-aligned reads. To support non-little endian, the functions
  14. // CompressionSourceData::GetBit() and CompressionSourceData::GetBits(int)
  15. // need to be modified.
  16. // If the target system does not support mis-aligned reads, either
  17. // the actual decompresssion data has to be made to align to 4-byte
  18. // boundaries [note that there's a 10-byte header on JCALG1], or else
  19. // the CompressionSourceData routines need to be modified.
  20. //
  21. //***************************************************************************
  22.  
  23. //***************************************************************************
  24.  
  25. class CompressionSourceData
  26. {
  27. private:
  28. const unsigned *Data;
  29. unsigned BitBuffer;
  30. int BitsRemaining;
  31.  
  32. public:
  33. CompressionSourceData(const unsigned *iData);
  34.  
  35. int GetBit();
  36. int GetBits(int Count);
  37. int GetInteger();
  38. };
  39.  
  40. CompressionSourceData::CompressionSourceData(const unsigned *iData)
  41. {
  42. Data = iData;
  43. BitBuffer = 0;
  44. BitsRemaining = 0;
  45. }
  46.  
  47. int CompressionSourceData::GetBit()
  48. {
  49. int ReturnValue;
  50.  
  51. if(!BitsRemaining)
  52. {
  53. BitsRemaining = 32;
  54. BitBuffer = *Data++;
  55. }
  56.  
  57. ReturnValue = BitBuffer >> 31;
  58. BitBuffer <<= 1;
  59. BitsRemaining--;
  60. printf("dbr %d, ", BitBuffer);
  61. return ReturnValue;
  62. }
  63.  
  64. int CompressionSourceData::GetBits(int Count)
  65. {
  66. if(BitsRemaining >= Count)
  67. {
  68. int ReturnValue = BitBuffer >> (32-Count);
  69. BitBuffer <<= Count;
  70. BitsRemaining -= Count;
  71. return ReturnValue;
  72. }
  73. else
  74. {
  75. int Remainder = Count-BitsRemaining;
  76.  
  77. int ReturnValue = BitBuffer >> (32-BitsRemaining) << Remainder;
  78. BitBuffer = *Data++;
  79.  
  80. ReturnValue |= BitBuffer >> (32-Remainder);
  81. BitsRemaining = 32-Remainder;
  82. BitBuffer <<= Remainder;
  83.  
  84. return ReturnValue;
  85. }
  86. }
  87.  
  88. int CompressionSourceData::GetInteger()
  89. {
  90. int Value = 1;
  91. do
  92. {
  93. Value = (Value<<1) + GetBit();
  94. } while(GetBit());
  95.  
  96. return Value;
  97. }
  98.  
  99. //***************************************************************************
  100.  
  101. struct CompressionState
  102. {
  103. int LastIndex;
  104. int IndexBase;
  105. int LiteralBits;
  106. int LiteralOffset;
  107.  
  108. CompressionState() { LastIndex = 1; IndexBase = 8; }
  109. };
  110.  
  111. //***************************************************************************
  112.  
  113. void TransferMatch(unsigned char* &Destination, int MatchOffset, int MatchLength)
  114. {
  115. unsigned char* p = Destination;
  116. unsigned char* s = p-MatchOffset;
  117.  
  118. do
  119. {
  120. *p++ = *s++;
  121. } while(--MatchLength);
  122.  
  123. Destination = p;
  124. }
  125.  
  126. //***************************************************************************
  127.  
  128. void DecompressJCALG1(void *pDestination, const unsigned *pSource)
  129. {
  130. CompressionState State;
  131. CompressionSourceData Source(pSource+10); // +10 skips the header of JCALG. A more robust routine would check this
  132. unsigned char *Destination = (unsigned char*) pDestination;
  133.  
  134. while(1)
  135. {
  136. if(Source.GetBit())
  137. {
  138. // Is Literal
  139. *Destination++ = Source.GetBits(State.LiteralBits) + State.LiteralOffset;
  140. }
  141. else
  142. {
  143. // Isn't literal
  144. if(Source.GetBit())
  145. {
  146. // Normal phrase
  147. int HighIndex = Source.GetInteger();
  148.  
  149. if(HighIndex == 2) // Use the last index
  150. {
  151. int PhraseLength = Source.GetInteger();
  152. TransferMatch(Destination, State.LastIndex, PhraseLength);
  153. }
  154. else
  155. {
  156. State.LastIndex = ((HighIndex-3) << State.IndexBase) + Source.GetBits(State.IndexBase);
  157.  
  158. int PhraseLength = Source.GetInteger();
  159.  
  160. if(State.LastIndex >= 0x10000) PhraseLength += 3;
  161. else if(State.LastIndex >= 0x37FF) PhraseLength += 2;
  162. else if(State.LastIndex >= 0x27F) PhraseLength++;
  163. else if(State.LastIndex <= 127) PhraseLength += 4;
  164.  
  165. TransferMatch(Destination, State.LastIndex, PhraseLength);
  166. }
  167. }
  168. else
  169. {
  170. if(Source.GetBit())
  171. {
  172. // OneBytePhrase or literal size change
  173. int OneBytePhraseValue = Source.GetBits(4) - 1;
  174. if(OneBytePhraseValue == 0)
  175. {
  176. *Destination++ = 0;
  177. }
  178. else if(OneBytePhraseValue > 0)
  179. {
  180. *Destination = *(Destination-OneBytePhraseValue);
  181. Destination++;
  182. }
  183. else
  184. {
  185. if(Source.GetBit())
  186. {
  187. // Next block
  188. do
  189. {
  190. for(int i = 0; i < 256; i++) *Destination++ = Source.GetBits(8);
  191. } while(Source.GetBit());
  192. }
  193. else
  194. {
  195. // New literal size
  196. State.LiteralBits = 7+Source.GetBit();
  197. State.LiteralOffset = 0;
  198. if(State.LiteralBits != 8)
  199. {
  200. State.LiteralOffset = Source.GetBits(8);
  201. }
  202. }
  203. }
  204. }
  205. else
  206. {
  207. // Short match
  208. int NewIndex = Source.GetBits(7);
  209. int MatchLength = 2+Source.GetBits(2);
  210. printf("ni %d, ml %d ", NewIndex, MatchLength);
  211. if(NewIndex == 0)
  212. {
  213. // Extended short
  214. if(MatchLength == 2) break; // End of decompression
  215.  
  216. State.IndexBase = Source.GetBits(MatchLength+1);
  217. }
  218. else
  219. {
  220. State.LastIndex = NewIndex;
  221. TransferMatch(Destination, State.LastIndex, MatchLength);
  222. }
  223. }
  224. }
  225. }
  226. }
  227. }
  228.  
  229. //***************************************************************************
  230.  
  231.  
  232. int main() {
  233. // your code goes here
  234. unsigned int* s = new unsigned int[22]{
  235. 74, 67, 44, 0, 0, 0, 14, 0, 0, 0, 69, 17, 0, 32, 18, 137, 20, 250, 0, 0, 0, 32 };
  236. unsigned char d[44];
  237. DecompressJCALG1(&d, s);
  238. for (int i = 0; i < 44; i++) {
  239. printf("%d, ", d[i]);
  240. }
  241. cout << endl;
  242.  
  243. return 0;
  244. }
  245.  
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
dbr 138, dbr 276, dbr 552, ni 0, ml 2 136, 189, 135, 139, 188, 85, 0, 0, 253, 174, 103, 139, 188, 85, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 174, 103, 139, 188, 85, 0, 0, 32, 169, 103, 139,