mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-05 13:14:29 +02:00
added ASCII character validation; added ASCII-only superscripts, scientific notation, dot product
This commit is contained in:
committed by
Mateusz Pusz
parent
c610b04904
commit
e0263c554d
@@ -45,7 +45,7 @@ constexpr auto operator_text()
|
||||
return basic_fixed_string("/");
|
||||
}
|
||||
else {
|
||||
return basic_fixed_string("⋅");
|
||||
return basic_symbol_text("⋅", ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
src/include/units/bits/external/text_tools.h
vendored
27
src/include/units/bits/external/text_tools.h
vendored
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/fixed_string.h>
|
||||
#include <units/symbol_text.h>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
@@ -41,26 +42,34 @@ template<> inline constexpr basic_fixed_string superscript_number<7> = "\u2077";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<8> = "\u2078";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<9> = "\u2079";
|
||||
|
||||
inline constexpr basic_fixed_string superscript_minus = "\u207b";
|
||||
inline constexpr basic_symbol_text superscript_minus("\u207b", "-");
|
||||
|
||||
inline constexpr basic_symbol_text superscript_prefix("", "^");
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto superscript_helper()
|
||||
{
|
||||
if constexpr(Value < 0)
|
||||
return superscript_minus + superscript_helper<-Value>();
|
||||
else if constexpr(Value < 10)
|
||||
return basic_symbol_text(superscript_number<Value>, basic_fixed_string(static_cast<char>('0' + Value)));
|
||||
else
|
||||
return superscript_helper<Value / 10>() + superscript_helper<Value % 10>();
|
||||
}
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto superscript()
|
||||
{
|
||||
if constexpr(Value < 0)
|
||||
return superscript_minus + superscript<-Value>();
|
||||
else if constexpr(Value < 10)
|
||||
return superscript_number<Value>;
|
||||
else
|
||||
return superscript<Value / 10>() + superscript<Value % 10>();
|
||||
return superscript_prefix + superscript_helper<Value>();
|
||||
}
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto regular()
|
||||
{
|
||||
if constexpr (Value < 0)
|
||||
return basic_fixed_string("-") + superscript<-Value>();
|
||||
return basic_fixed_string("-") + superscript_helper<-Value>();
|
||||
else if constexpr (Value < 10)
|
||||
return basic_fixed_string(static_cast<char>('0' + Value));
|
||||
return basic_symbol_text(static_cast<char>('0' + Value));
|
||||
else
|
||||
return regular<Value / 10>() + regular<Value % 10>();
|
||||
}
|
||||
|
@@ -30,11 +30,13 @@
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
inline constexpr basic_symbol_text base_multiplier("\u00D7 10", "x 10");
|
||||
|
||||
template<typename Ratio>
|
||||
constexpr auto ratio_text()
|
||||
{
|
||||
if constexpr(Ratio::num == 1 && Ratio::den == 1 && Ratio::exp != 0) {
|
||||
return basic_fixed_string("\u00D7 10") + superscript<Ratio::exp>() + basic_fixed_string(" ");
|
||||
return base_multiplier + superscript<Ratio::exp>() + basic_fixed_string(" ");
|
||||
}
|
||||
else if constexpr(Ratio::num != 1 || Ratio::den != 1 || Ratio::exp != 0) {
|
||||
auto txt = basic_fixed_string("[") + regular<Ratio::num>();
|
||||
@@ -43,7 +45,7 @@ constexpr auto ratio_text()
|
||||
return txt + basic_fixed_string("] ");
|
||||
}
|
||||
else {
|
||||
return txt + basic_fixed_string(" \u00D7 10") + superscript<Ratio::exp>() +
|
||||
return txt + " " + base_multiplier + superscript<Ratio::exp>() +
|
||||
basic_fixed_string("] ");
|
||||
}
|
||||
}
|
||||
@@ -54,7 +56,7 @@ constexpr auto ratio_text()
|
||||
}
|
||||
else {
|
||||
return txt + basic_fixed_string("/") + regular<Ratio::den>() +
|
||||
basic_fixed_string(" \u00D7 10") + superscript<Ratio::exp>() +
|
||||
" " + base_multiplier + superscript<Ratio::exp>() +
|
||||
basic_fixed_string("] ");
|
||||
}
|
||||
}
|
||||
|
@@ -10,12 +10,21 @@ struct basic_symbol_text {
|
||||
basic_fixed_string<StandardCharT, N> standard_;
|
||||
basic_fixed_string<char, M> ascii_;
|
||||
|
||||
constexpr basic_symbol_text(StandardCharT s) noexcept: standard_(s), ascii_(s) {}
|
||||
constexpr basic_symbol_text(StandardCharT s, char a) noexcept: standard_(s), ascii_(a) {}
|
||||
constexpr basic_symbol_text(const StandardCharT (&s)[N + 1]) noexcept: standard_(s), ascii_(s) {}
|
||||
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& s) noexcept: standard_(s), ascii_(s) {}
|
||||
constexpr basic_symbol_text(const StandardCharT (&s)[N + 1], const StandardCharT (&a)[M + 1]) noexcept: standard_(s), ascii_(a) {}
|
||||
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& s, const basic_fixed_string<char, M>& a) noexcept: standard_(s), ascii_(a) {}
|
||||
constexpr void validate_ascii_char(char c) noexcept { assert((c & 0x80) == 0); }
|
||||
|
||||
template<std::size_t P>
|
||||
constexpr void validate_ascii_string(const char (&s)[P + 1]) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < P; ++i)
|
||||
validate_ascii_char(s[i]);
|
||||
}
|
||||
|
||||
constexpr basic_symbol_text(StandardCharT s) noexcept: standard_(s), ascii_(s) { validate_ascii_char(s); }
|
||||
constexpr basic_symbol_text(StandardCharT s, char a) noexcept: standard_(s), ascii_(a) { validate_ascii_char(a); }
|
||||
constexpr basic_symbol_text(const StandardCharT (&s)[N + 1]) noexcept: standard_(s), ascii_(s) { validate_ascii_string<N>(s); }
|
||||
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& s) noexcept: standard_(s), ascii_(s) { validate_ascii_string<N>(s.data_); }
|
||||
constexpr basic_symbol_text(const StandardCharT (&s)[N + 1], const char (&a)[M + 1]) noexcept: standard_(s), ascii_(a) { validate_ascii_string<M>(a); }
|
||||
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& s, const basic_fixed_string<char, M>& a) noexcept: standard_(s), ascii_(a) { validate_ascii_string<M>(a.data_); }
|
||||
|
||||
[[nodiscard]] constexpr auto& standard() { return standard_; }
|
||||
[[nodiscard]] constexpr const auto& standard() const { return standard_; }
|
||||
|
@@ -56,6 +56,8 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
CHECK(fmt::format("{}", 1q_ns) == "1 ns");
|
||||
CHECK(fmt::format("{}", 1q_us) == "1 µs");
|
||||
CHECK(fmt::format("{}", 1q_ms) == "1 ms");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_us) == "1 us");
|
||||
}
|
||||
|
||||
SECTION("length")
|
||||
@@ -98,11 +100,18 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
CHECK(fmt::format("{}", 1q_cm2) == "1 cm²");
|
||||
CHECK(fmt::format("{}", 1q_km2) == "1 km²");
|
||||
CHECK(fmt::format("{}", 1q_ft2) == "1 ft²");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_m2) == "1 m^2");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_mm2) == "1 mm^2");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_cm2) == "1 cm^2");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_km2) == "1 km^2");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_ft2) == "1 ft^2");
|
||||
}
|
||||
|
||||
SECTION("density")
|
||||
{
|
||||
CHECK(fmt::format("{}", 1q_kg_per_m3) == "1 kg/m³");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_kg_per_m3) == "1 kg/m^3");
|
||||
}
|
||||
|
||||
SECTION("resistance")
|
||||
@@ -111,6 +120,11 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
CHECK(fmt::format("{}", 1q_kR) == "1 kΩ");
|
||||
CHECK(fmt::format("{}", 1q_mR) == "1 mΩ");
|
||||
CHECK(fmt::format("{}", 1q_MR) == "1 MΩ");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_R) == "1 ohm");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_kR) == "1 kohm");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_mR) == "1 mohm");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_MR) == "1 Mohm");
|
||||
}
|
||||
|
||||
SECTION("voltage")
|
||||
@@ -120,6 +134,8 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
CHECK(fmt::format("{}", 1q_uV) == "1 µV");
|
||||
CHECK(fmt::format("{}", 1q_nV) == "1 nV");
|
||||
CHECK(fmt::format("{}", 1q_pV) == "1 pV");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_uV) == "1 uV");
|
||||
}
|
||||
|
||||
SECTION("volume")
|
||||
@@ -129,6 +145,12 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
CHECK(fmt::format("{}", 1q_cm3) == "1 cm³");
|
||||
CHECK(fmt::format("{}", 1q_km3) == "1 km³");
|
||||
CHECK(fmt::format("{}", 1q_ft3) == "1 ft³");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_m3) == "1 m^3");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_mm3) == "1 mm^3");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_cm3) == "1 cm^3");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_km3) == "1 km^3");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_ft3) == "1 ft^3");
|
||||
}
|
||||
|
||||
SECTION("frequency")
|
||||
@@ -150,11 +172,13 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
SECTION("acceleration")
|
||||
{
|
||||
CHECK(fmt::format("{}", 1q_m_per_s2) == "1 m/s²");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_m_per_s2) == "1 m/s^2");
|
||||
}
|
||||
|
||||
SECTION("momentum")
|
||||
{
|
||||
CHECK(fmt::format("{}", 1q_kg_m_per_s) == "1 kg⋅m/s");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_kg_m_per_s) == "1 kg.m/s");
|
||||
}
|
||||
|
||||
SECTION("energy")
|
||||
@@ -187,10 +211,14 @@ TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]")
|
||||
{
|
||||
CHECK(fmt::format("{}", 1q_mi * 1q_mi * 1q_mi) == "1 [15900351812136/3814697265625 × 10⁹] m³");
|
||||
CHECK(fmt::format("{}", 1q_au * 1q_au) == "1 [2237952291797391849 × 10⁴] m²");
|
||||
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_mi * 1q_mi * 1q_mi) == "1 [15900351812136/3814697265625 x 10^9] m^3");
|
||||
CHECK(fmt::format("{:%Q %Aq}", 1q_au * 1q_au) == "1 [2237952291797391849 x 10^4] m^2");
|
||||
}
|
||||
|
||||
SECTION("unknown scaled unit with reference different than the dimension's coherent unit")
|
||||
{
|
||||
CHECK(fmt::format("{}", mass<units::scaled_unit<units::ratio<2, 3>, gram>>(1)) == "1 [2/3 × 10⁻³] kg");
|
||||
CHECK(fmt::format("{:%Q %Aq}", mass<units::scaled_unit<units::ratio<2, 3>, gram>>(1)) == "1 [2/3 x 10^-3] kg");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user