#ifndef INCLUDED_BOBCAT_EXCEPTION_
#define INCLUDED_BOBCAT_EXCEPTION_

#include <string>
#include <sstream>
#include <exception>
#include <iosfwd>

namespace FBB
{

class Exception: public std::exception
{
    template <typename Type>
    friend Exception &&operator<<(Exception &&tmp, Type const &value);

    std::string d_what;
    
    public:
        enum 
        {
            STRERROR_BUFSIZE = 100
        };

        enum Protection
        {
            ANY,
            EQUAL
        };

        Exception() = default;
        explicit Exception(int errnoValue);              // exception1.cc

        ~Exception() noexcept(true) override;

        static size_t protection(std::string const &name, size_t protect, 
                          Protection type = EQUAL);

        template <typename StreamType>
        static void open(StreamType &stream,                    // open1.f
                         std::string const &name);

        template <typename StreamType>
        static void open(int errnoValue, StreamType &stream,    // open2.f
                         std::string const &name);

        template <typename StreamType>
        static void open(StreamType &stream,                    // open3.f
                            std::string const &name, std::ios::openmode mode);

        template <typename StreamType>
        static void open(int errnoValue, StreamType &stream,    // open4.f
                            std::string const &name, std::ios::openmode mode);
    private:
        char const *what() const noexcept(true) override;
};

#include "open1.f"
#include "open2.f"
#include "open3.f"
#include "open4.f"

    // Free functions

std::ostream &errnodescr(std::ostream &out);

#include "opinsert.f"           // Exception << Type

} // FBB

   
#endif

