2
0

LZSSStream.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. namespace OpenVIII
  6. {
  7. /// <summary>
  8. /// Attempt to make the LZSS into a stream that we can read from on the fly...
  9. /// putting on back burner as I feel like it's taking too much time. This class does not work. So discard or ignore.
  10. /// </summary>
  11. public class LZSSStream : Stream
  12. {
  13. #region License
  14. /**************************************************************
  15. LZSS.C -- A Data Compression Program
  16. (tab = 4 spaces)
  17. ***************************************************************
  18. 4/6/1989 Haruhiko Okumura
  19. Use, distribute, and modify this program freely.
  20. Please send me your improved versions.
  21. PC-VAN SCIENCE
  22. NIFTY-Serve PAF01022
  23. CompuServe 74050,1022
  24. **************************************************************/
  25. #endregion License
  26. private static readonly int N = 4096;
  27. private static readonly int F = 18;
  28. private static readonly int THRESHOLD = 2;
  29. private static readonly int EOF = -1;
  30. private long _length;
  31. private List<byte> outfile;
  32. public LZSSStream(Stream src, long infilepos, long position) {
  33. infile = src;
  34. _infilepos = infilepos;
  35. Position = position;
  36. //_length = length;
  37. outfile = new List<byte>();
  38. infile.Seek(infilepos, SeekOrigin.Begin);
  39. }
  40. public override bool CanRead => true;
  41. public override bool CanSeek => false;
  42. public override bool CanWrite => false;
  43. public override long Length { get => _length; }
  44. private Stream infile;
  45. private long _infilepos;
  46. public override long Position { get; set; }
  47. ///<remarks>Code borrowed from Java's implementation of LZSS by antiquechrono</remarks>
  48. private byte[] Decode(int offset, int count)
  49. {
  50. int i, j, k, r, c;
  51. int[] text_buf = new int[N + F - 1]; /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */
  52. //unsigned int flags;
  53. int flags;
  54. for (i = 0; i < N - F; i++) text_buf[i] = 0;
  55. r = N - F; flags = 0;
  56. for (; ; )
  57. {
  58. if (((flags >>= 1) & 256) == 0)
  59. {
  60. if ((c = infile.ReadByte()) == EOF) break;
  61. flags = c | 0xff00; /* uses higher byte cleverly */
  62. } /* to count eight */
  63. // if (flags & 1) {
  64. if ((flags & 1) == 1)
  65. {
  66. if ((c = infile.ReadByte()) == EOF) break;
  67. outfile.Add((byte)c);
  68. text_buf[r++] = c;
  69. r &= (N - 1);
  70. }
  71. else
  72. {
  73. if ((i = infile.ReadByte()) == EOF) break;
  74. if ((j = infile.ReadByte()) == EOF) break;
  75. i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
  76. for (k = 0; k <= j; k++)
  77. {
  78. c = text_buf[(i + k) & (N - 1)];
  79. outfile.Add((byte)c);
  80. text_buf[r++] = c;
  81. r &= (N - 1);
  82. }
  83. }
  84. }
  85. try
  86. {
  87. return outfile.Skip(offset).Take(count).ToArray();
  88. }
  89. finally
  90. {
  91. //outfile.RemoveRange(0,offset + count);
  92. }
  93. }
  94. public override void Flush() => throw new NotImplementedException();
  95. public override int Read(byte[] buffer, int offset, int count)
  96. {
  97. if(CanRead)
  98. {
  99. var decbuffer = Decode(offset, count);
  100. for (int a = 0; a < buffer.Length && a<count && a < decbuffer.Length; a++)
  101. {
  102. buffer[a] = decbuffer[a];
  103. }
  104. return Math.Min(Math.Min(count, buffer.Length), decbuffer.Length);
  105. }
  106. return 0;
  107. }
  108. public override long Seek(long offset, SeekOrigin origin)
  109. {
  110. if(CanSeek)
  111. {
  112. switch(origin)
  113. {
  114. case SeekOrigin.Begin:
  115. Position = offset;
  116. break;
  117. case SeekOrigin.Current:
  118. Position += offset;
  119. break;
  120. case SeekOrigin.End:
  121. Position = _length + offset;
  122. break;
  123. }
  124. }
  125. return Position;
  126. }
  127. public override void SetLength(long value) => _length = value;
  128. public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
  129. }
  130. }