#ifndef TOML11_FORMAT #define TOML11_FORMAT #include "value.hpp" #include #include #include #include namespace toml { // synopsis // toml::format("key", value, toml::make_inline(80)) // toml::format("key", value, toml::forceinline) // std::cout << toml::make_inline(80) << value; // std::cout << toml::forceinline << value; template, typename alloc = std::allocator> std::basic_string format(const value& v); template, typename alloc = std::allocator> std::basic_string format(const value& v, std::size_t mk); template, typename alloc = std::allocator> std::basic_string format(const toml::key& k, const value& v); template, typename alloc = std::allocator> std::basic_string format(const toml::key& k, const value& v, std::size_t mk); template struct format_impl; template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { return val ? "true" : "false"; } }; template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { return std::to_string(val); } }; template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { std::basic_ostringstream oss; oss << std::showpoint << val; if(oss.str().back() == '.') oss << '0'; return oss.str(); } }; template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { //TODO escape some charactors! return val; } }; template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { std::basic_ostringstream oss; oss << val; return oss.str(); } }; // TODO max length! template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { std::basic_string retval; retval += '['; for(const auto&& item : val) { retval += format(val); retval += ", "; } retval += ']'; return ; } }; // TODO max length && inline! template<> struct format_impl { typedef detail::toml_default_type::type type; static std::basic_string invoke(const type& val) { std::basic_string retval; for(const auto&& item : val) { retval += val.first; retval += " = " retval += format(val.second); retval += '\n'; } return ; } }; template std::basic_string format(const value& v) { switch(v.type()) { case value_t::Boolean : return format_impl::invoke(v.template cast()); case value_t::Integer : return format_impl::invoke(v.template cast()); case value_t::Float : return format_impl::invoke(v.template cast()); case value_t::String : return format_impl::invoke(v.template cast()); case value_t::Datetime: return format_impl::invoke(v.template cast()); case value_t::Array : return format_impl::invoke(v.template cast()); case value_t::Table : return format_impl::invoke(v.template cast()); case value_t::Empty : return format_impl::invoke(v.template cast()); case value_t::Unknown : return format_impl::invoke(v.template cast()); default throw std::logic_error("toml::format: unknown enum value"); } } template std::basic_string format(std::basic_string&& key, const value& val) { std::basic_string retval( std::forward>(key)); retval += " = "; retval += format(val); return retval; } // ----------------------------- stream operators ----------------------------- namespace detail { template struct inline_limit { static_assert(std::is_same::value, "do not instantiate this"); static const int index; T limit; inline_limit() = default; ~inline_limit() = default; constexpr make_inline(T i): limit(i){} constexpr operator T() const {return limit;} static void callback(std::ios_base::event ev, std::ios_base& ios, int idx) { void*& info = ios.pword(idx); switch (ev) { case std::ios_base::erase_event: { delete static_cast(info); break; } case std::ios_base::copyfmt_event: { info = new std::size_t(*static_cast(info)); break; } case std::ios_base::imbue_event: { break; } } } }; template const int inline_limit::index = std::ios_base::xalloc(); } //detail template> std::basic_ostream& operator<<(std::basic_ostream& os, const detail::inline_limit& inl) { void*& info = os.pword(detail::inline_limit::index); if(!os.bad()) { if(info == nullptr) { os.register_callback(detail::inline_limit::callback, detail::inline_limit::index); info = new std::size_t(inl.limit); } else { *static_cast(info) = inl.limit; } } return os; } constexpr static detail::inline_limit forceinline = detail::inline_limit(std::numeric_limits::max()); inline detail::inline_limit make_inline(std::size_t sz) { return detail::inline_limit(sz); } template std::basic_ostream& operator<<(std::basic_ostream& os, const toml::value& v) { std::size_t* info = static_cast(os.pword(inline_limit::index)); return os << (info == nullptr ? toml::format(v) : toml::format(v, *info)); } } #endif // TOML11_FORMAT