mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-11 09:50:06 +00:00
Add a simple format string compilation API
This commit is contained in:
parent
d259fcfb05
commit
2d71d7e030
@ -15,6 +15,17 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
// A compile-time string which is compiled into fast formatting code.
|
||||
class compiled_string {};
|
||||
|
||||
template <typename S>
|
||||
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
||||
|
||||
#define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
|
||||
|
||||
template <typename T, typename... Tail>
|
||||
const T& first(const T& value, const Tail&...) { return value; }
|
||||
|
||||
// Part of a compiled format string. It can be either literal text or a
|
||||
// replacement field.
|
||||
template <typename Char> struct format_part {
|
||||
@ -381,31 +392,6 @@ constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
|
||||
return {{&s[pos], size}};
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt, typename T,
|
||||
std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
||||
OutputIt format_default(OutputIt out, T value) {
|
||||
// TODO: reserve
|
||||
format_int fi(value);
|
||||
return std::copy(fi.data(), fi.data() + fi.size(), out);
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt format_default(OutputIt out, double value) {
|
||||
return detail::write(out, value);
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt format_default(OutputIt out, Char value) {
|
||||
*out++ = value;
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt format_default(OutputIt out, const Char* value) {
|
||||
auto length = std::char_traits<Char>::length(value);
|
||||
return copy_str<Char>(value, value + length, out);
|
||||
}
|
||||
|
||||
// A replacement field that refers to argument N.
|
||||
template <typename Char, typename T, int N> struct field {
|
||||
using char_type = Char;
|
||||
@ -414,7 +400,7 @@ template <typename Char, typename T, int N> struct field {
|
||||
OutputIt format(OutputIt out, const Args&... args) const {
|
||||
// This ensures that the argument type is convertile to `const T&`.
|
||||
const T& arg = get<N>(args...);
|
||||
return format_default<Char>(out, arg);
|
||||
return write<Char>(out, arg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -456,7 +442,8 @@ constexpr auto compile_format_string(S format_str);
|
||||
|
||||
template <typename Args, size_t POS, int ID, typename T, typename S>
|
||||
constexpr auto parse_tail(T head, S format_str) {
|
||||
if constexpr (POS != to_string_view(format_str).size()) {
|
||||
if constexpr (POS !=
|
||||
basic_string_view<typename S::char_type>(format_str).size()) {
|
||||
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
|
||||
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
|
||||
unknown_format>())
|
||||
@ -506,7 +493,8 @@ constexpr auto compile_format_string(S format_str) {
|
||||
#if FMT_USE_CONSTEXPR
|
||||
# ifdef __cpp_if_constexpr
|
||||
template <typename... Args, typename S,
|
||||
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compile_string<S>::value ||
|
||||
detail::is_compiled_string<S>::value)>
|
||||
constexpr auto compile(S format_str) {
|
||||
constexpr basic_string_view<typename S::char_type> str = format_str;
|
||||
if constexpr (str.size() == 0) {
|
||||
@ -529,7 +517,8 @@ template <typename CompiledFormat, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
cf.format(std::back_inserter(buffer), args...);
|
||||
detail::buffer<Char>& base = buffer;
|
||||
cf.format(std::back_inserter(base), args...);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@ -569,6 +558,16 @@ std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(S, Args&&... args) {
|
||||
constexpr basic_string_view<typename S::char_type> str = S();
|
||||
if (str.size() == 2 && str[0] == '{' && str[1] == '}')
|
||||
return fmt::to_string(detail::first(args...));
|
||||
constexpr auto compiled = compile<Args...>(S());
|
||||
return format(compiled, std::forward<Args...>(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format,
|
||||
CompiledFormat>::value)>
|
||||
|
@ -481,7 +481,7 @@ inline basic_string_view<Char> to_string_view(detail::std_string_view<Char> s) {
|
||||
}
|
||||
|
||||
// A base class for compile-time strings. It is defined in the fmt namespace to
|
||||
// make formatting functions visible via ADL, e.g. format(fmt("{}"), 42).
|
||||
// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42).
|
||||
struct compile_string {};
|
||||
|
||||
template <typename S>
|
||||
@ -1745,8 +1745,8 @@ template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
|
||||
FMT_INLINE void check_format_string(const S&) {
|
||||
#ifdef FMT_ENFORCE_COMPILE_STRING
|
||||
static_assert(is_compile_string<S>::value,
|
||||
"FMT_ENFORCE_COMPILE_STRING requires all format strings to "
|
||||
"utilize FMT_STRING() or fmt().");
|
||||
"FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
|
||||
"FMT_STRING.");
|
||||
#endif
|
||||
}
|
||||
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||
|
@ -700,6 +700,10 @@ void basic_memory_buffer<T, SIZE, Allocator>::grow(size_t size) {
|
||||
using memory_buffer = basic_memory_buffer<char>;
|
||||
using wmemory_buffer = basic_memory_buffer<wchar_t>;
|
||||
|
||||
template <typename T, size_t SIZE, typename Allocator>
|
||||
struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
|
||||
};
|
||||
|
||||
/** A formatting error such as invalid format string. */
|
||||
FMT_CLASS_API
|
||||
class FMT_API format_error : public std::runtime_error {
|
||||
@ -2746,12 +2750,12 @@ FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
|
||||
return {s.data(), s.size()};
|
||||
}
|
||||
|
||||
#define FMT_STRING_IMPL(s, ...) \
|
||||
#define FMT_STRING_IMPL(s, base) \
|
||||
[] { \
|
||||
/* Use a macro-like name to avoid shadowing warnings. */ \
|
||||
struct FMT_COMPILE_STRING : fmt::compile_string { \
|
||||
struct FMT_COMPILE_STRING : base { \
|
||||
using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
|
||||
FMT_MAYBE_UNUSED __VA_ARGS__ FMT_CONSTEXPR \
|
||||
FMT_MAYBE_UNUSED FMT_CONSTEXPR \
|
||||
operator fmt::basic_string_view<char_type>() const { \
|
||||
return fmt::detail::compile_string_to_view<char_type>(s); \
|
||||
} \
|
||||
@ -2769,7 +2773,7 @@ FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
|
||||
std::string s = format(FMT_STRING("{:d}"), "foo");
|
||||
\endrst
|
||||
*/
|
||||
#define FMT_STRING(s) FMT_STRING_IMPL(s, )
|
||||
#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string)
|
||||
|
||||
template <typename... Args, typename S,
|
||||
enable_if_t<(is_compile_string<S>::value), int>>
|
||||
@ -3344,9 +3348,14 @@ join(const Range& range, wstring_view sep) {
|
||||
std::string answer = fmt::to_string(42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename T> inline std::string to_string(const T& value) {
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
inline std::string to_string(const T& value) {
|
||||
return format("{}", value);
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline std::string to_string(T value) {
|
||||
return format_int(value).str();
|
||||
}
|
||||
|
||||
/**
|
||||
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
||||
|
Loading…
Reference in New Issue
Block a user