Source

IronPython.Zlib / IronPython.Zlib / ZlibModule.cs

Full commit
/* ****************************************************************************
 *
 * 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 IronPython.Runtime.Types;
using ComponentAce.Compression.Libs.zlib;
using System.Runtime.InteropServices;

[assembly: PythonModule("zlib", typeof(IronPython.Zlib.ZlibModule))]

namespace IronPython.Zlib
{
    public static class ZlibModule
    {
        public static string ZLIB_VERSION
        {
            get { return zlibConst.version(); }
        }

        internal const int Z_OK = zlibConst.Z_OK;
        internal const int Z_STREAM_END = zlibConst.Z_STREAM_END;
        internal const int Z_NEED_DICT = zlibConst.Z_NEED_DICT;
        internal const int Z_ERRNO = zlibConst.Z_ERRNO;
        internal const int Z_STREAM_ERROR = zlibConst.Z_STREAM_ERROR;
        internal const int Z_DATA_ERROR = zlibConst.Z_DATA_ERROR;
        internal const int Z_MEM_ERROR = zlibConst.Z_MEM_ERROR;
        internal const int Z_BUF_ERROR = zlibConst.Z_BUF_ERROR;
        internal const int Z_VERSION_ERROR = zlibConst.Z_VERSION_ERROR;

        public const int Z_NO_FLUSH = zlibConst.Z_NO_FLUSH;
        public const int Z_SYNC_FLUSH = zlibConst.Z_SYNC_FLUSH;
        public const int Z_FULL_FLUSH = zlibConst.Z_FULL_FLUSH;
        public const int Z_FINISH = zlibConst.Z_FINISH;

        public const int Z_BEST_SPEED = zlibConst.Z_BEST_SPEED;
        public const int Z_BEST_COMPRESSION = zlibConst.Z_BEST_COMPRESSION;
        public const int Z_DEFAULT_COMPRESSION = zlibConst.Z_DEFAULT_COMPRESSION;

        public const int Z_FILTERED = zlibConst.Z_FILTERED;
        public const int Z_HUFFMAN_ONLY = zlibConst.Z_HUFFMAN_ONLY;
        public const int Z_DEFAULT_STRATEGY = zlibConst.Z_DEFAULT_STRATEGY;

        public const int DEFLATED = 8;
        public const int DEF_MEM_LEVEL = 8;
        public const int MAX_WBITS = 15;

        internal const int DEFAULTALLOC = 16 * 1024;

        #region adler32

        public static long adler32(string data)
        {
            return adler32(data, 0);
        }

        public static long adler32(string data, uint value)
        {
            Adler32 a32 = new Adler32();
            byte[] bytes = Latin1.GetBytes(data);
            return a32.adler32(value, bytes, 0, bytes.Length);
        }

        #endregion

        #region crc32

        public static int crc32(string data, [DefaultParameterValue(0)] int baseValue)
        {
            return IronPython.Modules.PythonBinaryAscii.crc32(data, baseValue);
        }

        public static int crc32(string data, uint baseValue)
        {
            return IronPython.Modules.PythonBinaryAscii.crc32(data, baseValue);
        }

        #endregion

        #region compress

        public static string compress(PythonBuffer data)
        {
            return compress(data, Z_DEFAULT_COMPRESSION);
        }

        public static string compress(PythonBuffer data, int level)
        {
            return compress(data.ToString(), level);
        }

        public static string compress(string data)
        {
            return compress(data, Z_DEFAULT_COMPRESSION);
        }

        public static string compress(string data, int level)
        {
            byte[] input = Latin1.GetBytes(data);
            byte[] output = new byte[input.Length + input.Length / 1000 + 12 + 1];

            ZStream zst = new ZStream();
            zst.next_in = input;
            zst.avail_in = input.Length;
            zst.next_out = output;
            zst.avail_out = output.Length;

            int err = zst.deflateInit(level);
            if(err != Z_OK)
            {
                throw new ZStreamException();
            }

            err = zst.deflate(Z_FINISH);

            if(err != Z_STREAM_END)
            {
                zst.deflateEnd();
                throw new ZStreamException();
            }

            err = zst.deflateEnd();

            if(err == Z_OK)
                return Latin1.GetString(output, 0, (int)zst.total_out);
            else
                throw new ZStreamException();
        }

        #endregion

        #region compressobj

        public static Compress compressobj()
        {
            return compressobj(Z_DEFAULT_COMPRESSION, DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
        }

        public static Compress compressobj(int level)
        {
            return new Compress(level, DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
        }

        public static Compress compressobj(int level, int method)
        {
            return new Compress(level, method, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
        }

        public static Compress compressobj(int level, int method, int wbits)
        {
            return new Compress(level, method, wbits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
        }

        public static Compress compressobj(int level, int method, int wbits, int memlevel)
        {
            return new Compress(level, method, wbits, memlevel, Z_DEFAULT_STRATEGY);
        }

        public static Compress compressobj(int level, int method, int wbits, int memlevel, int strategy)
        {
            return new Compress(level, method, wbits, memlevel, strategy);
        }

        #endregion

        #region decompress

        public static string decompress(string data)
        {
            return decompress(data, MAX_WBITS, DEFAULTALLOC);
        }

        public static string decompress(string data, int wbits)
        {
            return decompress(data, wbits, DEFAULTALLOC);
        }

        public static string decompress(string data, int wbits, int bufsize)
        {
            byte[] input = Latin1.GetBytes(data);

            byte[] outputBuffer = new byte[bufsize];
            byte[] output = new byte[bufsize];
            int outputOffset = 0;

            ZStream zst = new ZStream();
            zst.next_in = input;
            zst.avail_in = input.Length;
            zst.next_out = outputBuffer;
            zst.avail_out = outputBuffer.Length;

            int err = zst.inflateInit(wbits);
            if(err != Z_OK)
            {
                throw new ZStreamException();
            }

            do
            {
                err = zst.inflate(Z_FINISH);

                if(err != Z_STREAM_END)
                {
                    if(err == Z_BUF_ERROR && zst.avail_out > 0)
                    {
                        zst.inflateEnd();
                        throw new ZStreamException();
                    }
                    else if(err == Z_OK || (err == Z_BUF_ERROR && zst.avail_out == 0))
                    {
                        // copy to the output and reset the buffer
                        if(outputOffset + outputBuffer.Length > output.Length)
                            Array.Resize(ref output, output.Length * 2);

                        Array.Copy(outputBuffer, 0, output, outputOffset, outputBuffer.Length);
                        outputOffset += outputBuffer.Length;

                        zst.next_out = outputBuffer;
                        zst.avail_out = outputBuffer.Length;
                        zst.next_out_index = 0;
                    }
                    else
                    {
                        zst.inflateEnd();
                        throw new ZStreamException();
                    }
                }

            } while(err != Z_STREAM_END);

            err = zst.inflateEnd();
            if(err != Z_OK)
            {
                throw new ZStreamException();
            }

            if(outputOffset + outputBuffer.Length - zst.avail_out > output.Length)
                Array.Resize(ref output, output.Length * 2);

            Array.Copy(outputBuffer, 0, output, outputOffset, outputBuffer.Length - zst.avail_out);
            outputOffset += outputBuffer.Length - zst.avail_out;

            return Latin1.GetString(output, 0, outputOffset);
        }

        #endregion

        #region decompressobj

        public static Decompress decompressobj()
        {
            return decompressobj(MAX_WBITS);
        }

        public static Decompress decompressobj(int wbits)
        {
            return new Decompress(wbits);
        }

        #endregion

        public static readonly PythonType/*!*/ ZlibErrorType = DynamicHelpers.GetPythonTypeFromType(typeof(ZStreamException));
        public static readonly PythonType/*!*/ error = ZlibErrorType;

        internal static System.Text.Encoding Latin1 = System.Text.Encoding.GetEncoding("iso-8859-1");
    }
}