Skip to content

Commit 606fd4e

Browse files
committed
Add format specialization for all types
1 parent 1296489 commit 606fd4e

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

include/boost/decimal/format.hpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Copyright 2023 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_DECIMAL_FORMAT_HPP
6+
#define BOOST_DECIMAL_FORMAT_HPP
7+
8+
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) && __has_include(<format>) && !defined(BOOST_DECIMAL_DISABLE_CLIB)
9+
10+
#include <boost/decimal/decimal32.hpp>
11+
#include <boost/decimal/decimal64.hpp>
12+
#include <boost/decimal/decimal128.hpp>
13+
#include <format>
14+
#include <iostream>
15+
#include <iomanip>
16+
#include <string>
17+
#include <tuple>
18+
19+
// See for general impl
20+
// https://en.cppreference.com/w/cpp/utility/format/formatter
21+
22+
namespace boost::decimal::detail {
23+
24+
template <typename ParseContext>
25+
constexpr auto parse_impl(ParseContext& ctx)
26+
{
27+
auto it {ctx.begin()};
28+
int precision = 5;
29+
30+
if (it == ctx.end())
31+
{
32+
return std::make_tuple(precision, it);
33+
}
34+
35+
if (*it == '.')
36+
{
37+
++it;
38+
precision = 0;
39+
while (*it >= '0' && *it <= '9')
40+
{
41+
precision = precision * 10 + *it;
42+
++it;
43+
}
44+
45+
if (*it != 'f')
46+
{
47+
throw std::format_error("Invalid format");
48+
}
49+
++it;
50+
}
51+
52+
if (*it != '}')
53+
{
54+
throw std::format_error("Invalid format");
55+
}
56+
57+
return std::make_tuple(precision, it);
58+
};
59+
};
60+
61+
template <>
62+
struct std::formatter<boost::decimal::decimal32>
63+
{
64+
int precision {};
65+
66+
template <typename ParseContext>
67+
constexpr auto parse(ParseContext& ctx)
68+
{
69+
auto res {boost::decimal::detail::parse_impl(ctx)};
70+
precision = std::get<0>(res);
71+
return std::get<1>(res);
72+
}
73+
74+
template <typename FormatContext>
75+
auto format(const boost::decimal::decimal32& v, FormatContext& ctx)
76+
{
77+
std::ostringstream out;
78+
out << std::setprecision(precision) << v;
79+
80+
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
81+
}
82+
};
83+
84+
template <>
85+
struct std::formatter<boost::decimal::decimal64>
86+
{
87+
int precision;
88+
89+
template <typename ParseContext>
90+
constexpr auto parse(ParseContext& ctx)
91+
{
92+
auto res {boost::decimal::detail::parse_impl(ctx)};
93+
precision = std::get<0>(res);
94+
return std::get<1>(res);
95+
}
96+
97+
template <typename FormatContext>
98+
auto format(const boost::decimal::decimal32& v, FormatContext& ctx)
99+
{
100+
std::ostringstream out;
101+
out << std::setprecision(precision) << v;
102+
103+
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
104+
}
105+
};
106+
107+
template <>
108+
struct std::formatter<boost::decimal::decimal128>
109+
{
110+
int precision;
111+
112+
template <typename ParseContext>
113+
constexpr auto parse(ParseContext& ctx)
114+
{
115+
auto res {boost::decimal::detail::parse_impl(ctx)};
116+
precision = std::get<0>(res);
117+
return std::get<1>(res);
118+
}
119+
120+
template <typename FormatContext>
121+
auto format(const boost::decimal::decimal32& v, FormatContext& ctx)
122+
{
123+
std::ostringstream out;
124+
out << std::setprecision(precision) << v;
125+
126+
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
127+
}
128+
};
129+
130+
131+
#endif
132+
133+
#endif //BOOST_DECIMAL_FORMAT_HPP

0 commit comments

Comments
 (0)