#ifndef _STD_STDEXCEPT
#define _STD_STDEXCEPT

// from rb3 decomp

#include "shared_ptr.hpp"
#include <cstring>
#include <exception>
#include <new>

namespace std {

    class logic_error : public exception {
    public:
        explicit logic_error(const char *what_arg) :
            m_What(new char[strlen(what_arg) + 1]) {}

        virtual const char *what() const {
            return (char *)m_What.get();
        }

    private:
        detail::shared_ptr<char[]> m_What;
    };

    class runtime_error : public exception {
    public:
        explicit runtime_error(const char *what_arg) :
            m_What(new char[strlen(what_arg) + 1]) {}

        virtual const char *what() const {
            return m_What.get();
        }

    private:
        detail::shared_ptr<char[]> m_What;
    };

    class domain_error : public logic_error {
    public:
        explicit domain_error(const char *what_arg) :
            logic_error(what_arg) {}
    };

    class invalid_argument : public logic_error {
    public:
        explicit invalid_argument(const char *what_arg) :
            logic_error(what_arg) {}
    };

    class length_error : public logic_error {
    public:
        explicit length_error(const char *what_arg) :
            logic_error(what_arg) {}
    };

    class out_of_range : public logic_error {
    public:
        explicit out_of_range(const char *what_arg) :
            logic_error(what_arg) {}
    };

    class range_error : public runtime_error {
    public:
        explicit range_error(const char *what_arg) :
            runtime_error(what_arg) {}
    };

    class overflow_error : public runtime_error {
    public:
        explicit overflow_error(const char *what_arg) :
            runtime_error(what_arg) {}
    };

    class underflow_error : public runtime_error {
    public:
        explicit underflow_error(const char *what_arg) :
            runtime_error(what_arg) {}
    };

} // namespace std

#endif
