lzs.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #pragma once
  2. namespace Lzs
  3. {
  4. inline std::vector<unsigned char> Decompress(const std::vector<unsigned char>& compressed)
  5. {
  6. if (compressed.size() < 4)
  7. {
  8. abort();
  9. }
  10. const unsigned int inputBufferSize = static_cast<unsigned int>(compressed.size());
  11. const unsigned int input_length =
  12. (((compressed[0] & 0xFF) << 0) |
  13. ((compressed[1] & 0xFF) << 8) |
  14. ((compressed[2] & 0xFF) << 16) |
  15. ((compressed[3] & 0xFF) << 24)) + 4;
  16. if (input_length != inputBufferSize)
  17. {
  18. abort();
  19. }
  20. unsigned int extract_size = (inputBufferSize + 255) & ~255;
  21. std::vector<unsigned char> extract_buffer(extract_size);
  22. unsigned int input_offset = 4;
  23. unsigned int output_offset = 0;
  24. unsigned char control_byte = 0;
  25. unsigned char control_bit = 0;
  26. while (input_offset < inputBufferSize)
  27. {
  28. if (control_bit == 0)
  29. {
  30. control_byte = compressed[input_offset++];
  31. control_bit = 8;
  32. }
  33. if (control_byte & 1)
  34. {
  35. extract_buffer[output_offset++] = compressed[input_offset++];
  36. if (output_offset == extract_size)
  37. {
  38. extract_size += 256;
  39. extract_buffer.resize(extract_size);
  40. }
  41. }
  42. else
  43. {
  44. const unsigned char reference1 = compressed[input_offset++];
  45. const unsigned char reference2 = compressed[input_offset++];
  46. const unsigned short int reference_offset = reference1 | ((reference2 & 0xF0) << 4);
  47. const unsigned char reference_length = (reference2 & 0xF) + 3;
  48. int real_offset = output_offset - ((output_offset - 18 - reference_offset) & 0xFFF);
  49. for (int j = 0; j < reference_length; ++j)
  50. {
  51. if (real_offset < 0)
  52. {
  53. extract_buffer[output_offset++] = 0;
  54. }
  55. else
  56. {
  57. extract_buffer[output_offset++] = extract_buffer[real_offset];
  58. }
  59. if (output_offset == extract_size)
  60. {
  61. extract_size += 256;
  62. extract_buffer.resize(extract_size);
  63. }
  64. ++real_offset;
  65. }
  66. }
  67. control_byte >>= 1;
  68. control_bit--;
  69. }
  70. // Truncate to exact size
  71. extract_buffer.resize(output_offset);
  72. return extract_buffer;
  73. }
  74. }