Removed c, s and p types; added optional # specifier

This commit is contained in:
rbrugo
2020-03-18 00:09:16 +01:00
committed by Mateusz Pusz
parent 4174f184f3
commit 8b4f4daa55

View File

@@ -32,7 +32,7 @@ namespace units {
namespace detail { namespace detail {
// units-format-spec: // units-format-spec:
// fill-and-align[opt] sign[opt] width[opt] precision[opt] type[opt] units-specs[opt] // fill-and-align[opt] sign[opt] #[opt] width[opt] precision[opt] type[opt] units-specs[opt]
// units-specs: // units-specs:
// conversion-spec // conversion-spec
// units-specs conversion-spec // units-specs conversion-spec
@@ -94,11 +94,11 @@ namespace units {
return ptr; return ptr;
} }
template<typename Rep, typename OutputIt> template<typename Rep, typename OutputIt, typename CharT>
inline OutputIt format_units_quantity_value(OutputIt out, const Rep& val, fmt::sign_t sign, int precision, char type) inline OutputIt format_units_quantity_value(OutputIt out, const Rep& val, fmt::basic_format_specs<CharT> const & specs)
{ {
std::string sign_text; std::string sign_text;
switch(sign) { switch(specs.sign) {
case fmt::sign::none: case fmt::sign::none:
break; break;
case fmt::sign::plus: case fmt::sign::plus:
@@ -111,44 +111,45 @@ namespace units {
sign_text = " "; sign_text = " ";
break; break;
} }
if(precision >= 0) { if (specs.alt) {
if (type == '\0') type = 'f'; sign_text.push_back('#');
return format_to(out, "{:" + sign_text + ".{}" + type + "}", val, precision); }
if(specs.precision >= 0) {
auto type = specs.type == '\0' ? 'f' : specs.type;
return format_to(out, "{:" + sign_text + ".{}" + type + "}", val, specs.precision);
} }
if constexpr (treat_as_floating_point<Rep>) { if constexpr (treat_as_floating_point<Rep>) {
if (type == '\0') type = 'g'; auto type = specs.type == '\0' ? 'g' : specs.type;
return format_to(out, "{:" + sign_text + type + "}", val); return format_to(out, "{:" + sign_text + type + "}", val);
} }
else { else {
if (type == '\0') { if (specs.type == '\0') {
return format_to(out, "{:" + sign_text + "}", val); return format_to(out, "{:" + sign_text + "}", val);
} }
return format_to(out, "{:" + sign_text + type + "}", val); return format_to(out, "{:" + sign_text + specs.type + "}", val);
} }
} }
template<typename OutputIt, typename Dimension, typename Unit, typename Rep> template<typename OutputIt, typename Dimension, typename Unit, typename Rep, typename CharT>
struct units_formatter { struct units_formatter {
OutputIt out; OutputIt out;
Rep val; Rep val;
fmt::sign_t sign; fmt::basic_format_specs<CharT> const & specs;
int precision;
char type;
explicit units_formatter(OutputIt o, quantity<Dimension, Unit, Rep> q, fmt::sign_t s, int prec, char tp): explicit units_formatter(OutputIt o, quantity<Dimension, Unit, Rep> q, fmt::basic_format_specs<CharT> const & spcs):
out(o), val(q.count()), sign(s), precision(prec), type(tp) out(o), val(q.count()), specs(spcs)
{ {
} }
template<typename CharT> template<typename CharT2>
void on_text(const CharT* begin, const CharT* end) void on_text(const CharT2* begin, const CharT2* end)
{ {
std::copy(begin, end, out); std::copy(begin, end, out);
} }
void on_quantity_value() void on_quantity_value()
{ {
out = format_units_quantity_value(out, val, sign, precision, type); out = format_units_quantity_value(out, val, specs);
} }
void on_quantity_unit() void on_quantity_unit()
@@ -203,12 +204,13 @@ private:
constexpr void on_plus() { f.specs.sign = fmt::sign::plus; } constexpr void on_plus() { f.specs.sign = fmt::sign::plus; }
constexpr void on_minus() { f.specs.sign = fmt::sign::minus; } constexpr void on_minus() { f.specs.sign = fmt::sign::minus; }
constexpr void on_space() { f.specs.sign = fmt::sign::space; } constexpr void on_space() { f.specs.sign = fmt::sign::space; }
constexpr void on_hash() { f.specs.alt = true; }
constexpr void on_align(align_t align) { f.specs.align = align; } constexpr void on_align(align_t align) { f.specs.align = align; }
constexpr void on_width(int width) { f.specs.width = width; } constexpr void on_width(int width) { f.specs.width = width; }
constexpr void on_precision(int precision) { f.specs.precision = precision; } constexpr void on_precision(int precision) { f.specs.precision = precision; }
constexpr void on_type(char type) constexpr void on_type(char type)
{ {
constexpr auto good_types = std::string_view{"aAbBcdeEfFgGopsxX"}; constexpr auto good_types = std::string_view{"aAbBdeEfFgGoxX"};
if (good_types.find(type) != std::string_view::npos) { if (good_types.find(type) != std::string_view::npos) {
f.specs.type = type; f.specs.type = type;
} }
@@ -269,6 +271,11 @@ private:
if(begin == end) if(begin == end)
return {begin, begin}; return {begin, begin};
if (*begin == '#') {
handler.on_hash();
if (++begin == end) return {begin, begin};
}
// parse width // parse width
begin = fmt::internal::parse_width(begin, end, handler); begin = fmt::internal::parse_width(begin, end, handler);
if(begin == end) if(begin == end)
@@ -323,7 +330,7 @@ public:
// deal with quantity content // deal with quantity content
if(begin == end || *begin == '}') { if(begin == end || *begin == '}') {
// default format should print value followed by the unit separated with 1 space // default format should print value followed by the unit separated with 1 space
out = units::detail::format_units_quantity_value(out, q.count(), specs.sign, specs.precision, specs.type); out = units::detail::format_units_quantity_value(out, q.count(), specs);
constexpr auto symbol = units::detail::unit_text<Dimension, Unit>(); constexpr auto symbol = units::detail::unit_text<Dimension, Unit>();
if(symbol.size()) { if(symbol.size()) {
*out++ = CharT(' '); *out++ = CharT(' ');
@@ -332,7 +339,7 @@ public:
} }
else { else {
// user provided format // user provided format
units::detail::units_formatter f(out, q, specs.sign, specs.precision, specs.type); units::detail::units_formatter f(out, q, specs);
parse_units_format(begin, end, f); parse_units_format(begin, end, f);
} }