// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
// (C) Copyright 2003-2007 Jonathan Turkanis
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)

// See http://www.boost.org/libs/iostreams for documentation.

// To configure Boost to work with zlib, see the 
// installation instructions here:
// http://boost.org/libs/iostreams/doc/index.html?path=7

// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> 
// knows that we are building the library (possibly exporting code), rather 
// than using it (possibly importing code).
#define BOOST_IOSTREAMS_SOURCE 

#include <boost/throw_exception.hpp>
#include <boost/iostreams/detail/config/dyn_link.hpp>
#include <boost/iostreams/filter/zlib.hpp> 
#include "zlib.h"   // Jean-loup Gailly's and Mark Adler's "zlib.h" header.
                    // To configure Boost to work with zlib, see the 
                    // installation instructions here:
                    // http://boost.org/libs/iostreams/doc/index.html?path=7

namespace boost { namespace iostreams {

namespace zlib {

                    // Compression levels

const int no_compression       = Z_NO_COMPRESSION;
const int best_speed           = Z_BEST_SPEED;
const int best_compression     = Z_BEST_COMPRESSION;
const int default_compression  = Z_DEFAULT_COMPRESSION;

                    // Compression methods

const int deflated             = Z_DEFLATED;

                    // Compression strategies

const int default_strategy     = Z_DEFAULT_STRATEGY;
const int filtered             = Z_FILTERED;
const int huffman_only         = Z_HUFFMAN_ONLY;

                    // Status codes

const int okay                 = Z_OK;
const int stream_end           = Z_STREAM_END;
const int stream_error         = Z_STREAM_ERROR;
const int version_error        = Z_VERSION_ERROR;
const int data_error           = Z_DATA_ERROR;
const int mem_error            = Z_MEM_ERROR;
const int buf_error            = Z_BUF_ERROR;

                    // Flush codes

const int finish               = Z_FINISH;
const int no_flush             = Z_NO_FLUSH;
const int sync_flush           = Z_SYNC_FLUSH;

                    // Code for current OS

//const int os_code              = OS_CODE;

} // End namespace zlib. 

//------------------Implementation of zlib_error------------------------------//
                    
zlib_error::zlib_error(int error) 
    : BOOST_IOSTREAMS_FAILURE("zlib error"), error_(error) 
    { }

void zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
{
    switch (error) {
    case Z_OK: 
    case Z_STREAM_END: 
    //case Z_BUF_ERROR: 
        return;
    case Z_MEM_ERROR: 
        boost::throw_exception(std::bad_alloc());
    default:
        boost::throw_exception(zlib_error(error));
        ;
    }
}

//------------------Implementation of zlib_base-------------------------------//

namespace detail {

zlib_base::zlib_base()
    : stream_(new z_stream), calculate_crc_(false), crc_(0), crc_imp_(0)
    { }

zlib_base::~zlib_base() { delete static_cast<z_stream*>(stream_); }

void zlib_base::before( const char*& src_begin, const char* src_end,
                        char*& dest_begin, char* dest_end )
{
    z_stream* s = static_cast<z_stream*>(stream_);
    s->next_in = reinterpret_cast<zlib::byte*>(const_cast<char*>(src_begin));
    s->avail_in = static_cast<zlib::uint>(src_end - src_begin);
    s->next_out = reinterpret_cast<zlib::byte*>(dest_begin);
    s->avail_out= static_cast<zlib::uint>(dest_end - dest_begin);
}

void zlib_base::after(const char*& src_begin, char*& dest_begin, bool compress)
{
    z_stream* s = static_cast<z_stream*>(stream_);
    char* next_in = reinterpret_cast<char*>(s->next_in);
    char* next_out = reinterpret_cast<char*>(s->next_out);
    if (calculate_crc_) {
        const zlib::byte* buf = compress ?
            reinterpret_cast<const zlib::byte*>(src_begin) :
            reinterpret_cast<const zlib::byte*>(
                const_cast<const char*>(dest_begin)
            );
        zlib::uint length = compress ?
            static_cast<zlib::uint>(next_in - src_begin) :
            static_cast<zlib::uint>(next_out - dest_begin);
        if (length > 0)
            crc_ = crc_imp_ = crc32(crc_imp_, buf, length);
    }
    total_in_ = s->total_in;
    total_out_ = s->total_out;
    src_begin = const_cast<const char*>(next_in);
    dest_begin = next_out;
}

int zlib_base::xdeflate(int flush)
{ 
    return ::deflate(static_cast<z_stream*>(stream_), flush);
}

int zlib_base::xinflate(int flush)
{ 
    return ::inflate(static_cast<z_stream*>(stream_), flush);
}

void zlib_base::reset(bool compress, bool realloc)
{
    z_stream* s = static_cast<z_stream*>(stream_);
    // Undiagnosed bug:
    // deflateReset(), etc., return Z_DATA_ERROR
    //zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
        realloc ?
            (compress ? deflateReset(s) : inflateReset(s)) :
            (compress ? deflateEnd(s) : inflateEnd(s))
                ;
    //);
    crc_imp_ = 0;
}

void zlib_base::do_init
    ( const zlib_params& p, bool compress, 
      #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
          zlib::xalloc_func /* alloc */, zlib::xfree_func /* free*/, 
      #endif
      void* derived )
{
    calculate_crc_ = p.calculate_crc;
    z_stream* s = static_cast<z_stream*>(stream_);

    // Current interface for customizing memory management 
    // is non-conforming and has been disabled:
    //#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    //    s->zalloc = alloc;
    //    s->zfree = free;
    //#else
        s->zalloc = 0;
        s->zfree = 0;
    //#endif
    s->opaque = derived;
    int window_bits = p.noheader? -p.window_bits : p.window_bits;
    zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
        compress ?
            deflateInit2( s, 
                          p.level,
                          p.method,
                          window_bits,
                          p.mem_level,
                          p.strategy ) :
            inflateInit2(s, window_bits)
    );
}

} // End namespace detail.

//----------------------------------------------------------------------------//

} } // End namespaces iostreams, boost.
