Exemplo n.º 1
0
        public async Task Extract()
        {
            TotalWords = (await mRead(64)).GetValueOrDefault();
            FileLength?.Invoke(TotalWords);
            mMaxHistory    = Convert.ToUInt32((await mRead(32)).GetValueOrDefault());
            mPresentLength = Convert.ToInt32((await mRead(8)).GetValueOrDefault());
            int historyLengthInBits = Log2_WiegleyJ(mMaxHistory - 1) + 1;

            while (mWordsWritten < TotalWords)
            {
                var type = await mRead(1);

                if (type == null)
                {
                    throw new EndOfStreamException();
                }

                if (type.Value == 1)
                {
                    var word = await mRead(8);

                    if (word == null)
                    {
                        throw new EndOfStreamException();
                    }
                    await mWrite(word.Value, 8);

                    mHistory.AddLast(Convert.ToByte(word.Value));
                    if (mHistory.Count > mMaxHistory)
                    {
                        mHistory.RemoveFirst();
                    }

                    mWordsWritten++;
                    WordsWritten?.Invoke(1);
                }
                else if (type.Value == 0)
                {
                    var offset = await mRead(historyLengthInBits);

                    var length = await mRead(mPresentLength);

                    if (offset == null || length == null)
                    {
                        throw new EndOfStreamException();
                    }

                    if (offset >= mHistory.Count)
                    {
                        throw new ArgumentOutOfRangeException(nameof(offset));
                    }

                    if (offset < length - 1)
                    {
                        throw new ArgumentOutOfRangeException(nameof(length));
                    }

                    var pointer = mHistory.Last;
                    for (int i = 0; i < offset.Value; i++)
                    {
                        pointer = pointer.Previous;
                    }
                    for (int i = 0; i < length.Value; i++)
                    {
                        mHistory.AddLast(pointer.Value);
                        await mWrite(pointer.Value, 8);

                        pointer = pointer.Next;
                        if (mHistory.Count > mMaxHistory)
                        {
                            mHistory.RemoveFirst();
                        }
                    }

                    mWordsWritten += length.Value;
                    WordsWritten?.Invoke(length.Value);
                }
                else
                {
                    throw new ArgumentOutOfRangeException(nameof(type));
                }
            }
        }