fork(2) download
  1. #!/usr/bin/env python3
  2. from pprint import pprint as P
  3. import struct
  4.  
  5. def test(data_in, data_out):
  6. print("==========================")
  7. print("IN: %s"%data_in)
  8. try:
  9. r = decode(data_in)
  10. except:
  11. print("ERR: exception during decoding")
  12. else:
  13. print("FINAL OUT: %s"%r)
  14. if r == data_out:
  15. print("MATCH")
  16. else:
  17. print("ERR: decompressed output doesnt match %d %d"%(len(r), len(data_out)))
  18.  
  19. def main():
  20.  
  21. test(bytes.fromhex(" ff ff ff 1f 61 62 63 17 00 0f ff 26 01"),
  22. b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'+
  23. b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'+
  24. b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'+
  25. b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'+
  26. b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc')
  27.  
  28. test(bytes.fromhex('ff ff ff 7f ff 07 00 0f ff 00 00 fc ff 01 00'),
  29. b'\xff'*(1024*128))
  30.  
  31. def decode(ibuf):
  32. obuf = bytearray()
  33. BufferedFlags = 0
  34. BufferedFlagCount = 0
  35. InputPosition = 0
  36. OutputPosition = 0
  37. LastLengthHalfByte = 0
  38.  
  39. def output(x):
  40. obuf.append(x)
  41. #print("OUT: %02x"%x)
  42.  
  43. while True:
  44. if BufferedFlagCount == 0:
  45. # Read 4 bytes at InputPosition
  46. BufferedFlags = struct.unpack_from('<I', ibuf, InputPosition)[0]
  47. InputPosition += 4
  48. BufferedFlagCount = 32
  49. BufferedFlagCount = BufferedFlagCount - 1
  50. if (BufferedFlags & (1 << BufferedFlagCount)) == 0:
  51. # Copy 1 byte from InputPosition to OutputPosition. Advance both.
  52. output(ibuf[InputPosition])
  53. InputPosition += 1
  54. OutputPosition += 1
  55. else:
  56. if InputPosition == len(ibuf):
  57. # Decompression is complete. Return with success.
  58. return obuf
  59. # Read 2 bytes from InputPosition
  60. MatchBytes = struct.unpack_from('<H', ibuf, InputPosition)[0]
  61. InputPosition += 2
  62. MatchLength = MatchBytes % 8
  63. MatchOffset = (MatchBytes // 8) + 1
  64. if MatchLength == 7:
  65. if LastLengthHalfByte == 0:
  66. #read 1 byte from InputPosition
  67. MatchLength = ibuf[InputPosition]
  68. MatchLength = MatchLength % 16
  69. LastLengthHalfByte = InputPosition
  70. InputPosition += 1
  71. else:
  72. # read 1 byte from LastLengthHalfByte position
  73. MatchLength = ibuf[LastLengthHalfByte]
  74. MatchLength = MatchLength / 16
  75. LastLengthHalfByte = 0
  76. if MatchLength == 15:
  77. # read 1 byte from InputPosition
  78. MatchLength = ibuf[InputPosition]
  79. InputPosition += 1
  80. if MatchLength == 255:
  81. # read 2 bytes from InputPosition
  82. MatchLength = struct.unpack_from('<H', ibuf, InputPosition)[0]
  83. InputPosition += 2
  84. if MatchLength < 15 + 7:
  85. raise Exception("error")
  86. MatchLength -= (15 + 7)
  87. MatchLength += 15
  88. MatchLength += 7
  89. MatchLength += 3
  90. for i in range(MatchLength):# i = 0 to MatchLength - 1:
  91. # Copy 1 byte from OutputBuffer[OutputPosition - MatchOffset]
  92. output(obuf[OutputPosition-MatchOffset])
  93. OutputPosition += 1
  94.  
  95. if __name__ == '__main__':
  96. main()
  97.  
Success #stdin #stdout 0.02s 27968KB
stdin
Standard input is empty
stdout
==========================
IN: b'\xff\xff\xff\x1fabc\x17\x00\x0f\xff&\x01'
FINAL OUT: bytearray(b'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc')
MATCH
==========================
IN: b'\xff\xff\xff\x7f\xff\x07\x00\x0f\xff\x00\x00\xfc\xff\x01\x00'
ERR: exception during decoding