include/str.hpp
c3e0ef8c
 #ifndef STR_HPP_
 #define STR_HPP_
 
 
 #include <cerrno>
 #include <exception>
 #include <functional>
 #include <initializer_list>
 #include <sstream>
 #include <stdexcept>
 #include <string>
 #include <system_error>
 
 
 #define STR(VALUE) \
     (((std::ostringstream &)(std::ostringstream{} << VALUE)).str())
 
 #define STR_FUNC(VALUE) \
     ([=]() { return STR(VALUE); })
 
 #define STR_JOIN(JOIN, ITERATOR, VALUE, ...) \
     ([&]() \
     { \
         auto const & str_join_  = JOIN; \
         auto         str_oss_   = std::ostringstream{}; \
         auto         str_first_ = true; \
         for (auto const & ITERATOR : __VA_ARGS__) \
         { \
             auto str_value_ = STR(VALUE); \
             if (str_value_.empty()) \
                 continue; \
             if (!str_first_) \
                 str_oss_ << str_join_; \
             str_first_ = false; \
             str_oss_ << str_value_; \
         } \
         return str_oss_.str(); \
     }())
 
 #define STR_JOIN_INIT(JOIN, ITERATOR, VALUE, TYPE, ...) \
     STR_JOIN(JOIN, ITERATOR, VALUE, std::initializer_list<TYPE>__VA_ARGS__)
 
 #define STR_JOIN_INITSTR(JOIN, ITERATOR, VALUE, ...) \
     STR_JOIN_INIT(JOIN, ITERATOR, VALUE, std::string, __VA_ARGS__)
 
 
 #define STR_CASE(CASE) \
     case (CASE): return (#CASE);
 
 #define STR_COND(VALUE, CASE) \
     ((VALUE) == (CASE)) ? (#CASE) :
 
 #define STR_INIT(CASE) \
     {(CASE), (#CASE)},
 
 #define STR_ARGS(ARG) \
     ARG, #ARG
 
 #define STR_ARGS_PREFIX(PREFIX, ARG) \
     PREFIX##ARG, #ARG
 
 
 #define STR_HERE(VALUE) \
     STR(__FILE__ << ":" << __LINE__ << ":" << __func__ << ": " << VALUE)
 
 
 #ifndef STR_EXCEPTION
     #define STR_EXCEPTION std::runtime_error
 #endif
 
 #define STR_THROW(VALUE) \
     (throw STR_EXCEPTION{STR(VALUE)})
 
 #define STR_THROW_ERRNO() \
     STR_THROW(std::generic_category().message(errno) << ".")
 
 #define STR_RETHROW(VALUE) \
     try \
     { \
         throw; \
     } \
     catch (std::exception const & str_exception_) \
     { \
         STR_THROW(VALUE << str_exception_.what()); \
     }
 
 #define STR_NESTED_THROW(VALUE) \
     (std::throw_with_nested(STR_EXCEPTION{STR(VALUE)}))
 
 #define STR_NESTED_THROW_ERRNO() \
     STR_NESTED_THROW(std::generic_category().message(errno) << ".")
 
 #define STR_NESTED_WHAT(JOIN, EXCEPTION) \
     ([&]() \
     { \
         auto const & str_join_   = JOIN; \
         auto         str_oss_    = std::ostringstream{}; \
         auto         str_first_  = true; \
         auto str_what_ = std::function<void(std::exception const &)>{}; \
         str_what_ = [&](std::exception const & str_exception_) \
         { \
             if (!str_first_) \
                 str_oss_ << str_join_; \
             str_first_ = false; \
             str_oss_ << str_exception_.what(); \
             try \
             { \
                 std::rethrow_if_nested(str_exception_); \
             } \
             catch (std::exception const & str_exception_nested_) \
             { \
                 str_what_(str_exception_nested_); \
             } \
         }; \
         str_what_(EXCEPTION); \
         return str_oss_.str(); \
     }())
 
 
 #endif // STR_HPP_