// Copyright (C) 2003  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_KERNEl_C_
#define DLIB_BIT_STREAM_KERNEl_C_

#include "bit_stream_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <iosfwd>

namespace dlib
{

    template <
        typename bit_stream_base // implements bit_stream/bit_stream_kernel_abstract.h
        >
    class bit_stream_kernel_c : public bit_stream_base
    {
    public:


        void set_input_stream (
            std::istream& is
        );

        void set_output_stream (
            std::ostream& os
        );

        void close (
        );

        void write (
            int bit
        );

        bool read (
            int& bit
        );

    };

    template <
        typename bit_stream_base
        >
    inline void swap (
        bit_stream_kernel_c<bit_stream_base>& a, 
        bit_stream_kernel_c<bit_stream_base>& b
    ) { a.swap(b); }

// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
    // member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------

    template <
        typename bit_stream_base
        >
    void bit_stream_kernel_c<bit_stream_base>:: 
    set_input_stream (
        std::istream& is
    )
    {
        // make sure requires clause is not broken
        DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ), 
            "\tvoid bit_stream::set_intput_stream"
            << "\n\tbit_stream must not be in write or read mode" 
            << "\n\tthis: " << this
            );

        // call the real function
        bit_stream_base::set_input_stream(is);

    }

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

    template <
        typename bit_stream_base
        >
    void bit_stream_kernel_c<bit_stream_base>:: 
    set_output_stream (
        std::ostream& os
    )
    {

        // make sure requires clause is not broken
        DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ), 
            "\tvoid bit_stream::set_output_stream"
            << "\n\tbit_stream must not be in write or read mode" 
            << "\n\tthis: " << this
            );

        // call the real function
        bit_stream_base::set_output_stream(os);
    }

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

    template <
        typename bit_stream_base
        >
    void bit_stream_kernel_c<bit_stream_base>:: 
    close (
    )
    {

        // make sure requires clause is not broken
        DLIB_CASSERT(( this->is_in_write_mode() == true ) || ( this->is_in_read_mode() == true ), 
            "\tvoid bit_stream::close"
            << "\n\tyou can't close a bit_stream that isn't open" 
            << "\n\tthis: " << this
            );

        // call the real function
        bit_stream_base::close();
    }

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

    template <
        typename bit_stream_base
        >
    void bit_stream_kernel_c<bit_stream_base>:: 
    write (
        int bit
    )
    {
        // make sure requires clause is not broken
        DLIB_CASSERT(( this->is_in_write_mode() == true ) && ( bit == 0 || bit == 1 ), 
            "\tvoid bit_stream::write"
            << "\n\tthe bit stream bust be in write mode and bit must be either 1 or 0" 
            << "\n\tis_in_write_mode() == " << this->is_in_write_mode()
            << "\n\tbit == " << bit
            << "\n\tthis: " << this
            );

        // call the real function
        bit_stream_base::write(bit);

    }

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

    template <
        typename bit_stream_base
        >
    bool bit_stream_kernel_c<bit_stream_base>:: 
    read (
        int& bit
    )
    {

        // make sure requires clause is not broken
        DLIB_CASSERT(( this->is_in_read_mode() == true ), 
            "\tbool bit_stream::read"
            << "\n\tyou can't read from a bit_stream that isn't in read mode" 
            << "\n\tthis: " << this
            );

        // call the real function
        return bit_stream_base::read(bit);

    }

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

}

#endif // DLIB_BIT_STREAM_KERNEl_C_