Operating system for OpenComputers
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.

124 lines
3.6KB

  1. --[[----------------------------------------------------------------------------
  2. LZSS - encoder / decoder
  3. This is free and unencumbered software released into the public domain.
  4. Anyone is free to copy, modify, publish, use, compile, sell, or
  5. distribute this software, either in source code form or as a compiled
  6. binary, for any purpose, commercial or non-commercial, and by any
  7. means.
  8. In jurisdictions that recognize copyright laws, the author or authors
  9. of this software dedicate any and all copyright interest in the
  10. software to the public domain. We make this dedication for the benefit
  11. of the public at large and to the detriment of our heirs and
  12. successors. We intend this dedication to be an overt act of
  13. relinquishment in perpetuity of all present and future rights to this
  14. software under copyright law.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. For more information, please refer to <http://unlicense.org/>
  23. --]]----------------------------------------------------------------------------
  24. --------------------------------------------------------------------------------
  25. local M = {}
  26. local string, table = string, table
  27. --------------------------------------------------------------------------------
  28. local POS_BITS = 12
  29. local LEN_BITS = 16 - POS_BITS
  30. local POS_SIZE = 1 << POS_BITS
  31. local LEN_SIZE = 1 << LEN_BITS
  32. local LEN_MIN = 3
  33. --------------------------------------------------------------------------------
  34. function M.compress(input)
  35. local offset, output = 1, {}
  36. local window = ''
  37. local function search()
  38. for i = LEN_SIZE + LEN_MIN - 1, LEN_MIN, -1 do
  39. local str = string.sub(input, offset, offset + i - 1)
  40. local pos = string.find(window, str, 1, true)
  41. if pos then
  42. return pos, str
  43. end
  44. end
  45. end
  46. while offset <= #input do
  47. local flags, buffer = 0, {}
  48. for i = 0, 7 do
  49. if offset <= #input then
  50. local pos, str = search()
  51. if pos and #str >= LEN_MIN then
  52. local tmp = ((pos - 1) << LEN_BITS) | (#str - LEN_MIN)
  53. buffer[#buffer + 1] = string.pack('>I2', tmp)
  54. else
  55. flags = flags | (1 << i)
  56. str = string.sub(input, offset, offset)
  57. buffer[#buffer + 1] = str
  58. end
  59. window = string.sub(window .. str, -POS_SIZE)
  60. offset = offset + #str
  61. else
  62. break
  63. end
  64. end
  65. if #buffer > 0 then
  66. output[#output + 1] = string.char(flags)
  67. output[#output + 1] = table.concat(buffer)
  68. end
  69. end
  70. return table.concat(output)
  71. end
  72. --------------------------------------------------------------------------------
  73. function M.decompress(input)
  74. local offset, output = 1, {}
  75. local window = ''
  76. while offset <= #input do
  77. local flags = string.byte(input, offset)
  78. offset = offset + 1
  79. for i = 1, 8 do
  80. local str = nil
  81. if (flags & 1) ~= 0 then
  82. if offset <= #input then
  83. str = string.sub(input, offset, offset)
  84. offset = offset + 1
  85. end
  86. else
  87. if offset + 1 <= #input then
  88. local tmp = string.unpack('>I2', input, offset)
  89. offset = offset + 2
  90. local pos = (tmp >> LEN_BITS) + 1
  91. local len = (tmp & (LEN_SIZE - 1)) + LEN_MIN
  92. str = string.sub(window, pos, pos + len - 1)
  93. end
  94. end
  95. flags = flags >> 1
  96. if str then
  97. output[#output + 1] = str
  98. window = string.sub(window .. str, -POS_SIZE)
  99. end
  100. end
  101. end
  102. return table.concat(output)
  103. end
  104. return M