mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
Merge pull request #555 from mpusz/new_format
docs: new formatting syntax ideas
This commit is contained in:
@ -121,8 +121,8 @@ int main()
|
||||
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
|
||||
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
|
||||
std::println("{:%N in %U of %D}", v4); // 70 in mi/h of LT⁻¹
|
||||
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
|
||||
std::println("{:{%N:.2f}%?{%U:dn}}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{::N[.2f]}", v5); // 30.56 m/s
|
||||
std::println("{::N[.2f]U[dn]}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{:%N}", v7); // 31
|
||||
}
|
||||
```
|
||||
|
@ -242,9 +242,9 @@ quantity q = (90. * km / h).in(mph);
|
||||
std::cout << "Number: " << q.numerical_value_in(mph) << "\n";
|
||||
std::cout << "Unit: " << q.unit << "\n";
|
||||
std::cout << "Dimension: " << q.dimension << "\n";
|
||||
std::println("{:{%N:.2f}%?%U}", q);
|
||||
std::println("{::N[.2f]}", q);
|
||||
std::println("{:.4f} in {} of {}", q.numerical_value_in(mph), q.unit, q.dimension);
|
||||
std::println("{:{%N:.4f} in %U of %D}", q);
|
||||
std::println("{:%N in %U of %D:N[.4f]}", q);
|
||||
```
|
||||
|
||||
```text
|
||||
|
@ -100,8 +100,8 @@ performed without sacrificing accuracy. Please see the below example for a quick
|
||||
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
|
||||
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
|
||||
std::println("{:%N in %U of %D}", v4); // 70 in mi/h of LT⁻¹
|
||||
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
|
||||
std::println("{:{%N:.2f}%?{%U:dn}}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{::N[.2f]}", v5); // 30.56 m/s
|
||||
std::println("{::N[.2f]U[dn]}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{:%N}", v7); // 31
|
||||
}
|
||||
```
|
||||
@ -144,8 +144,8 @@ performed without sacrificing accuracy. Please see the below example for a quick
|
||||
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
|
||||
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
|
||||
std::println("{:%N in %U of %D}", v4); // 70 in mi/h of LT⁻¹
|
||||
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
|
||||
std::println("{:{%N:.2f}%?{%U:dn}}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{::N[.2f]}", v5); // 30.56 m/s
|
||||
std::println("{::N[.2f]U[dn]}", v6); // 31.29 m⋅s⁻¹
|
||||
std::println("{:%N}", v7); // 31
|
||||
}
|
||||
```
|
||||
|
@ -38,7 +38,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
|
||||
int main()
|
||||
{
|
||||
constexpr quantity dist = 364.4 * smoot;
|
||||
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
|
||||
std::println("Harvard Bridge length = {::N[.5]} ({::N[.5]}, {::N[.5]}) ± 1 εar",
|
||||
dist, dist.in(usc::foot), dist.in(si::metre));
|
||||
}
|
||||
```
|
||||
@ -58,7 +58,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
|
||||
int main()
|
||||
{
|
||||
constexpr quantity dist = 364.4 * smoot;
|
||||
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
|
||||
std::println("Harvard Bridge length = {::N[.5]} ({::N[.5]}, {::N[.5]}) ± 1 εar",
|
||||
dist, dist.in(usc::foot), dist.in(si::metre));
|
||||
}
|
||||
```
|
||||
|
@ -61,7 +61,7 @@ constexpr auto speed_of_light_in_vacuum = 1 * si::si2019::speed_of_light_in_vacu
|
||||
|
||||
QuantityOf<isq::permittivity_of_vacuum> auto q = 1 / (permeability_of_vacuum * pow<2>(speed_of_light_in_vacuum));
|
||||
|
||||
std::println("permittivity of vacuum = {} = {:{%N:.3e} %U}", q, q.in(F / m));
|
||||
std::println("permittivity of vacuum = {} = {::N[.3e]}", q, q.in(F / m));
|
||||
```
|
||||
|
||||
The above first prints the following:
|
||||
|
@ -75,7 +75,7 @@ Here is a simple example showing how to deal with such quantities:
|
||||
const quantity duration = 2 * h;
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
|
||||
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
|
||||
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
|
||||
distance, duration, speed, speed.in(km / h));
|
||||
}
|
||||
```
|
||||
@ -103,7 +103,7 @@ Here is a simple example showing how to deal with such quantities:
|
||||
const quantity duration = 2 * h;
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
|
||||
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
|
||||
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
|
||||
distance, duration, speed, speed.in(km / h));
|
||||
}
|
||||
```
|
||||
@ -194,7 +194,7 @@ The previous example can be re-typed using typed quantities in the following way
|
||||
const quantity duration = isq::time(2 * h);
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
|
||||
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
|
||||
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
|
||||
distance, duration, speed, speed.in(km / h));
|
||||
}
|
||||
```
|
||||
@ -223,7 +223,7 @@ The previous example can be re-typed using typed quantities in the following way
|
||||
const quantity duration = isq::time(2 * h);
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
|
||||
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
|
||||
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
|
||||
distance, duration, speed, speed.in(km / h));
|
||||
}
|
||||
```
|
||||
|
@ -529,20 +529,19 @@ std::println("{:d}", kg * m2 / s2); // kg⋅m²/s²
|
||||
### Quantity formatting
|
||||
|
||||
```bnf
|
||||
quantity-format-spec ::= [fill-and-align] [width] [quantity-specs]
|
||||
quantity-format-spec ::= [fill-and-align] [width] [quantity-specs] [defaults-specs]
|
||||
quantity-specs ::= conversion-spec
|
||||
quantity-specs conversion-spec
|
||||
quantity-specs literal-char
|
||||
literal-char ::= <any character other than '{', '}', or '%'>
|
||||
conversion-spec ::= placement-spec
|
||||
subentity-replacement-field
|
||||
placement-spec ::= '%' placement-type
|
||||
placement-type ::= 'N' | 'U' | 'D' | '?' | '%'
|
||||
subentity-replacement-field ::= '{' '%' subentity-id [format-specifier] '}'
|
||||
subentity-id ::= literal-char
|
||||
subentity-id literal-char
|
||||
format-specifier ::= ':' format-spec
|
||||
format-spec ::= <as specified by the formatter for the argument type; cannot start with '}'>
|
||||
conversion-spec ::= '%' placement-type
|
||||
placement-type ::= subentity-id | '?' | '%'
|
||||
defaults-specs ::= ':' default-spec-list
|
||||
default-spec-list ::= default-spec
|
||||
default-spec-list default-spec
|
||||
default-spec ::= subentity-id '[' format-spec ']'
|
||||
subentity-id ::= 'N' | 'U' | 'D'
|
||||
format-spec ::= <as specified by the formatter for the argument type>
|
||||
```
|
||||
|
||||
In the above grammar:
|
||||
@ -556,12 +555,9 @@ In the above grammar:
|
||||
- '?' inserts an optional separator between the number and a unit based on the value of
|
||||
`space_before_unit_symbol` for this unit,
|
||||
- '%' just inserts '%' character.
|
||||
- `subentity-replacement-field` token allows the composition of formatters. The following identifiers
|
||||
are recognized by the quantity formatter:
|
||||
- 'N' passes `format-spec` to the `formatter` specialization for the quantity representation
|
||||
type,
|
||||
- 'U' passes `format-spec` to the `formatter` specialization for the unit type,
|
||||
- 'D' passes `format-spec` to the `formatter` specialization for the dimension type.
|
||||
- `defaults-specs` token allows overwriting defaults for the underlying formatters with the custom
|
||||
format string. Each override starts with a subentity identifier ('N', 'U', or 'D') followed by
|
||||
the format string enclosed in square brackets.
|
||||
|
||||
#### Default formatting
|
||||
|
||||
@ -573,7 +569,6 @@ This is why the following code lines produce the same output:
|
||||
std::cout << "Distance: " << 123 * km << "\n";
|
||||
std::cout << std::format("Distance: {}\n", 123 * km);
|
||||
std::cout << std::format("Distance: {:%N%?%U}\n", 123 * km);
|
||||
std::cout << std::format("Distance: {:{%N}%?{%U}}\n", 123 * km);
|
||||
```
|
||||
|
||||
!!! note
|
||||
@ -610,7 +605,7 @@ Thanks to the grammar provided above, the user can easily decide to either:
|
||||
- provide custom formatting for components:
|
||||
|
||||
```cpp
|
||||
std::println("Speed: {:{%N:.2f} {%U:n}}", 100. * km / (3 * h));
|
||||
std::println("Speed: {::N[.2f]U[n]}", 100. * km / (3 * h));
|
||||
```
|
||||
|
||||
```text
|
||||
@ -630,25 +625,11 @@ Thanks to the grammar provided above, the user can easily decide to either:
|
||||
- dimension: LT⁻¹
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
The above grammar allows repeating the same field many times, possibly with a different
|
||||
format spec. For example:
|
||||
|
||||
```cpp
|
||||
std::println("Speed: {:%N {%N:.4f} {%N:.2f} {%U:n}}", 100. * km / (3 * h));
|
||||
```
|
||||
|
||||
```text
|
||||
Speed: 33.333333333333336 33.3333 33.33 km h⁻¹
|
||||
```
|
||||
|
||||
|
||||
#### Formatting of the quantity numerical value
|
||||
|
||||
The representation type used as a numerical value of a quantity must provide its own formatter
|
||||
specialization. It will be called by the quantity formatter with the format-spec provided
|
||||
by the user in the `%N` replacement field.
|
||||
by the user in the `N` defaults specification.
|
||||
|
||||
In case we use C++ fundamental arithmetic types with our quantities the standard formatter
|
||||
specified in [format.string.std](https://wg21.link/format.string.std) will be used. The rest
|
||||
@ -657,8 +638,8 @@ of this chapter assumes that it is the case and provides some usage examples.
|
||||
`sign` token allows us to specify how the value's sign is being printed:
|
||||
|
||||
```cpp
|
||||
std::println("{0:%N %U},{0:{%N:+} %U},{0:{%N:-} %U},{0:{%N: } %U}", 1 * m); // 1 m,+1 m,1 m, 1 m
|
||||
std::println("{0:%N %U},{0:{%N:+} %U},{0:{%N:-} %U},{0:{%N: } %U}", -1 * m); // -1 m,-1 m,-1 m,-1 m
|
||||
std::println("{0},{0::N[+]},{0::N[-]},{0::N[ ]}", 1 * m); // 1 m,+1 m,1 m, 1 m
|
||||
std::println("{0},{0::N[+]},{0::N[-]},{0::N[ ]}", -1 * m); // -1 m,-1 m,-1 m,-1 m
|
||||
```
|
||||
|
||||
where:
|
||||
@ -672,54 +653,54 @@ where:
|
||||
`precision` token is allowed only for floating-point representation types:
|
||||
|
||||
```cpp
|
||||
std::println("{:{%N:.0} %U}", 1.2345 * m); // 1 m
|
||||
std::println("{:{%N:.1} %U}", 1.2345 * m); // 1 m
|
||||
std::println("{:{%N:.2} %U}", 1.2345 * m); // 1.2 m
|
||||
std::println("{:{%N:.3} %U}", 1.2345 * m); // 1.23 m
|
||||
std::println("{:{%N:.0f} %U}", 1.2345 * m); // 1 m
|
||||
std::println("{:{%N:.1f} %U}", 1.2345 * m); // 1.2 m
|
||||
std::println("{:{%N:.2f} %U}", 1.2345 * m); // 1.23 m
|
||||
std::println("{::N[.0]}", 1.2345 * m); // 1 m
|
||||
std::println("{::N[.1]}", 1.2345 * m); // 1 m
|
||||
std::println("{::N[.2]}", 1.2345 * m); // 1.2 m
|
||||
std::println("{::N[.3]}", 1.2345 * m); // 1.23 m
|
||||
std::println("{::N[.0f]}", 1.2345 * m); // 1 m
|
||||
std::println("{::N[.1f]}", 1.2345 * m); // 1.2 m
|
||||
std::println("{::N[.2f]}", 1.2345 * m); // 1.23 m
|
||||
```
|
||||
|
||||
`type` specifies how a value of the representation type is being printed.
|
||||
For integral types:
|
||||
|
||||
```cpp
|
||||
std::println("{:{%N:b} %U}", 42 * m); // 101010 m
|
||||
std::println("{:{%N:B} %U}", 42 * m); // 101010 m
|
||||
std::println("{:{%N:d} %U}", 42 * m); // 42 m
|
||||
std::println("{:{%N:o} %U}", 42 * m); // 52 m
|
||||
std::println("{:{%N:x} %U}", 42 * m); // 2a m
|
||||
std::println("{:{%N:X} %U}", 42 * m); // 2A m
|
||||
std::println("{::N[b]}", 42 * m); // 101010 m
|
||||
std::println("{::N[B]}", 42 * m); // 101010 m
|
||||
std::println("{::N[d]}", 42 * m); // 42 m
|
||||
std::println("{::N[o]}", 42 * m); // 52 m
|
||||
std::println("{::N[x]}", 42 * m); // 2a m
|
||||
std::println("{::N[X]}", 42 * m); // 2A m
|
||||
```
|
||||
|
||||
The above can be printed in an alternate version thanks to the `#` token:
|
||||
|
||||
```cpp
|
||||
std::println("{:{%N:#b} %U}", 42 * m); // 0b101010 m
|
||||
std::println("{:{%N:#B} %U}", 42 * m); // 0B101010 m
|
||||
std::println("{:{%N:#o} %U}", 42 * m); // 052 m
|
||||
std::println("{:{%N:#x} %U}", 42 * m); // 0x2a m
|
||||
std::println("{:{%N:#X} %U}", 42 * m); // 0X2A m
|
||||
std::println("{::N[#b]}", 42 * m); // 0b101010 m
|
||||
std::println("{::N[#B]}", 42 * m); // 0B101010 m
|
||||
std::println("{::N[#o]}", 42 * m); // 052 m
|
||||
std::println("{::N[#x]}", 42 * m); // 0x2a m
|
||||
std::println("{::N[#X]}", 42 * m); // 0X2A m
|
||||
```
|
||||
|
||||
For floating-point values, the `type` token works as follows:
|
||||
|
||||
```cpp
|
||||
std::println("{:{%N:a} %U}", 1.2345678 * m); // 1.3c0ca2a5b1d5dp+0 m
|
||||
std::println("{:{%N:.3a} %U}", 1.2345678 * m); // 1.3c1p+0 m
|
||||
std::println("{:{%N:A} %U}", 1.2345678 * m); // 1.3C0CA2A5B1D5DP+0 m
|
||||
std::println("{:{%N:.3A} %U}", 1.2345678 * m); // 1.3C1P+0 m
|
||||
std::println("{:{%N:e} %U}", 1.2345678 * m); // 1.234568e+00 m
|
||||
std::println("{:{%N:.3e} %U}", 1.2345678 * m); // 1.235e+00 m
|
||||
std::println("{:{%N:E} %U}", 1.2345678 * m); // 1.234568E+00 m
|
||||
std::println("{:{%N:.3E} %U}", 1.2345678 * m); // 1.235E+00 m
|
||||
std::println("{:{%N:g} %U}", 1.2345678 * m); // 1.23457 m
|
||||
std::println("{:{%N:g} %U}", 1.2345678e8 * m); // 1.23457e+08 m
|
||||
std::println("{:{%N:.3g} %U}", 1.2345678 * m); // 1.23 m
|
||||
std::println("{:{%N:.3g} %U}", 1.2345678e8 * m); // 1.23e+08 m
|
||||
std::println("{:{%N:G} %U}", 1.2345678 * m); // 1.23457 m
|
||||
std::println("{:{%N:G} %U}", 1.2345678e8 * m); // 1.23457E+08 m
|
||||
std::println("{:{%N:.3G} %U}", 1.2345678 * m); // 1.23 m
|
||||
std::println("{:{%N:.3G} %U}", 1.2345678e8 * m); // 1.23E+08 m
|
||||
std::println("{::N[a]}", 1.2345678 * m); // 1.3c0ca2a5b1d5dp+0 m
|
||||
std::println("{::N[.3a]}", 1.2345678 * m); // 1.3c1p+0 m
|
||||
std::println("{::N[A]}", 1.2345678 * m); // 1.3C0CA2A5B1D5DP+0 m
|
||||
std::println("{::N[.3A]}", 1.2345678 * m); // 1.3C1P+0 m
|
||||
std::println("{::N[e]}", 1.2345678 * m); // 1.234568e+00 m
|
||||
std::println("{::N[.3e]}", 1.2345678 * m); // 1.235e+00 m
|
||||
std::println("{::N[E]}", 1.2345678 * m); // 1.234568E+00 m
|
||||
std::println("{::N[.3E]}", 1.2345678 * m); // 1.235E+00 m
|
||||
std::println("{::N[g]}", 1.2345678 * m); // 1.23457 m
|
||||
std::println("{::N[g]}", 1.2345678e8 * m); // 1.23457e+08 m
|
||||
std::println("{::N[.3g]}", 1.2345678 * m); // 1.23 m
|
||||
std::println("{::N[.3g]}", 1.2345678e8 * m); // 1.23e+08 m
|
||||
std::println("{::N[G]}", 1.2345678 * m); // 1.23457 m
|
||||
std::println("{::N[G]}", 1.2345678e8 * m); // 1.23457E+08 m
|
||||
std::println("{::N[.3G]}", 1.2345678 * m); // 1.23 m
|
||||
std::println("{::N[.3G]}", 1.2345678e8 * m); // 1.23E+08 m
|
||||
```
|
||||
|
@ -491,7 +491,7 @@ room_temp room_ref{};
|
||||
room_temp room_low = room_ref - number_of_steps * step_delta;
|
||||
room_temp room_high = room_ref + number_of_steps * step_delta;
|
||||
|
||||
std::println("Room reference temperature: {} ({}, {:{%N:.2f}%?%U})\n",
|
||||
std::println("Room reference temperature: {} ({}, {::N[.2f]})\n",
|
||||
room_ref.quantity_from_zero(),
|
||||
room_ref.in(usc::degree_Fahrenheit).quantity_from_zero(),
|
||||
room_ref.in(si::kelvin).quantity_from_zero());
|
||||
@ -501,7 +501,7 @@ std::println("| {:<18} | {:^18} | {:^18} | {:^18} |",
|
||||
std::println("|{0:=^20}|{0:=^20}|{0:=^20}|{0:=^20}|", "");
|
||||
|
||||
auto print_temp = [&](std::string_view label, auto v) {
|
||||
std::println("| {:<18} | {:^18} | {:^18} | {:^18{%N:.2f}%?%U} |", label,
|
||||
std::println("| {:<14} | {:^18} | {:^18} | {:^18:N[.2f]} |", label,
|
||||
v - room_reference_temp, (v - si::ice_point).in(deg_C), (v - si::absolute_zero).in(deg_C));
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ void calcs_comparison()
|
||||
const auto L1A = 2.f * fm;
|
||||
const auto L2A = 3.f * fm;
|
||||
const auto LrA = L1A + L2A;
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.30} %U}\n + {:{%N:.30} %U}\n = {:{%N:.30} %U}\n\n", L1A, L2A, LrA);
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.30]}\n + {::N[.30]}\n = {::N[.30]}\n\n", L1A, L2A, LrA);
|
||||
|
||||
std::cout << "The single unit method must convert large\n"
|
||||
"or small values in other units to the base unit.\n"
|
||||
@ -127,17 +127,17 @@ void calcs_comparison()
|
||||
const auto L1B = L1A.in(m);
|
||||
const auto L2B = L2A.in(m);
|
||||
const auto LrB = L1B + L2B;
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.30e} %U}\n + {:{%N:.30e} %U}\n = {:{%N:.30e} %U}\n\n", L1B, L2B, LrB);
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.30e]}\n + {::N[.30e]}\n = {::N[.30e]}\n\n", L1B, L2B, LrB);
|
||||
|
||||
std::cout << "In multiplication and division:\n\n";
|
||||
|
||||
const quantity<isq::area[square(fm)], float> ArA = L1A * L2A;
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.30} %U}\n * {:{%N:.30} %U}\n = {:{%N:.30} %U}\n\n", L1A, L2A, ArA);
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.30]}\n * {::N[.30]}\n = {::N[.30]}\n\n", L1A, L2A, ArA);
|
||||
|
||||
std::cout << "similar problems arise\n\n";
|
||||
|
||||
const quantity<isq::area[m2], float> ArB = L1B * L2B;
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.30e} %U}\n * {:{%N:.30e} %U}\n = {:{%N:.30e} %U}\n\n", L1B, L2B, ArB);
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.30e]}\n * {::N[.30e]}\n = {::N[.30e]}\n\n", L1B, L2B, ArB);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -87,8 +87,7 @@ void print(const R& gliders)
|
||||
std::cout << "- Polar:\n";
|
||||
for (const auto& p : g.polar) {
|
||||
const auto ratio = glide_ratio(g.polar[0]).force_in(one);
|
||||
std::cout << MP_UNITS_STD_FMT::format(" * {:{%N:.4} %U} @ {:{%N:.1} %U} -> {:{%N:.1} %U} ({:{%N:.1} %U})\n",
|
||||
p.climb, p.v, ratio,
|
||||
std::cout << MP_UNITS_STD_FMT::format(" * {::N[.4]} @ {::N[.1]} -> {::N[.1]} ({::N[.1]})\n", p.climb, p.v, ratio,
|
||||
// TODO is it possible to make ADL work below (we need another set of trig
|
||||
// functions for strong angle in a different namespace)
|
||||
si::asin(1 / ratio).force_in(si::degree));
|
||||
@ -106,8 +105,8 @@ void print(const R& conditions)
|
||||
for (const auto& c : conditions) {
|
||||
std::cout << "- " << c.first << "\n";
|
||||
const auto& w = c.second;
|
||||
std::cout << " * Cloud base: " << MP_UNITS_STD_FMT::format("{:{%N:.0} %U}", w.cloud_base) << " AGL\n";
|
||||
std::cout << " * Thermals strength: " << MP_UNITS_STD_FMT::format("{:{%N:.1} %U}", w.thermal_strength) << "\n";
|
||||
std::cout << " * Cloud base: " << MP_UNITS_STD_FMT::format("{::N[.0]}", w.cloud_base) << " AGL\n";
|
||||
std::cout << " * Thermals strength: " << MP_UNITS_STD_FMT::format("{::N[.1]}", w.thermal_strength) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
@ -119,7 +118,7 @@ void print(const R& waypoints)
|
||||
std::cout << "Waypoints:\n";
|
||||
std::cout << "==========\n";
|
||||
for (const auto& w : waypoints)
|
||||
std::cout << MP_UNITS_STD_FMT::format("- {}: {} {}, {:{%N:.1} %U}\n", w.name, w.pos.lat, w.pos.lon, w.alt);
|
||||
std::cout << MP_UNITS_STD_FMT::format("- {}: {} {}, {::N[.1]}\n", w.name, w.pos.lat, w.pos.lon, w.alt);
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -130,13 +129,12 @@ void print(const task& t)
|
||||
|
||||
std::cout << "- Start: " << t.get_start().name << "\n";
|
||||
std::cout << "- Finish: " << t.get_finish().name << "\n";
|
||||
std::cout << "- Length: " << MP_UNITS_STD_FMT::format("{:{%N:.1} %U}", t.get_distance()) << "\n";
|
||||
std::cout << "- Length: " << MP_UNITS_STD_FMT::format("{::N[.1]}", t.get_distance()) << "\n";
|
||||
|
||||
std::cout << "- Legs: "
|
||||
<< "\n";
|
||||
for (const auto& l : t.get_legs())
|
||||
std::cout << MP_UNITS_STD_FMT::format(" * {} -> {} ({:{%N:.1} %U})\n", l.begin().name, l.end().name,
|
||||
l.get_distance());
|
||||
std::cout << MP_UNITS_STD_FMT::format(" * {} -> {} ({::N[.1]})\n", l.begin().name, l.end().name, l.get_distance());
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -144,7 +142,7 @@ void print(const safety& s)
|
||||
{
|
||||
std::cout << "Safety:\n";
|
||||
std::cout << "=======\n";
|
||||
std::cout << "- Min AGL separation: " << MP_UNITS_STD_FMT::format("{:{%N:.0} %U}", s.min_agl_height) << "\n";
|
||||
std::cout << "- Min AGL separation: " << MP_UNITS_STD_FMT::format("{::N[.0]}", s.min_agl_height) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@ -153,8 +151,8 @@ void print(const aircraft_tow& tow)
|
||||
std::cout << "Tow:\n";
|
||||
std::cout << "====\n";
|
||||
std::cout << "- Type: aircraft\n";
|
||||
std::cout << "- Height: " << MP_UNITS_STD_FMT::format("{:{%N:.0} %U}", tow.height_agl) << "\n";
|
||||
std::cout << "- Performance: " << MP_UNITS_STD_FMT::format("{:{%N:.1} %U}", tow.performance) << "\n";
|
||||
std::cout << "- Height: " << MP_UNITS_STD_FMT::format("{::N[.0]}", tow.height_agl) << "\n";
|
||||
std::cout << "- Performance: " << MP_UNITS_STD_FMT::format("{::N[.1]}", tow.performance) << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
|
@ -82,9 +82,7 @@ void print(std::string_view phase_name, timestamp start_ts, const glide_computer
|
||||
const glide_computer::flight_point& new_point)
|
||||
{
|
||||
std::cout << MP_UNITS_STD_FMT::format(
|
||||
"| {:<12} | {:>9{%N:.1} %U} (Total: {:>9{%N:.1} %U}) | {:>8{%N:.1} %U} (Total: {:>8{%N:.1} %U}) | {:>7{%N:.0} %U} "
|
||||
"({:>6{%N:.0} %U}) "
|
||||
"|\n",
|
||||
"| {:<12} | {:>9:N[.1]} (Total: {:>9:N[.1]}) | {:>8:N[.1]} (Total: {:>8:N[.1]}) | {:>7:N[.0]} ({:>6:N[.0]}) |\n",
|
||||
phase_name, value_cast<si::minute>(new_point.ts - point.ts), value_cast<si::minute>(new_point.ts - start_ts),
|
||||
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt);
|
||||
}
|
||||
|
@ -58,11 +58,11 @@ int main()
|
||||
constexpr quantity v6 = value_cast<m / s>(v4);
|
||||
constexpr quantity v7 = value_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:*^10}\n", v3); // *110 km/h*
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:%N in %U of %D}\n", v4); // 70 in mi/h of LT⁻¹
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.2f}%?%U}\n", v5); // 30.56 in m/s
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:{%N:.2f}%?{%U:dn}}\n", v6); // 31.29 in m⋅s⁻¹
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:%N}\n", v7); // 31
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:*^10}\n", v3); // *110 km/h*
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:%N in %U of %D}\n", v4); // 70 in mi/h of LT⁻¹
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.2f]}\n", v5); // 30.56 m/s
|
||||
std::cout << MP_UNITS_STD_FMT::format("{::N[.2f]U[dn]}\n", v6); // 31.29 m⋅s⁻¹
|
||||
std::cout << MP_UNITS_STD_FMT::format("{:%N}\n", v7); // 31
|
||||
}
|
||||
|
@ -45,19 +45,19 @@ int main()
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
std::cout << "The seven defining constants of the SI and the seven corresponding units they define:\n";
|
||||
std::cout << MP_UNITS_STD_FMT::format("- hyperfine transition frequency of Cs: {} = {:{%N:.0} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- hyperfine transition frequency of Cs: {} = {::N[.0]}\n",
|
||||
1. * si2019::hyperfine_structure_transition_frequency_of_cs,
|
||||
(1. * si2019::hyperfine_structure_transition_frequency_of_cs).in(Hz));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- speed of light in vacuum: {} = {:{%N:.0} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- speed of light in vacuum: {} = {::N[.0]}\n",
|
||||
1. * si2019::speed_of_light_in_vacuum,
|
||||
(1. * si2019::speed_of_light_in_vacuum).in(m / s));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Planck constant: {} = {:{%N:.8e} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Planck constant: {} = {::N[.8e]}\n",
|
||||
1. * si2019::planck_constant, (1. * si2019::planck_constant).in(J * s));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- elementary charge: {} = {:{%N:.9e} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- elementary charge: {} = {::N[.9e]}\n",
|
||||
1. * si2019::elementary_charge, (1. * si2019::elementary_charge).in(C));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Boltzmann constant: {} = {:{%N:.6e} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Boltzmann constant: {} = {::N[.6e]}\n",
|
||||
1. * si2019::boltzmann_constant, (1. * si2019::boltzmann_constant).in(J / K));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Avogadro constant: {} = {:{%N:.8e} %U}\n",
|
||||
std::cout << MP_UNITS_STD_FMT::format("- Avogadro constant: {} = {::N[.8e]}\n",
|
||||
1. * si2019::avogadro_constant, (1. * si2019::avogadro_constant).in(one / mol));
|
||||
std::cout << MP_UNITS_STD_FMT::format("- luminous efficacy: {} = {}\n",
|
||||
1. * si2019::luminous_efficacy, (1. * si2019::luminous_efficacy).in(lm / W));
|
||||
|
@ -170,6 +170,6 @@ int main()
|
||||
};
|
||||
|
||||
waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft};
|
||||
std::cout << MP_UNITS_STD_FMT::format("{}: {} {}, {:{%N:.2} %U}, {:{%N:.2} %U}\n", wpt.name, wpt.pos.lat, wpt.pos.lon,
|
||||
std::cout << MP_UNITS_STD_FMT::format("{}: {} {}, {::N[.2]}, {::N[.2]}\n", wpt.name, wpt.pos.lat, wpt.pos.lon,
|
||||
wpt.msl_alt, to_hae<earth_gravity_model::egm2008_1>(wpt.msl_alt, wpt.pos));
|
||||
}
|
||||
|
@ -67,31 +67,6 @@ template<typename Char, typename Specs>
|
||||
return mp_units::detail::parse_dynamic_spec(it, end, specs.width, specs.width_ref, ctx);
|
||||
}
|
||||
|
||||
template<typename Char, typename Handler>
|
||||
[[nodiscard]] constexpr const Char* parse_subentity_replacement_field(const Char* begin, const Char* end,
|
||||
Handler&& handler)
|
||||
{
|
||||
if (end - begin++ < 4)
|
||||
return MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("`subentity-replacement-field` too short")), end;
|
||||
if (*begin++ != '%')
|
||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("`subentity-replacement-field` should start with '%'"));
|
||||
if (*begin == '}')
|
||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("`subentity-replacement-field` should have an identifier"));
|
||||
auto it = begin;
|
||||
for (; it != end; ++it) {
|
||||
if (*it == '{' || *it == '%')
|
||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid `subentity-replacement-field` format"));
|
||||
if (*it == '}' || *it == ':') break;
|
||||
}
|
||||
if (it == end) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("`subentity-replacement-field` too short"));
|
||||
std::string_view id{begin, it};
|
||||
if (*it == ':') ++it;
|
||||
it = handler.on_replacement_field(id, it);
|
||||
if (it == end || *it != '}')
|
||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("`subentity-replacement-field` should end with '}'"));
|
||||
return ++it;
|
||||
}
|
||||
|
||||
template<typename OutputIt, typename Char>
|
||||
OutputIt format_global_buffer(OutputIt out, const fill_align_width_format_specs<Char>& specs)
|
||||
{
|
||||
@ -128,25 +103,10 @@ OutputIt format_global_buffer(OutputIt out, const fill_align_width_format_specs<
|
||||
template<mp_units::Dimension D, typename Char>
|
||||
class MP_UNITS_STD_FMT::formatter<D, Char> {
|
||||
struct format_specs : mp_units::detail::fill_align_width_format_specs<Char>, mp_units::dimension_symbol_formatting {};
|
||||
|
||||
std::basic_string_view<Char> fill_align_width_format_str_;
|
||||
std::basic_string_view<Char> modifiers_format_str_;
|
||||
format_specs specs_{};
|
||||
std::basic_string_view<Char> fill_align_width_format_str_;
|
||||
|
||||
struct format_checker {
|
||||
using enum mp_units::text_encoding;
|
||||
mp_units::text_encoding encoding = unicode;
|
||||
constexpr void on_text_encoding(Char val) { encoding = (val == 'U') ? unicode : ascii; }
|
||||
};
|
||||
|
||||
struct unit_formatter {
|
||||
format_specs specs;
|
||||
using enum mp_units::text_encoding;
|
||||
constexpr void on_text_encoding(Char val) { specs.encoding = (val == 'U') ? unicode : ascii; }
|
||||
};
|
||||
|
||||
template<typename Handler>
|
||||
constexpr const Char* parse_dimension_specs(const Char* begin, const Char* end, Handler&& handler) const
|
||||
constexpr const Char* parse_dimension_specs(const Char* begin, const Char* end)
|
||||
{
|
||||
auto it = begin;
|
||||
if (it == end || *it == '}') return begin;
|
||||
@ -158,7 +118,9 @@ class MP_UNITS_STD_FMT::formatter<D, Char> {
|
||||
}
|
||||
end = it;
|
||||
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "UA"); it != end) handler.on_text_encoding(*it);
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "UA"); it != end)
|
||||
specs_.encoding = (*it == 'U') ? mp_units::text_encoding::unicode : mp_units::text_encoding::ascii;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -172,26 +134,21 @@ public:
|
||||
fill_align_width_format_str_ = {begin, it};
|
||||
if (it == end) return it;
|
||||
|
||||
format_checker checker;
|
||||
end = parse_dimension_specs(it, end, checker);
|
||||
modifiers_format_str_ = {it, end};
|
||||
return end;
|
||||
return parse_dimension_specs(it, end);
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const D& d, FormatContext& ctx) const -> decltype(ctx.out())
|
||||
{
|
||||
unit_formatter f{specs_};
|
||||
mp_units::detail::handle_dynamic_spec<mp_units::detail::width_checker>(f.specs.width, f.specs.width_ref, ctx);
|
||||
auto specs = specs_;
|
||||
mp_units::detail::handle_dynamic_spec<mp_units::detail::width_checker>(specs.width, specs.width_ref, ctx);
|
||||
|
||||
parse_dimension_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f);
|
||||
|
||||
if (f.specs.width == 0) {
|
||||
if (specs.width == 0) {
|
||||
// Avoid extra copying if width is not specified
|
||||
return mp_units::dimension_symbol_to<Char>(ctx.out(), d, f.specs);
|
||||
return mp_units::dimension_symbol_to<Char>(ctx.out(), d, specs);
|
||||
} else {
|
||||
std::basic_string<Char> unit_buffer;
|
||||
mp_units::dimension_symbol_to<Char>(std::back_inserter(unit_buffer), d, f.specs);
|
||||
mp_units::dimension_symbol_to<Char>(std::back_inserter(unit_buffer), d, specs);
|
||||
|
||||
std::basic_string<Char> global_format_buffer = "{:" + std::basic_string<Char>{fill_align_width_format_str_} + "}";
|
||||
return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer,
|
||||
@ -217,52 +174,11 @@ public:
|
||||
template<mp_units::Unit U, typename Char>
|
||||
class MP_UNITS_STD_FMT::formatter<U, Char> {
|
||||
struct format_specs : mp_units::detail::fill_align_width_format_specs<Char>, mp_units::unit_symbol_formatting {};
|
||||
|
||||
std::basic_string_view<Char> fill_align_width_format_str_;
|
||||
std::basic_string_view<Char> modifiers_format_str_;
|
||||
format_specs specs_{};
|
||||
|
||||
struct format_checker {
|
||||
using enum mp_units::text_encoding;
|
||||
std::basic_string_view<Char> fill_align_width_format_str_;
|
||||
|
||||
mp_units::text_encoding encoding = unicode;
|
||||
|
||||
constexpr void on_text_encoding(Char val) { encoding = (val == 'U') ? unicode : ascii; }
|
||||
constexpr void on_unit_symbol_solidus(Char) const {}
|
||||
constexpr void on_unit_symbol_separator(Char val) const
|
||||
{
|
||||
if (val == 'd' && encoding == ascii)
|
||||
throw MP_UNITS_STD_FMT::format_error("half_high_dot unit separator allowed only for Unicode encoding");
|
||||
}
|
||||
};
|
||||
|
||||
struct unit_formatter {
|
||||
format_specs specs;
|
||||
|
||||
using enum mp_units::text_encoding;
|
||||
using enum mp_units::unit_symbol_solidus;
|
||||
using enum mp_units::unit_symbol_separator;
|
||||
|
||||
constexpr void on_text_encoding(Char val) { specs.encoding = (val == 'U') ? unicode : ascii; }
|
||||
constexpr void on_unit_symbol_solidus(Char val)
|
||||
{
|
||||
switch (val) {
|
||||
case '1':
|
||||
specs.solidus = one_denominator;
|
||||
break;
|
||||
case 'a':
|
||||
specs.solidus = always;
|
||||
break;
|
||||
case 'n':
|
||||
specs.solidus = never;
|
||||
break;
|
||||
}
|
||||
}
|
||||
constexpr void on_unit_symbol_separator(Char val) { specs.separator = (val == 's') ? space : half_high_dot; }
|
||||
};
|
||||
|
||||
template<typename Handler>
|
||||
constexpr const Char* parse_unit_specs(const Char* begin, const Char* end, Handler&& handler) const
|
||||
constexpr const Char* parse_unit_specs(const Char* begin, const Char* end)
|
||||
{
|
||||
auto it = begin;
|
||||
if (it == end || *it == '}') return begin;
|
||||
@ -274,9 +190,27 @@ class MP_UNITS_STD_FMT::formatter<U, Char> {
|
||||
}
|
||||
end = it;
|
||||
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "UA"); it != end) handler.on_text_encoding(*it);
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "1an"); it != end) handler.on_unit_symbol_solidus(*it);
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "sd"); it != end) handler.on_unit_symbol_separator(*it);
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "UA"); it != end)
|
||||
specs_.encoding = (*it == 'U') ? mp_units::text_encoding::unicode : mp_units::text_encoding::ascii;
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "1an"); it != end) {
|
||||
switch (*it) {
|
||||
case '1':
|
||||
specs_.solidus = mp_units::unit_symbol_solidus::one_denominator;
|
||||
break;
|
||||
case 'a':
|
||||
specs_.solidus = mp_units::unit_symbol_solidus::always;
|
||||
break;
|
||||
case 'n':
|
||||
specs_.solidus = mp_units::unit_symbol_solidus::never;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it = mp_units::detail::at_most_one_of(begin, end, "sd"); it != end) {
|
||||
if (*it == 'd' && specs_.encoding == mp_units::text_encoding::ascii)
|
||||
throw MP_UNITS_STD_FMT::format_error("half_high_dot unit separator allowed only for Unicode encoding");
|
||||
specs_.separator =
|
||||
(*it == 's') ? mp_units::unit_symbol_separator::space : mp_units::unit_symbol_separator::half_high_dot;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -290,26 +224,21 @@ public:
|
||||
fill_align_width_format_str_ = {begin, it};
|
||||
if (it == end) return it;
|
||||
|
||||
format_checker checker;
|
||||
end = parse_unit_specs(it, end, checker);
|
||||
modifiers_format_str_ = {it, end};
|
||||
return end;
|
||||
return parse_unit_specs(it, end);
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const U& u, FormatContext& ctx) const -> decltype(ctx.out())
|
||||
{
|
||||
unit_formatter f{specs_};
|
||||
mp_units::detail::handle_dynamic_spec<mp_units::detail::width_checker>(f.specs.width, f.specs.width_ref, ctx);
|
||||
auto specs = specs_;
|
||||
mp_units::detail::handle_dynamic_spec<mp_units::detail::width_checker>(specs.width, specs.width_ref, ctx);
|
||||
|
||||
parse_unit_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f);
|
||||
|
||||
if (f.specs.width == 0) {
|
||||
if (specs.width == 0) {
|
||||
// Avoid extra copying if width is not specified
|
||||
return mp_units::unit_symbol_to<Char>(ctx.out(), u, f.specs);
|
||||
return mp_units::unit_symbol_to<Char>(ctx.out(), u, specs);
|
||||
} else {
|
||||
std::basic_string<Char> unit_buffer;
|
||||
mp_units::unit_symbol_to<Char>(std::back_inserter(unit_buffer), u, f.specs);
|
||||
mp_units::unit_symbol_to<Char>(std::back_inserter(unit_buffer), u, specs);
|
||||
|
||||
std::basic_string<Char> global_format_buffer = "{:" + std::basic_string<Char>{fill_align_width_format_str_} + "}";
|
||||
return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer,
|
||||
@ -322,22 +251,25 @@ public:
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
// quantity-format-spec ::= [fill-and-align] [width] [quantity-specs]
|
||||
// quantity-format-spec ::= [fill-and-align] [width] [quantity-specs] [defaults-specs]
|
||||
// quantity-specs ::= conversion-spec
|
||||
// quantity-specs conversion-spec
|
||||
// quantity-specs literal-char
|
||||
// literal-char ::= <any character other than '{', '}', or '%'>
|
||||
// conversion-spec ::= placement-spec
|
||||
// subentity-replacement-field
|
||||
// placement-spec ::= '%' placement-type
|
||||
// placement-type ::= 'N' | 'U' | 'D' | '?' | '%'
|
||||
// subentity-replacement-field ::= '{' '%' subentity-id [format-specifier] '}'
|
||||
// subentity-id ::= literal-char
|
||||
// subentity-id literal-char
|
||||
// format-specifier ::= ':' format-spec
|
||||
// format-spec ::= <as specified by the formatter for the argument type; cannot start with '}'>
|
||||
// conversion-spec ::= '%' placement-type
|
||||
// placement-type ::= subentity-id | '?' | '%'
|
||||
// defaults-specs ::= ':' default-spec-list
|
||||
// default-spec-list ::= default-spec
|
||||
// default-spec-list default-spec
|
||||
// default-spec ::= subentity-id '[' format-spec ']'
|
||||
// subentity-id ::= 'N' | 'U' | 'D'
|
||||
// format-spec ::= <as specified by the formatter for the argument type>
|
||||
//
|
||||
#if __cpp_lib_format_ranges && !MP_UNITS_USE_FMTLIB
|
||||
template<auto Reference, typename Char, std::formattable<Char> Rep>
|
||||
#else
|
||||
template<auto Reference, typename Rep, typename Char>
|
||||
#endif
|
||||
class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
static constexpr auto unit = get_unit(Reference);
|
||||
static constexpr auto dimension = get_quantity_spec(Reference).dimension;
|
||||
@ -345,106 +277,76 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
using quantity_t = mp_units::quantity<Reference, Rep>;
|
||||
using unit_t = std::remove_const_t<decltype(unit)>;
|
||||
using dimension_t = std::remove_const_t<decltype(dimension)>;
|
||||
|
||||
using format_specs = mp_units::detail::fill_align_width_format_specs<Char>;
|
||||
|
||||
std::basic_string_view<Char> modifiers_format_str_;
|
||||
std::vector<size_t> format_str_lengths_;
|
||||
format_specs specs_{};
|
||||
|
||||
std::basic_string_view<Char> modifiers_format_str_;
|
||||
std::basic_string<Char> rep_format_str_ = "{}";
|
||||
std::basic_string<Char> unit_format_str_ = "{}";
|
||||
std::basic_string<Char> dimension_format_str_ = "{}";
|
||||
|
||||
MP_UNITS_STD_FMT::formatter<Rep> rep_formatter_;
|
||||
MP_UNITS_STD_FMT::formatter<unit_t> unit_formatter_;
|
||||
MP_UNITS_STD_FMT::formatter<dimension_t> dimension_formatter_;
|
||||
|
||||
struct format_checker {
|
||||
MP_UNITS_STD_FMT::basic_format_parse_context<Char>& ctx;
|
||||
std::vector<size_t>& format_str_lengths;
|
||||
|
||||
constexpr void on_number(std::basic_string_view<Char>) const {}
|
||||
constexpr void on_number() const {}
|
||||
constexpr void on_maybe_space() const {}
|
||||
constexpr void on_unit(std::basic_string_view<Char>) const {}
|
||||
constexpr void on_dimension(std::basic_string_view<Char>) const {}
|
||||
constexpr void on_unit() const {}
|
||||
constexpr void on_dimension() const {}
|
||||
constexpr void on_text(const Char*, const Char*) const {}
|
||||
|
||||
constexpr const Char* on_replacement_field(std::basic_string_view<Char> id, const Char* begin)
|
||||
{
|
||||
if (id == "N")
|
||||
return on_replacement_field<Rep>(begin);
|
||||
else if (id == "U")
|
||||
return on_replacement_field<unit_t>(begin);
|
||||
else if (id == "D")
|
||||
return on_replacement_field<dimension_t>(begin);
|
||||
else
|
||||
throw MP_UNITS_STD_FMT::format_error("unknown replacement field '" + std::string(id) + "'");
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
constexpr const Char* on_replacement_field(const Char* begin) const
|
||||
{
|
||||
MP_UNITS_STD_FMT::formatter<T> sf;
|
||||
ctx.advance_to(begin);
|
||||
auto ptr = sf.parse(ctx);
|
||||
if (*ptr != '}') throw MP_UNITS_STD_FMT::format_error("unmatched '}' in format string");
|
||||
format_str_lengths.push_back(mp_units::detail::to_unsigned(ptr - begin));
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename OutputIt>
|
||||
struct quantity_formatter {
|
||||
const formatter& f;
|
||||
OutputIt out;
|
||||
const quantity_t& q;
|
||||
std::vector<size_t>::const_iterator format_str_lengths_it;
|
||||
std::locale locale;
|
||||
|
||||
void on_number(std::basic_string_view<Char> format_str)
|
||||
void on_number()
|
||||
{
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, format_str,
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, f.rep_format_str_,
|
||||
MP_UNITS_STD_FMT::make_format_args(q.numerical_value_ref_in(q.unit)));
|
||||
}
|
||||
void on_maybe_space()
|
||||
{
|
||||
if constexpr (mp_units::space_before_unit_symbol<unit>) *out++ = ' ';
|
||||
}
|
||||
void on_unit(std::basic_string_view<Char> format_str)
|
||||
void on_unit()
|
||||
{
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, format_str, MP_UNITS_STD_FMT::make_format_args(q.unit));
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, f.unit_format_str_, MP_UNITS_STD_FMT::make_format_args(q.unit));
|
||||
}
|
||||
void on_dimension(std::basic_string_view<Char> format_str)
|
||||
void on_dimension()
|
||||
{
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, format_str, MP_UNITS_STD_FMT::make_format_args(q.dimension));
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, f.dimension_format_str_,
|
||||
MP_UNITS_STD_FMT::make_format_args(q.dimension));
|
||||
}
|
||||
void on_text(const Char* begin, const Char* end) const { std::copy(begin, end, out); }
|
||||
|
||||
constexpr const Char* on_replacement_field(std::basic_string_view<Char> id, const Char* begin)
|
||||
{
|
||||
auto format_str = [&] { return "{:" + std::string(begin, *format_str_lengths_it + 1); };
|
||||
if (id == "N")
|
||||
on_number(format_str());
|
||||
else if (id == "U")
|
||||
on_unit(format_str());
|
||||
else if (id == "D")
|
||||
on_dimension(format_str());
|
||||
else
|
||||
throw MP_UNITS_STD_FMT::format_error("unknown replacement field '" + std::string(id) + "'");
|
||||
return begin + *format_str_lengths_it++;
|
||||
}
|
||||
};
|
||||
template<typename OutputIt, typename... Args>
|
||||
quantity_formatter(OutputIt, Args...) -> quantity_formatter<OutputIt>;
|
||||
quantity_formatter(const formatter&, OutputIt, Args...) -> quantity_formatter<OutputIt>;
|
||||
|
||||
template<typename Handler>
|
||||
constexpr const Char* parse_quantity_specs(const Char* begin, const Char* end, Handler&& handler) const
|
||||
{
|
||||
if (begin == end || *begin == '}') return begin;
|
||||
if (*begin != '%' && *begin != '{')
|
||||
if (begin == end || *begin == ':' || *begin == '}') return begin;
|
||||
if (*begin != '%')
|
||||
throw MP_UNITS_STD_FMT::format_error(
|
||||
"`quantity-specs` should start with a `conversion-spec` ('%' or '{' characters expected)})");
|
||||
"`quantity-specs` should start with a `conversion-spec` ('%' characters expected)");
|
||||
auto ptr = begin;
|
||||
while (ptr != end) {
|
||||
auto c = *ptr;
|
||||
if (c == '}') break;
|
||||
if (c == '{') {
|
||||
if (begin != ptr) handler.on_text(begin, ptr);
|
||||
begin = ptr = mp_units::detail::parse_subentity_replacement_field(ptr, end, handler);
|
||||
continue;
|
||||
if (c == ':') {
|
||||
if (ptr + 1 != end && *(ptr + 1) == ':') {
|
||||
handler.on_text(begin, ++ptr); // account for ':'
|
||||
++ptr; // consume the second ':'
|
||||
continue;
|
||||
} else
|
||||
// default specs started
|
||||
break;
|
||||
}
|
||||
if (c != '%') {
|
||||
++ptr;
|
||||
@ -452,18 +354,18 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
}
|
||||
if (begin != ptr) handler.on_text(begin, ptr);
|
||||
++ptr; // consume '%'
|
||||
if (ptr == end) throw MP_UNITS_STD_FMT::format_error("invalid `placement-spec` format");
|
||||
if (ptr == end) throw MP_UNITS_STD_FMT::format_error("invalid `conversion-spec` format");
|
||||
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 'N':
|
||||
handler.on_number("{}");
|
||||
handler.on_number();
|
||||
break;
|
||||
case 'U':
|
||||
handler.on_unit("{}");
|
||||
handler.on_unit();
|
||||
break;
|
||||
case 'D':
|
||||
handler.on_dimension("{}");
|
||||
handler.on_dimension();
|
||||
break;
|
||||
case '?':
|
||||
handler.on_maybe_space();
|
||||
@ -472,7 +374,7 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
handler.on_text(ptr - 1, ptr);
|
||||
break;
|
||||
default:
|
||||
throw MP_UNITS_STD_FMT::format_error(std::string("unknown `placement-spec` token '") + c + "'");
|
||||
throw MP_UNITS_STD_FMT::format_error(std::string("unknown `placement-type` token '") + c + "'");
|
||||
}
|
||||
begin = ptr;
|
||||
}
|
||||
@ -480,19 +382,63 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename Formatter>
|
||||
constexpr const Char* parse_default_spec(const Char* begin, const Char* end, Formatter& f, std::string& format_str)
|
||||
{
|
||||
if (begin == end || *begin++ != '[')
|
||||
throw MP_UNITS_STD_FMT::format_error("`default-spec` should contain a `[` character");
|
||||
auto it = begin;
|
||||
for (int nested_brackets = 0; it != end && !(*it == ']' && nested_brackets == 0); it++) {
|
||||
if (*it == '[') ++nested_brackets;
|
||||
if (*it == ']') {
|
||||
if (nested_brackets == 0) throw MP_UNITS_STD_FMT::format_error("unmatched ']' in format string");
|
||||
--nested_brackets;
|
||||
}
|
||||
}
|
||||
format_str = "{:" + std::string(begin, it) + '}';
|
||||
if (it == end) throw MP_UNITS_STD_FMT::format_error("unmatched '[' in format string");
|
||||
MP_UNITS_STD_FMT::basic_format_parse_context<Char> ctx(std::string_view(begin, it));
|
||||
auto ptr = f.parse(ctx);
|
||||
if (ptr != it) throw MP_UNITS_STD_FMT::format_error("invalid subentity format '" + std::string(begin, it) + "'");
|
||||
return ++it; // skip `]`
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const Char* parse_defaults_specs(const Char* begin, const Char* end)
|
||||
{
|
||||
if (begin == end || *begin == '}') return begin;
|
||||
if (*begin++ != ':') throw MP_UNITS_STD_FMT::format_error("`defaults-specs` should start with a `:`");
|
||||
do {
|
||||
auto c = *begin++;
|
||||
switch (c) {
|
||||
case 'N':
|
||||
begin = parse_default_spec(begin, end, rep_formatter_, rep_format_str_);
|
||||
break;
|
||||
case 'U':
|
||||
begin = parse_default_spec(begin, end, unit_formatter_, unit_format_str_);
|
||||
break;
|
||||
case 'D':
|
||||
begin = parse_default_spec(begin, end, dimension_formatter_, dimension_format_str_);
|
||||
break;
|
||||
default:
|
||||
throw MP_UNITS_STD_FMT::format_error(std::string("unknown `subentity-id` token '") + c + "'");
|
||||
}
|
||||
} while (begin != end && *begin != '}');
|
||||
return begin;
|
||||
}
|
||||
|
||||
template<typename OutputIt, typename FormatContext>
|
||||
OutputIt format_quantity(OutputIt out, const quantity_t& q, FormatContext& ctx) const
|
||||
{
|
||||
std::locale locale = MP_UNITS_FMT_LOCALE(ctx.locale());
|
||||
if (modifiers_format_str_.empty()) {
|
||||
// default format should print value followed by the unit separated with 1 space
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, "{}",
|
||||
// default
|
||||
out = MP_UNITS_STD_FMT::vformat_to(out, locale, rep_format_str_,
|
||||
MP_UNITS_STD_FMT::make_format_args(q.numerical_value_ref_in(q.unit)));
|
||||
if constexpr (mp_units::space_before_unit_symbol<unit>) *out++ = ' ';
|
||||
return MP_UNITS_STD_FMT::vformat_to(out, locale, "{}", MP_UNITS_STD_FMT::make_format_args(q.unit));
|
||||
return MP_UNITS_STD_FMT::vformat_to(out, locale, unit_format_str_, MP_UNITS_STD_FMT::make_format_args(q.unit));
|
||||
} else {
|
||||
// user provided format
|
||||
quantity_formatter f{out, q, format_str_lengths_.cbegin(), locale};
|
||||
quantity_formatter f{*this, out, q, locale};
|
||||
parse_quantity_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f);
|
||||
return f.out;
|
||||
}
|
||||
@ -501,16 +447,16 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
||||
public:
|
||||
constexpr auto parse(MP_UNITS_STD_FMT::basic_format_parse_context<Char>& ctx) -> decltype(ctx.begin())
|
||||
{
|
||||
const auto begin = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
|
||||
auto it = parse_fill_align_width(ctx, begin, end, specs_, mp_units::detail::fmt_align::right);
|
||||
if (it == end) return it;
|
||||
begin = parse_fill_align_width(ctx, begin, end, specs_, mp_units::detail::fmt_align::right);
|
||||
if (begin == end) return begin;
|
||||
|
||||
format_checker checker{ctx, format_str_lengths_};
|
||||
end = parse_quantity_specs(it, end, checker);
|
||||
modifiers_format_str_ = {it, end};
|
||||
return end;
|
||||
format_checker checker{};
|
||||
auto it = parse_quantity_specs(begin, end, checker);
|
||||
modifiers_format_str_ = {begin, it};
|
||||
|
||||
return parse_defaults_specs(it, end);
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
@ -521,7 +467,8 @@ public:
|
||||
|
||||
if (specs.width == 0) {
|
||||
// Avoid extra copying if width is not specified
|
||||
return format_quantity(ctx.out(), q, ctx);
|
||||
format_quantity(ctx.out(), q, ctx);
|
||||
return ctx.out();
|
||||
} else {
|
||||
std::basic_string<Char> quantity_buffer;
|
||||
format_quantity(std::back_inserter(quantity_buffer), q, ctx);
|
||||
|
@ -738,45 +738,72 @@ TEST_CASE("sign specification", "[text][fmt]")
|
||||
|
||||
SECTION("full format {:%N%?%U} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:{%N:+}%U},{0:{%N:-}%U},{0:{%N: }%U}", 1 * isq::length[m]) ==
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", 1 * isq::length[m]) ==
|
||||
"1m,+1m,1m, 1m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:{%N:+}%U},{0:{%N:-}%U},{0:{%N: }%U}", -1 * isq::length[m]) ==
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", -1 * isq::length[m]) ==
|
||||
"-1m,-1m,-1m,-1m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:{%N:+}%U},{0:{%N:-}%U},{0:{%N: }%U}", inf) == "infm,+infm,infm, infm");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:{%N:+}%U},{0:{%N:-}%U},{0:{%N: }%U}", nan) == "nanm,+nanm,nanm, nanm");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", inf) ==
|
||||
"infm,+infm,infm, infm");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N%U},{0:%N%U:N[+]},{0:%N%U:N[-]},{0:%N%U:N[ ]}", nan) ==
|
||||
"nanm,+nanm,nanm, nanm");
|
||||
}
|
||||
|
||||
SECTION("value only format {:%N} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:{%N:+}},{0:{%N:-}},{0:{%N: }}", 1 * isq::length[m]) == "1,+1,1, 1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:{%N:+}},{0:{%N:-}},{0:{%N: }}", -1 * isq::length[m]) == "-1,-1,-1,-1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:{%N:+}},{0:{%N:-}},{0:{%N: }}", inf) == "inf,+inf,inf, inf");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:{%N:+}},{0:{%N:-}},{0:{%N: }}", nan) == "nan,+nan,nan, nan");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", 1 * isq::length[m]) == "1,+1,1, 1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", -1 * isq::length[m]) == "-1,-1,-1,-1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", inf) == "inf,+inf,inf, inf");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{0:%N},{0:%N:N[+]},{0:%N:N[-]},{0:%N:N[ ]}", nan) == "nan,+nan,nan, nan");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("precision specification", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%N%?%U} on a quantity")
|
||||
SECTION("full format on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.0f}%?%U}", 1.2345 * isq::length[m]) == "1 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.1f}%?%U}", 1.2345 * isq::length[m]) == "1.2 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.2f}%?%U}", 1.2345 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3f}%?%U}", 1.2345 * isq::length[m]) == "1.234 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.4f}%?%U}", 1.2345 * isq::length[m]) == "1.2345 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.5f}%?%U}", 1.2345 * isq::length[m]) == "1.23450 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.10f}%?%U}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||
SECTION("default spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.0f]}", 1.2345 * isq::length[m]) == "1 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||
}
|
||||
|
||||
SECTION("explicit spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.0f]}", 1.2345 * isq::length[m]) == "1 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000 m");
|
||||
}
|
||||
|
||||
SECTION("modified spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.0f]}", 1.2345 * isq::length[m]) == "1m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.1f]}", 1.2345 * isq::length[m]) == "1.2m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.2f]}", 1.2345 * isq::length[m]) == "1.23m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3f]}", 1.2345 * isq::length[m]) == "1.234m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000m");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value only format {:%N} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.0f}}", 1.2345 * isq::length[m]) == "1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.1f}}", 1.2345 * isq::length[m]) == "1.2");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.2f}}", 1.2345 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3f}}", 1.2345 * isq::length[m]) == "1.234");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.4f}}", 1.2345 * isq::length[m]) == "1.2345");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.5f}}", 1.2345 * isq::length[m]) == "1.23450");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.10f}}", 1.2345 * isq::length[m]) == "1.2345000000");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.0f]}", 1.2345 * isq::length[m]) == "1");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.1f]}", 1.2345 * isq::length[m]) == "1.2");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.2f]}", 1.2345 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3f]}", 1.2345 * isq::length[m]) == "1.234");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.4f]}", 1.2345 * isq::length[m]) == "1.2345");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.5f]}", 1.2345 * isq::length[m]) == "1.23450");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.10f]}", 1.2345 * isq::length[m]) == "1.2345000000");
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,70 +811,141 @@ TEST_CASE("type specification", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%N%?%U} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:b}%?%U}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:B}%?%U}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:d}%?%U}", 42 * isq::length[m]) == "42 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:o}%?%U}", 42 * isq::length[m]) == "52 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:x}%?%U}", 42 * isq::length[m]) == "2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:X}%?%U}", 42 * isq::length[m]) == "2A m");
|
||||
SECTION("default spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[b]}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[B]}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[d]}", 42 * isq::length[m]) == "42 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[o]}", 42 * isq::length[m]) == "52 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[x]}", 42 * isq::length[m]) == "2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[X]}", 42 * isq::length[m]) == "2A m");
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:a}%?%U}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3a}%?%U}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:A}%?%U}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3A}%?%U}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m");
|
||||
#else
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:a}%?%U}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3a}%?%U}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:A}%?%U}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3A}%?%U}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m");
|
||||
#endif
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:e}%?%U}", 1.2345678 * isq::length[m]) == "1.234568e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3e}%?%U}", 1.2345678 * isq::length[m]) == "1.235e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:E}%?%U}", 1.2345678 * isq::length[m]) == "1.234568E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3E}%?%U}", 1.2345678 * isq::length[m]) == "1.235E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:g}%?%U}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:g}%?%U}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3g}%?%U}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3g}%?%U}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:G}%?%U}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:G}%?%U}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3G}%?%U}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3G}%?%U}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||
}
|
||||
|
||||
SECTION("explicit spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[b]}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[B]}", 42 * isq::length[m]) == "101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[d]}", 42 * isq::length[m]) == "42 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[o]}", 42 * isq::length[m]) == "52 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[x]}", 42 * isq::length[m]) == "2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[X]}", 42 * isq::length[m]) == "2A m");
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0 m");
|
||||
#else
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0 m");
|
||||
#endif
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08 m");
|
||||
}
|
||||
|
||||
SECTION("modified spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[b]}", 42 * isq::length[m]) == "101010m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[B]}", 42 * isq::length[m]) == "101010m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[d]}", 42 * isq::length[m]) == "42m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[o]}", 42 * isq::length[m]) == "52m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[x]}", 42 * isq::length[m]) == "2am");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[X]}", 42 * isq::length[m]) == "2Am");
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0m");
|
||||
#else
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0m");
|
||||
#endif
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678 * isq::length[m]) == "1.23457m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678 * isq::length[m]) == "1.23457m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08m");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value only format {:%N} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:b}}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:B}}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:d}}", 42 * isq::length[m]) == "42");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:o}}", 42 * isq::length[m]) == "52");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:x}}", 42 * isq::length[m]) == "2a");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:X}}", 42 * isq::length[m]) == "2A");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[b]}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[B]}", 42 * isq::length[m]) == "101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[d]}", 42 * isq::length[m]) == "42");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[o]}", 42 * isq::length[m]) == "52");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[x]}", 42 * isq::length[m]) == "2a");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[X]}", 42 * isq::length[m]) == "2A");
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:a}}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3a}}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:A}}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3A}}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "0x1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "0x1.3c1p+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "0X1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "0X1.3C1P+0");
|
||||
#else
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:a}}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3a}}", 1.2345678 * isq::length[m]) == "1.3c1p+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:A}}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3A}}", 1.2345678 * isq::length[m]) == "1.3C1P+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[a]}", 1.2345678 * isq::length[m]) == "1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3a]}", 1.2345678 * isq::length[m]) == "1.3c1p+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[A]}", 1.2345678 * isq::length[m]) == "1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3A]}", 1.2345678 * isq::length[m]) == "1.3C1P+0");
|
||||
#endif
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:e}}", 1.2345678 * isq::length[m]) == "1.234568e+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3e}}", 1.2345678 * isq::length[m]) == "1.235e+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:E}}", 1.2345678 * isq::length[m]) == "1.234568E+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3E}}", 1.2345678 * isq::length[m]) == "1.235E+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:g}}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:g}}", 1.2345678e8 * isq::length[m]) == "1.23457e+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3g}}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3g}}", 1.2345678e8 * isq::length[m]) == "1.23e+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:G}}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:G}}", 1.2345678e8 * isq::length[m]) == "1.23457E+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3G}}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:.3G}}", 1.2345678e8 * isq::length[m]) == "1.23E+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[e]}", 1.2345678 * isq::length[m]) == "1.234568e+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3e]}", 1.2345678 * isq::length[m]) == "1.235e+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[E]}", 1.2345678 * isq::length[m]) == "1.234568E+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3E]}", 1.2345678 * isq::length[m]) == "1.235E+00");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[g]}", 1.2345678e8 * isq::length[m]) == "1.23457e+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3g]}", 1.2345678e8 * isq::length[m]) == "1.23e+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678 * isq::length[m]) == "1.23457");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[G]}", 1.2345678e8 * isq::length[m]) == "1.23457E+08");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678 * isq::length[m]) == "1.23");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[.3G]}", 1.2345678e8 * isq::length[m]) == "1.23E+08");
|
||||
}
|
||||
}
|
||||
|
||||
@ -855,20 +953,41 @@ TEST_CASE("different base types with the # specifier", "[text][fmt]")
|
||||
{
|
||||
SECTION("full format {:%N%?%U} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#b}%?%U}", 42 * isq::length[m]) == "0b101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#B}%?%U}", 42 * isq::length[m]) == "0B101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#o}%?%U}", 42 * isq::length[m]) == "052 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#x}%?%U}", 42 * isq::length[m]) == "0x2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#X}%?%U}", 42 * isq::length[m]) == "0X2A m");
|
||||
SECTION("default spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[#b]}", 42 * isq::length[m]) == "0b101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[#B]}", 42 * isq::length[m]) == "0B101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[#o]}", 42 * isq::length[m]) == "052 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[#x]}", 42 * isq::length[m]) == "0x2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{::N[#X]}", 42 * isq::length[m]) == "0X2A m");
|
||||
}
|
||||
|
||||
SECTION("explicit spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#b]}", 42 * isq::length[m]) == "0b101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#B]}", 42 * isq::length[m]) == "0B101010 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#o]}", 42 * isq::length[m]) == "052 m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#x]}", 42 * isq::length[m]) == "0x2a m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%?%U:N[#X]}", 42 * isq::length[m]) == "0X2A m");
|
||||
}
|
||||
|
||||
SECTION("modified spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#b]}", 42 * isq::length[m]) == "0b101010m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#B]}", 42 * isq::length[m]) == "0B101010m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#o]}", 42 * isq::length[m]) == "052m");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#x]}", 42 * isq::length[m]) == "0x2am");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N%U:N[#X]}", 42 * isq::length[m]) == "0X2Am");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value only format {:%N} on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#b}}", 42 * isq::length[m]) == "0b101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#B}}", 42 * isq::length[m]) == "0B101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#o}}", 42 * isq::length[m]) == "052");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#x}}", 42 * isq::length[m]) == "0x2a");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:{%N:#X}}", 42 * isq::length[m]) == "0X2A");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#b]}", 42 * isq::length[m]) == "0b101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#B]}", 42 * isq::length[m]) == "0B101010");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#o]}", 42 * isq::length[m]) == "052");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#x]}", 42 * isq::length[m]) == "0x2a");
|
||||
CHECK(MP_UNITS_STD_FMT::format("{:%N:N[#X]}", 42 * isq::length[m]) == "0X2A");
|
||||
}
|
||||
}
|
||||
|
||||
@ -887,10 +1006,25 @@ TEST_CASE("localization with the 'L' specifier", "[text][fmt][localization]")
|
||||
std::locale grp2{std::locale::classic(), new group2};
|
||||
std::locale grp3{std::locale::classic(), new group3};
|
||||
|
||||
SECTION("full format {:{%N:L}%?%U} on a quantity")
|
||||
SECTION("full format on a quantity")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp2, "{:{%N:L}%?%U}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s");
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp3, "{:{%N:L}%?%U}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||
SECTION("default spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp2, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s");
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp3, "{::N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||
}
|
||||
|
||||
SECTION("explicit spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58 m/s");
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%?%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458 m/s");
|
||||
}
|
||||
|
||||
SECTION("modified spec")
|
||||
{
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp2, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "2_99_79_24_58m/s");
|
||||
CHECK(MP_UNITS_STD_FMT::format(grp3, "{:%N%U:N[L]}", 299'792'458 * isq::speed[m / s]) == "299'792'458m/s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user