Source

IronPython.Zlib / src / ZlibModule.cs

Full commit
Jeff Hardy 9134f7e 














Jeff Hardy 2810204 


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 


































































Jeff Hardy 7c4fdc8 

Jeff Hardy 9134f7e 









Jeff Hardy 7c4fdc8 
Jeff Hardy 9134f7e 
















Jeff Hardy 7c4fdc8 
Jeff Hardy 9134f7e 







Jeff Hardy 7c4fdc8 
Jeff Hardy 9134f7e 


























Jeff Hardy 2810204 










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 System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ComponentAce.Compression.Libs.ZLib;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;

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

namespace IronPython.Zlib
{
    public static class ZlibModule
    {
        public const string ZLIB_VERSION = "1.2.3";     // just match the zlib version in Python 2.6

        internal const int Z_OK = (int)ZLibResultCode.Z_OK;
        internal const int Z_STREAM_END = (int)ZLibResultCode.Z_STREAM_END;
        internal const int Z_NEED_DICT = (int)ZLibResultCode.Z_NEED_DICT;
        internal const int Z_ERRNO = (int)ZLibResultCode.Z_ERRNO;
        internal const int Z_STREAM_ERROR = (int)ZLibResultCode.Z_STREAM_ERROR;
        internal const int Z_DATA_ERROR = (int)ZLibResultCode.Z_DATA_ERROR;
        internal const int Z_MEM_ERROR = (int)ZLibResultCode.Z_MEM_ERROR;
        internal const int Z_BUF_ERROR = (int)ZLibResultCode.Z_BUF_ERROR;
        internal const int Z_VERSION_ERROR = (int)ZLibResultCode.Z_VERSION_ERROR;

        public const int Z_NO_FLUSH = (int)FlushStrategy.Z_NO_FLUSH;
        public const int Z_SYNC_FLUSH = (int)FlushStrategy.Z_SYNC_FLUSH;
        public const int Z_FULL_FLUSH = (int)FlushStrategy.Z_FULL_FLUSH;
        public const int Z_FINISH = (int)FlushStrategy.Z_FINISH;

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

        public const int Z_FILTERED = (int)CompressionStrategy.Z_FILTERED;
        public const int Z_HUFFMAN_ONLY = (int)CompressionStrategy.Z_HUFFMAN_ONLY;
        public const int Z_DEFAULT_STRATEGY = (int)CompressionStrategy.Z_DEFAULT_STRATEGY;

        public const int DEFLATED = 8;
        public const int DEF_MEM_LEVEL = 8;
        public const int MAX_WBITS = ZLibUtil.MAX_WBITS;

        internal const int DEFAULTALLOC = 16 * 1024;

        #region adler32

        public static int adler32(string data, [DefaultParameterValue(1L)] long baseValue)
        {
            return adler32(Latin1.GetBytes(data), baseValue);
        }

        public static int adler32(byte[] data, [DefaultParameterValue(1L)] long baseValue)
        {
            return (int)Adler32.GetAdler32Checksum(baseValue, data, 0, data.Length);
        }

        #endregion

        #region crc32

        public static int crc32(string data, [DefaultParameterValue(0L)] long baseValue)
        {
            if(baseValue < int.MinValue || baseValue > uint.MaxValue)
                throw new ArgumentOutOfRangeException("baseValue");

            if(baseValue >= 0 && baseValue <= uint.MaxValue)
                return IronPython.Modules.PythonBinaryAscii.crc32(data, (uint)baseValue);
            else
                return IronPython.Modules.PythonBinaryAscii.crc32(data, (int)baseValue);
        }

        public static int crc32(byte[] data, [DefaultParameterValue(0L)] long baseValue)
        {
            if(baseValue < int.MinValue || baseValue > uint.MaxValue)
                throw new ArgumentOutOfRangeException("baseValue");

            if(baseValue >= 0 && baseValue <= uint.MaxValue)
                return IronPython.Modules.PythonBinaryAscii.crc32(data, (uint)baseValue);
            else
                return IronPython.Modules.PythonBinaryAscii.crc32(data, (int)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);
            switch(err)
            {
                case (Z_OK):
                    break;
                
                case (Z_STREAM_ERROR):
                    throw PythonOps.CreateThrowable(error,
                                    "Bad compression level");
                
                default:
                    zst.deflateEnd();
                    zlib_error(zst, err, "while compressing data");
                    return null;
            }

            err = zst.deflate(FlushStrategy.Z_FINISH);

            if(err != Z_STREAM_END)
            {
                zst.deflateEnd();
                throw zlib_error(zst, err, "while compressing data");
            }

            err = zst.deflateEnd();

            if(err == Z_OK)
                return Latin1.GetString(output, 0, (int)zst.total_out);
            else
                throw zlib_error(zst, err, "while finishing compression");
        }

        #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)
            {
                zst.inflateEnd();
                throw zlib_error(zst, err, "while preparing to decompress data");
            }

            do
            {
                err = zst.inflate(FlushStrategy.Z_FINISH);
                if(err != Z_STREAM_END)
                {
                    if(err == Z_BUF_ERROR && zst.avail_out > 0)
                    {
                        zst.inflateEnd();
                        throw zlib_error(zst, err, "while decompressing data");
                    }
                    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 zlib_error(zst, err, "while decompressing data");
                    }
                }

            } while(err != Z_STREAM_END);

            err = zst.inflateEnd();
            if(err != Z_OK)
            {
                throw zlib_error(zst, err, "while finishing data decompression");
            }

            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

        [SpecialName]
        public static void PerformModuleReload(PythonContext context, PythonDictionary dict)
        {
            error = context.EnsureModuleException("zlib.error", PythonExceptions.Exception, dict, "error", "zlib");
        }

        public static PythonType error;
        internal static Exception MakeError(params object[] args)
        {
            return PythonOps.CreateThrowable(error, args);
        }

        internal static Exception zlib_error(ZStream zst, int err, string msg)
        {
            string zmsg = zst.msg;
            if(zmsg == null)
            {
                switch(err)
                {
                    case Z_BUF_ERROR:
                        zmsg = "incomplete or truncated stream";
                        break;
                    case Z_STREAM_ERROR:
                        zmsg = "inconsistent stream state";
                        break;
                    case Z_DATA_ERROR:
                        zmsg = "invalid input data";
                        break;
                }
            }

            if(zmsg == null)
                return MakeError(string.Format("Error {0} {1}", err, msg));
            else
                return MakeError(string.Format("Error {0} {1}: {2}", err, msg, zmsg));
        }

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