Ejemplo 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));
                }
            }
        }
Ejemplo n.º 2
0
        public async Task Decode()
        {
            /* --Structure--
             * word length : byte
             * original file length in bytes : long
             * tree : Bit...
             * code : Bit...
             */

            //Reading word length, original file length
            this.wordLength = (byte)await reader.ReadCustomLength(8);

            long originalFileLength = (long)await reader.ReadCustomLength(64);

            WordLength?.Invoke(this.wordLength, originalFileLength);

            if (originalFileLength > 0)
            {
                //Parsing tree from bits
                TreeNode root = await ParseDecodeTreeAsync();


                //Creating decode table
                Dictionary <long?, (long?code, int codeLength)> encodingTable = await CreateEncodingsAsync(root);

                decimal bytesWritten = 0;
                decimal wordToBytes  = ((decimal)this.wordLength) / 8;

                while (bytesWritten + wordToBytes <= originalFileLength)
                {
                    TreeNode branch = root;
                    while (branch.leaf == null)
                    {
                        long?currentBit = await reader.ReadCustomLength(1);

                        branch = currentBit == 1 ? branch.Right : branch.Left;
                    }
                    bytesWritten += wordToBytes;
                    await this.writer.WriteCustomLength((long)branch.leaf, this.wordLength);

                    WordsWritten?.Invoke(1);
                }
                TreeNode branch2   = root;
                var      da        = (((decimal)originalFileLength) - bytesWritten);
                var      remainder = (8 * (((decimal)originalFileLength) - bytesWritten));
                if (remainder > 0)
                {
                    while (true)
                    {
                        long?currentBit = await reader.ReadCustomLength(1);

                        branch2 = currentBit == 1 ? branch2.Right : branch2.Left;
                        if (branch2.leaf != null)
                        {
                            bytesWritten += wordToBytes;
                            var d = (int)(remainder * this.wordLength);
                            await this.writer.WriteCustomLength((long)(branch2.leaf >> (this.wordLength - (int)remainder)), (int)remainder);

                            WordsWritten?.Invoke(1);
                            break;
                        }
                    }
                }
            }

            //Save
            //await this.writer.FlushBuffer();
        }
Ejemplo n.º 3
0
        public async Task Encode(byte wordLength)
        {
            this.wordLength = wordLength;

            //Calculate word frequencies
            //-------------------------------------------------------------------------
            Dictionary <long?, long> frequencies = await CalculateFrequencyAsync();

            //Check if empty file
            if (frequencies.Count > 0)
            {
                //Create encoding tree
                //-------------------------------------------------------------------------

                //Create sorted list
                List <KeyValuePair <long?, long> > frequencyList = frequencies.ToList();
                frequencyList.Sort((val1, val2) => (val1.Value.CompareTo(val2.Value)));

                //Creating tree
                TreeNode root = await CreateEncodeTree(frequencyList);


                //Create encoding table from tree
                //-------------------------------------------------------------------------
                Dictionary <long?, (long?code, int codeLength)> encodingTable = await CreateEncodingsAsync(root);

                //Encode file
                //-------------------------------------------------------------------------

                /* --Structure--
                 * word length : byte
                 * original file length in bytes : long
                 * tree : Bits...
                 * code : Bits...
                 */

                long originalFileLength = reader.GetFileSize();

                //Writing
                await this.writer.WriteCustomLength((long)this.wordLength, sizeof(byte) * 8);

                await this.writer.WriteCustomLength(originalFileLength, sizeof(long) * 8);

                //Writing tree
                await WriteEncodingTreeAsync(root);

                long?currentWord;
                long bitsWritten = 0;
                while ((currentWord = await this.reader.ReadCustomLength(this.wordLength)) != null)
                {
                    bitsWritten += encodingTable[currentWord].codeLength;
                    await this.writer.WriteCustomLength((long)encodingTable[currentWord].code, encodingTable[currentWord].codeLength);

                    WordsWritten?.Invoke(1);
                }
                for (int i = this.wordLength - 1; i > 0; i--)
                {
                    currentWord = await this.reader.ReadCustomLength(i);

                    if (currentWord != null)
                    {
                        currentWord <<= this.wordLength - i;

                        bitsWritten += encodingTable[currentWord].codeLength;
                        await this.writer.WriteCustomLength((long)encodingTable[currentWord].code, encodingTable[currentWord].codeLength);

                        WordsWritten?.Invoke(1);
                    }
                }
            }
            else
            {
                //File is empty

                //Encode file
                //-------------------------------------------------------------------------

                /* --Structure--
                 * word length : byte
                 * original file length in bytes : long
                 */

                //Writing empty file with word length and size of 0
                await this.writer.WriteCustomLength((long)this.wordLength, sizeof(byte) * 8);

                await this.writer.WriteCustomLength(0, sizeof(long) * 8);
            }

            //Save
            //await this.writer.FlushBuffer();
        }
