lz77_compression.sf 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/ruby
  2. # Implementation of the LZ77 compression algorithm.
  3. define(
  4. CHUNK_SIZE = (1 << 16),
  5. )
  6. func compression (str) {
  7. var rep = []
  8. var la = 0
  9. var prefix = ''
  10. var chars = str.chars
  11. var end = chars.end
  12. while (la <= end) {
  13. var n = 1
  14. var p = 0
  15. var token = chars[la]
  16. while ((n < 255) && (la+n <= end) && ((var tmp = prefix.index(token, p)) >= 0)) {
  17. p = tmp
  18. token += chars[la + n]
  19. ++n
  20. }
  21. --n
  22. var c = chars[la + n]
  23. rep << [p, n, c.ord]
  24. la += n+1
  25. prefix += token
  26. }
  27. rep.map {|e| 'SCC'.pack(e...) }.join
  28. }
  29. func decompression (str) {
  30. var ret = ''
  31. var chunk = ''
  32. for slice in (str.slices(4)) {
  33. var (s, l, c) = 'SCC'.unpack(slice)
  34. chunk += (chunk.substr(s, l) + 'C'.pack(c))
  35. if (chunk.len >= CHUNK_SIZE) {
  36. ret += chunk
  37. chunk = ''
  38. }
  39. }
  40. if (chunk != '') {
  41. ret += chunk
  42. }
  43. return ret
  44. }
  45. # How to use:
  46. var compressed = compression('TOBEORNOTTOBEORTOBEORNOT')
  47. say compressed.dump
  48. var decompressed = decompression(compressed)
  49. say decompressed
  50. __END__
  51. "\0\0\0T\0\0\0O\0\0\0B\0\0\0E\1\0\1R\0\0\0N\1\0\1T\0\0\6T\1\0\aT"
  52. TOBEORNOTTOBEORTOBEORNOT