Source

IronPython.Zlib / src / Decompress.cs

Full commit
Jeff Hardy 9134f7e 














Jeff Hardy 2810204 
Jeff Hardy 9134f7e 


















Jeff Hardy 7c4fdc8 



Jeff Hardy 9134f7e 
Jeff Hardy 7c4fdc8 




Jeff Hardy 9134f7e 































































Jeff Hardy 7c4fdc8 
Jeff Hardy 9134f7e 






































Jeff Hardy 7c4fdc8 
Jeff Hardy 9134f7e 












/* ****************************************************************************
 *
 * Copyright (c) Jeff Hardy 2007-2009.
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.txt file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * jdhardy@gmail.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

using System;
using ComponentAce.Compression.Libs.ZLib;
using IronPython.Runtime;
using IronPython.Runtime.Operations;

namespace IronPython.Zlib
{
    [PythonType]
    public class Decompress
    {
        private const int Z_OK = ZlibModule.Z_OK;
        private const int Z_STREAM_END = ZlibModule.Z_STREAM_END;
        private const int Z_BUF_ERROR = ZlibModule.Z_BUF_ERROR;

        private const int Z_SYNC_FLUSH = ZlibModule.Z_SYNC_FLUSH;
        private const int Z_FINISH = ZlibModule.Z_FINISH;

        internal Decompress(int wbits)
        {
            zst = new ZStream();
            int err = zst.inflateInit(wbits);
            switch(err)
            {
                case ZlibModule.Z_OK:
                    break;

                case ZlibModule.Z_STREAM_ERROR:
                    throw PythonOps.ValueError("Invalid initialization option");

                default:
                    throw ZlibModule.zlib_error(this.zst, err, "while creating decompression object");
            }

            _unused_data = string.Empty;
            _unconsumed_tail = string.Empty;
        }

        private string _unused_data;
        public string unused_data
        {
            get { return _unused_data; }
        }

        private string _unconsumed_tail;
        public string unconsumed_tail
        {
            get { return _unconsumed_tail; }
        }

        public string decompress(string value)
        {
            return decompress(value, 0);
        }

        public string decompress(string value, int max_length)
        {
            if(max_length < 0) throw new ArgumentException("max_length must be greater than zero");

            byte[] input = ZlibModule.Latin1.GetBytes(value);
            byte[] output = new byte[max_length > 0 ? max_length : ZlibModule.DEFAULTALLOC];

            long start_total_out = zst.total_out;
            zst.next_in = input;
            zst.next_in_index = 0;
            zst.avail_in = input.Length;
            zst.next_out = output;
            zst.next_out_index = 0;
            zst.avail_out = output.Length;

            int err = zst.inflate(FlushStrategy.Z_SYNC_FLUSH);

            while(err == Z_OK && zst.avail_out == 0)
            {
                if(max_length > 0 && output.Length >= max_length)
                    break;

                int old_length = output.Length;
                Array.Resize(ref output, output.Length * 2);
                zst.next_out = output;
                zst.avail_out = old_length;

                err = zst.inflate(FlushStrategy.Z_SYNC_FLUSH);
            }

            if(max_length > 0)
            {
                _unconsumed_tail = ZlibModule.Latin1.GetString(zst.next_in, zst.next_in_index, zst.avail_in);
            }

            if(err == Z_STREAM_END)
            {
                _unused_data += ZlibModule.Latin1.GetString(zst.next_in, zst.next_in_index, zst.avail_in);
            }
            else if(err != Z_OK && err != Z_BUF_ERROR)
            {
                throw ZlibModule.zlib_error(this.zst, err, "while decompressing");
            }

            return ZlibModule.Latin1.GetString(output, 0, (int)(zst.total_out - start_total_out));
        }

        public string flush()
        {
            return flush(ZlibModule.DEFAULTALLOC);
        }

        public string flush(int length)
        {
            if(length < 1)
                throw PythonOps.ValueError("length must be greater than 0.");

            byte[] output = new byte[length];

            long start_total_out = zst.total_out;
            zst.next_out = output;
            zst.next_out_index = 0;
            zst.avail_out = output.Length;

            int err = zst.inflate(FlushStrategy.Z_FINISH);

            while((err == Z_OK || err == Z_BUF_ERROR) &&zst.avail_out == 0)
            {
                int old_length = output.Length;
                Array.Resize(ref output, output.Length * 2);
                zst.next_out = output;
                zst.avail_out = old_length;

                err = zst.inflate(FlushStrategy.Z_FINISH);
            }

            if(err == Z_STREAM_END)
            {
                err = zst.inflateEnd();
                if(err != Z_OK)
                {
                    throw ZlibModule.zlib_error(this.zst, err, "from inflateEnd()");
                }
            }

            return ZlibModule.Latin1.GetString(output, 0, (int)(zst.total_out - start_total_out));
        }

        //public Compress copy()
        //{
        //    throw new NotImplementedException();
        //}

        private ZStream zst;
    }
}