Ejemplo n.º 4
0
        public async Task Compress(ulong size)
        {
            byte historyLengthInBits = (byte)(Log2_WiegleyJ(mMaxHistory - 1) + 1);
            byte presentLengthInBits = (byte)(Log2_WiegleyJ((uint)mPresent.Count) + 1);

            Console.WriteLine($"History length in bits: {historyLengthInBits}; present length in bits: {presentLengthInBits}");
            int typeThreshold = (1 + historyLengthInBits + presentLengthInBits) / (1 + sizeof(byte));

            // write file size, most significant part first
            await mWrite(unchecked ((long)size), 64);

            // write history size (in bytes)
            await mWrite(mMaxHistory, 32);

            // write present size (in bits)
            await mWrite(presentLengthInBits, 8);

            byte?nextWord;

            while (mPresent.Count > 0)
            {
                int bestPosition    = 0;
                int bestLength      = 0;
                var historyStart    = mHistory.Last;
                int currentPosition = 0;
                while (historyStart != null)
                {
                    var present = mPresent.First;
                    var history = historyStart;
                    if (history.Value == present.Value)
                    {
                        int maxPossibleLength = Math.Min(mPresent.Count, currentPosition + 1);
                        int currentLength     = 1;
                        history = history.Next;
                        present = present.Next;
                        while (currentLength < maxPossibleLength && history.Value == present.Value)
                        {
                            currentLength++;
                            history = history.Next;
                            present = present.Next;
                        }

                        if (currentLength > bestLength)
                        {
                            bestLength   = currentLength;
                            bestPosition = currentPosition;
                        }
                    }

                    currentPosition++;
                    historyStart = historyStart.Previous;
                }

                if (bestLength <= typeThreshold)
                {
                    // couldn't find matching word
                    await mWrite(1, 1);

                    byte word = mPresent.First.Value;
                    mPresent.RemoveFirst();
                    await mWrite(word, 8);

                    mHistory.AddLast(word);

                    WordsWritten?.Invoke(1);
                    nextWord = await mNextWord();

                    if (nextWord != null)
                    {
                        mPresent.AddLast(nextWord.Value);
                    }
                }
                else
                {
                    // found a matching word
                    await mWrite(0, 1);
                    await mWrite(bestPosition, historyLengthInBits);
                    await mWrite(bestLength, presentLengthInBits);

                    WordsWritten?.Invoke(bestLength);
                    for (int i = 0; i < bestLength; i++)
                    {
                        byte word = mPresent.First.Value;
                        mPresent.RemoveFirst();
                        mHistory.AddLast(word);
                        nextWord = await mNextWord();

                        if (nextWord != null)
                        {
                            mPresent.AddLast(nextWord.Value);
                        }
                    }
                }

                while (mHistory.Count > mMaxHistory)
                {
                    mHistory.RemoveFirst();
                }
            }
        }