IronPython.Zlib / IronPython.Zlib / Compress.cs

/* ****************************************************************************
 *
 * 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 System.Collections.Generic;
using System.Text;
using IronPython.Runtime;
using ComponentAce.Compression.Libs.ZLib;
using IronPython.Runtime.Operations;

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

        internal Compress(int level, int method, int wbits, int memlevel, int strategy)
        {
            zst = new ZStream();
            int err = zst.deflateInit(level, wbits);

            if(err != Z_OK)
            {
                throw PythonOps.ValueError("Could not initialize deflate.");
            }
        }

        public string compress(string data)
        {
            byte[] input = ZlibModule.Latin1.GetBytes(data);
            byte[] output = new byte[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.deflate(Z_NO_FLUSH);

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

                zst.next_out = output;
                zst.avail_out = length;

                err = zst.deflate(Z_NO_FLUSH);
            }

            if(err != Z_OK && err != Z_BUF_ERROR)
            {
                throw PythonOps.ValueError("deflate error.");
            }

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

        public string flush()
        {
            return flush(Z_FINISH);
        }

        public string flush(int mode)
        {
            byte[] output = new byte[ZlibModule.DEFAULTALLOC];

            if(mode == Z_NO_FLUSH)
            {
                return string.Empty;
            }

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

            int err = zst.deflate((FlushStrategy)mode);
            while(err == Z_OK && 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.deflate((FlushStrategy)mode);
            }

            if(err == Z_STREAM_END && mode == Z_FINISH)
            {
                err = zst.deflateEnd();
                if(err != Z_OK)
                {
                    throw PythonOps.ValueError("Error finishing deflate.");
                }
            }
            else if(err != Z_OK && err != Z_BUF_ERROR)
            {
                throw new ZStreamException("deflate error");
            }

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

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

        private ZStream zst;
    }
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.