339 lines
13 KiB
C++
339 lines
13 KiB
C++
/**
|
|
This file is a part of rexy's general purpose library
|
|
Copyright (C) 2022 rexy712
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef REXY_FORMAT_TPP
|
|
#define REXY_FORMAT_TPP
|
|
|
|
#include "detail/format/format_args.tpp"
|
|
#include "detail/format/formatter.tpp"
|
|
#include "detail/format/storage.tpp"
|
|
#include "detail/format/format_string.tpp"
|
|
#include "detail/format/arg_store.tpp"
|
|
#include "detail/format/output_buffer.tpp"
|
|
#include "detail/format/basic_types.tpp"
|
|
#include "detail/format/specs_handler.tpp"
|
|
#include "detail/format/parse.tpp"
|
|
#include "detail/format/context_handler.tpp"
|
|
#include "detail/format/named_args.tpp"
|
|
#include "detail/format/parse_context.tpp"
|
|
#include "detail/format/format_context.tpp"
|
|
|
|
#include <iterator> //back_insert_iterator
|
|
#include <utility> //move, forward
|
|
#include <type_traits> //is_same
|
|
#include <locale> //locale
|
|
#include <cstddef> //size_t
|
|
|
|
namespace rexy{
|
|
|
|
namespace fmt::detail{
|
|
|
|
template<class Char, class OutIt>
|
|
OutIt vformat_to(OutIt out, basic_string_view<std::type_identity_t<Char>> fmt, impl_format_args<std::type_identity_t<Char>> args){
|
|
using char_type = Char;
|
|
using format_handler_t = fmt::detail::format_handler<char_type>;
|
|
|
|
if constexpr(std::is_same_v<OutIt,fmt::detail::output_iterator_t<char_type>>){
|
|
|
|
fmt::detail::format_handler<char_type> handler{out, fmt, args};
|
|
fmt::detail::parse::perform_parse(handler, fmt);
|
|
|
|
return std::move(out);
|
|
}else{
|
|
|
|
fmt::detail::basic_format_output_buffer<char_type,OutIt> outbuf{out};
|
|
fmt::detail::format_handler<char_type> handler{fmt::detail::output_iterator_t<char_type>{outbuf}, fmt, args};
|
|
|
|
fmt::detail::parse::perform_parse(handler, fmt);
|
|
|
|
return std::move(outbuf.out());
|
|
}
|
|
|
|
}
|
|
template<class Char, class OutIt>
|
|
OutIt vformat_to(OutIt out, const std::locale& loc, basic_string_view<std::type_identity_t<Char>> fmt, impl_format_args<std::type_identity_t<Char>> args){
|
|
using char_type = Char;
|
|
using format_handler_t = fmt::detail::format_handler<char_type>;
|
|
|
|
if constexpr(std::is_same_v<OutIt,fmt::detail::output_iterator_t<char_type>>){
|
|
|
|
fmt::detail::format_handler<char_type> handler{out, fmt, args, loc};
|
|
fmt::detail::parse::perform_parse(handler, fmt);
|
|
|
|
return std::move(out);
|
|
}else{
|
|
|
|
fmt::detail::basic_format_output_buffer<char_type,OutIt> outbuf{out};
|
|
fmt::detail::format_handler<char_type> handler{fmt::detail::output_iterator_t<char_type>{outbuf}, fmt, args, loc};
|
|
|
|
fmt::detail::parse::perform_parse(handler, fmt);
|
|
|
|
return std::move(outbuf.out());
|
|
}
|
|
}
|
|
|
|
|
|
template<class Char, class... Args>
|
|
basic_format_arg_store<fmt_context_t<Char>,Args...> make_format_args(Args&&... args){
|
|
return basic_format_arg_store<fmt_context_t<Char>,Args...>{std::forward<Args>(args)...};
|
|
}
|
|
}
|
|
|
|
template<class Context, class... Args>
|
|
fmt::detail::basic_format_arg_store<Context,Args...> make_format_args(Args&&... args){
|
|
return fmt::detail::basic_format_arg_store<Context,Args...>{std::forward<Args>(args)...};
|
|
}
|
|
template<class Context, class... Args>
|
|
fmt::detail::basic_format_arg_store<Context,Args...> make_wformat_args(Args&&... args){
|
|
return fmt::detail::basic_format_arg_store<Context,Args...>{std::forward<Args>(args)...};
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////char overloads///////////////////////////////////////////////
|
|
template<class OutIt>
|
|
OutIt vformat_to(OutIt out, string_view fmt, format_args args){
|
|
return fmt::detail::vformat_to<char>(std::move(out), fmt, std::move(args));
|
|
}
|
|
template<class OutIt>
|
|
OutIt vformat_to(OutIt out, const std::locale& loc, string_view fmt, format_args args){
|
|
return fmt::detail::vformat_to<char>(std::move(out), loc, fmt, std::move(args));
|
|
}
|
|
|
|
string vformat(string_view fmt, format_args args){
|
|
using outit_t = std::back_insert_iterator<string>;
|
|
string output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), fmt, std::move(args));
|
|
return output;
|
|
}
|
|
|
|
string vformat(const std::locale& loc, string_view fmt, format_args args){
|
|
using outit_t = std::back_insert_iterator<string>;
|
|
string output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), loc, fmt, std::move(args));
|
|
return output;
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
OutIt format_to(OutIt out, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
return vformat_to(std::move(out), fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
OutIt format_to(OutIt out, const std::locale& loc, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
return vformat_to(std::move(out), loc, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
format_to_n_result<OutIt> format_to_n(OutIt out, std::size_t max, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_n_buffer<char,OutIt> outbuf{std::move(out), max};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{outbuf}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return {outbuf.out(), outbuf.count()};
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
format_to_n_result<OutIt> format_to_n(OutIt out, const std::locale& loc, std::size_t max, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_n_buffer<char,OutIt> outbuf{std::move(out), max};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{outbuf}, loc, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return {outbuf.out(), outbuf.count()};
|
|
}
|
|
|
|
template<class... Args>
|
|
string format(fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
using outit_t = std::back_insert_iterator<string>;
|
|
string output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return output;
|
|
}
|
|
|
|
template<class... Args>
|
|
string format(const std::locale& loc, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
using outit_t = std::back_insert_iterator<string>;
|
|
string output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), loc, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return output;
|
|
}
|
|
|
|
template<class... Args>
|
|
std::size_t formatted_size(fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_size_buffer<char> counter;
|
|
vformat_to(fmt::detail::output_iterator_t<char>{counter}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return counter.count();
|
|
}
|
|
template<class... Args>
|
|
std::size_t formatted_size(const std::locale& loc, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_size_buffer<char> counter;
|
|
vformat_to(fmt::detail::output_iterator_t<char>{counter}, loc, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return counter.count();
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////wchar_t overloads///////////////////////////////////////////////
|
|
template<class OutIt>
|
|
OutIt vformat_to(OutIt out, wstring_view fmt, wformat_args args){
|
|
return fmt::detail::vformat_to<wchar_t>(std::move(out), fmt, std::move(args));
|
|
}
|
|
template<class OutIt>
|
|
OutIt vformat_to(OutIt out, const std::locale& loc, wstring_view fmt, wformat_args args){
|
|
return fmt::detail::vformat_to<wchar_t>(std::move(out), loc, fmt, std::move(args));
|
|
}
|
|
|
|
wstring vformat(wstring_view fmt, wformat_args args){
|
|
using outit_t = std::back_insert_iterator<wstring>;
|
|
wstring output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), fmt, std::move(args));
|
|
return output;
|
|
}
|
|
wstring vformat(const std::locale& loc, wstring_view fmt, wformat_args args){
|
|
using outit_t = std::back_insert_iterator<wstring>;
|
|
wstring output;
|
|
outit_t out{output};
|
|
vformat_to(std::move(out), loc, fmt, std::move(args));
|
|
return output;
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
OutIt format_to(OutIt out, fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
return vformat_to(std::move(out), fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
}
|
|
template<class OutIt, class... Args>
|
|
OutIt format_to(OutIt out, const std::locale& loc, fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
return vformat_to(std::move(out), loc, fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class OutIt, class... Args>
|
|
format_to_n_result<OutIt> format_to_n(OutIt out, std::size_t max, fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_n_buffer<wchar_t,OutIt> outbuf{std::move(out), max};
|
|
vformat_to(fmt::detail::output_iterator_t<wchar_t>{outbuf}, fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
return {outbuf.out(), outbuf.count()};
|
|
}
|
|
template<class OutIt, class... Args>
|
|
format_to_n_result<OutIt> format_to_n(OutIt out, const std::locale& loc, std::size_t max, fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_n_buffer<wchar_t,OutIt> outbuf{std::move(out), max};
|
|
vformat_to(fmt::detail::output_iterator_t<wchar_t>{outbuf}, loc, fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
return {outbuf.out(), outbuf.count()};
|
|
}
|
|
|
|
template<class... Args>
|
|
wstring format(fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
using outit_t = std::back_insert_iterator<wstring>;
|
|
wstring output;
|
|
outit_t out{output};
|
|
vformat_to(out, fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
return output;
|
|
}
|
|
template<class... Args>
|
|
wstring format(const std::locale& loc, fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
using outit_t = std::back_insert_iterator<wstring>;
|
|
wstring output;
|
|
outit_t out{output};
|
|
vformat_to(out, fmt.str, make_wformat_args(std::forward<Args>(args)...));
|
|
return output;
|
|
}
|
|
|
|
template<class... Args>
|
|
std::size_t formatted_size(fmt::detail::wformat_string<Args...> fmt, Args&&... args){
|
|
|
|
}
|
|
template<class... Args>
|
|
std::size_t formatted_size(const std::locale& loc, fmt::detail::wformat_string<Args...> fmt, Args&&... args);
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////print char overloads///////////////////////////////////////////////
|
|
template<class... Args>
|
|
std::size_t print(fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return out.count();
|
|
}
|
|
template<class... Args>
|
|
std::size_t print(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
return out.count();
|
|
}
|
|
template<class... Args>
|
|
std::size_t println(fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
out.push_back('\n');
|
|
return out.count();
|
|
}
|
|
template<class... Args>
|
|
std::size_t println(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
|
out.push_back('\n');
|
|
return out.count();
|
|
}
|
|
std::size_t vprint_unicode(string_view fmt, format_args args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt, args);
|
|
return out.count();
|
|
}
|
|
std::size_t vprint_unicode(FILE* stream, string_view fmt, format_args args){
|
|
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
|
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt, args);
|
|
return out.count();
|
|
}
|
|
|
|
|
|
|
|
//creates a runtime argument from a c string
|
|
template<class T, class Char>
|
|
constexpr auto arg(const Char* name, T&& t){
|
|
return fmt::detail::runtime_arg<T,Char>{std::forward<T>(t), name};
|
|
}
|
|
|
|
//creates a runtime argument from a string view
|
|
template<class T, class Char>
|
|
constexpr auto arg(rexy::basic_string_view<Char> name, T&& t){
|
|
return fmt::detail::runtime_arg{std::forward<T>(t), name};
|
|
}
|
|
|
|
//create a compile time argument from a string literal
|
|
template<rexy::cx::string Name, class T>
|
|
constexpr auto arg(T&& t){
|
|
return fmt::detail::static_arg<T,Name>{t};
|
|
}
|
|
|
|
inline namespace fmt_literals{
|
|
//create a compile time argument from a string literal
|
|
template<rexy::cx::string Name>
|
|
constexpr auto operator""_a(void){
|
|
return fmt::detail::arg_literal_result<Name>{};
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#undef REXY_REAL_STRINGIFY
|
|
#undef REXY_STRINGIFY
|
|
#undef REXY_THROW_FORMAT_ERROR
|
|
|
|
#endif
|
|
|