//
// bitreaders  --  bitreader specializations
//
// Copyright (c) 2003 by Joergen Ibsen / Jibz
// All Rights Reserved
//
// http://www.ibsensoftware.com/
//

/// @file   bitreaders.hpp
/// @brief  bitreader specializations.
/// @author Jibz
/// @date   2003.08.02

#ifndef BITREADERS_HPP_INCLUDED
#define BITREADERS_HPP_INCLUDED

#include <iostream>
#include <vector>
#include <string>

#include "bitreader.hpp"

/// @addtogroup bitio
/// @{

/// Specialization without data.
/// Always returns zero.
class null_bitreader : public bitreader {

public:
    /// Constructor with optional size specification.
    /// @param size_in_bits - the number of bits available.
    null_bitreader(size_t size_in_bits=0) : bitreader(size_in_bits) { ; }

    ~null_bitreader() { finalize(); }

    bool supports_seek() const { return false; }

protected:
    char read_next_byte() { return 0; }
};

/// Specialization for streams.
class stream_bitreader : public bitreader {

public:
    /// Constructor with optional size specification.
    /// @param _s           - the stream to use.
    /// @param size_in_bits - the number of bits available.
    stream_bitreader(std::istream &_s, size_t size_in_bits=0)
	: bitreader(size_in_bits), s(_s) { ; }

    ~stream_bitreader() { finalize(); }

    bool supports_seek() const { return false; }

protected:
    char read_next_byte() { char c; s.get(c); return c; }

    std::istream &s;
};

/// Specialization for vector<char>.
class vector_bitreader : public bitreader {

public:
    /// Constructor. Sets the number of bits available
    /// to the size of the vector.
    /// @param _s - the vector to use.
    vector_bitreader(const std::vector<char> &_s)
	: bitreader(8 * _s.size()), s(_s), index(0) { ; }
    /// Constructor with size specification.
    /// @param _s           - the vector to use.
    /// @param size_in_bits - the number of bits available.
    vector_bitreader(const std::vector<char> &_s, size_t size_in_bits)
	: bitreader(size_in_bits), s(_s), index(0) { ; }

    ~vector_bitreader() { finalize(); }

    bool supports_seek() const { return true; }

protected:
    // Uses indexing to avoid iterator invalidation problems.
    char read_next_byte() { return s[index++]; }
    void set_position(size_t pos) { index = pos; }

    const std::vector<char> &s;
    size_t index;
};

/// Specialization for string.
class string_bitreader : public bitreader {

public:
    /// Constructor. Sets the number of bits available
    /// to the size of the string.
    /// @param _s - the string to use.
    string_bitreader(const std::string &_s)
	: bitreader(8 * _s.size()), s(_s), index(0)
    { ; }
    /// Constructor with size specification.
    /// @param _s           - the string to use.
    /// @param size_in_bits - the number of bits available.
    string_bitreader(const std::string &_s, size_t size_in_bits)
	: bitreader(size_in_bits), s(_s), index(0) { ; }

    ~string_bitreader() { finalize(); }

    bool supports_seek() const { return true; }

protected:
    // Uses indexing to avoid iterator invalidation problems.
    char read_next_byte() { return s[index++]; }
    void set_position(size_t pos) { index = pos; }

    const std::string &s;
    size_t index;
};

/// Specialization for C pointer to char.
class array_bitreader : public bitreader {

public:
    /// Constructor with optional size specification.
    /// @param _s           - the data to use.
    /// @param size_in_bits - the number of bits available.
    array_bitreader(const char *_s, size_t size_in_bits)
	: bitreader(size_in_bits), s(_s), index(0) { ; }

    ~array_bitreader() { finalize(); }

    bool supports_seek() const { return true; }

protected:
    char read_next_byte() { return s[index++]; }
    void set_position(size_t pos) { index = pos; }

    const char *s;
    size_t index;
};

/// @}

#endif // BITREADERS_HPP_INCLUDED
