13 template<arithmetic_c T, unit_enum_c unit_t>
14 convert(T, unit_t) -> convert<T, unit_t>;
16 template<arithmetic_c T, unit_enum_c unit_t>
17 convert(unit<T, unit_t>) -> convert<T, unit_t>;
19 namespace units::details
22 template<arithmetic_c T, unit_enum_c unit_t>
33 template<unit_enum_c unit_t,
class char_t>
36 template<
class format_context_type_t>
37 constexpr
auto format(unit_t eData, format_context_type_t& ctx)
const noexcept;
44 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
45 struct std::formatter<qx::unit<T, unit_t>, char_t>
47 template<
class format_parse_context_t>
48 constexpr
auto parse(format_parse_context_t& context) noexcept;
50 template<
class format_context_type_t>
51 constexpr
auto format(
const qx::unit<T, unit_t>& unit, format_context_type_t& ctx)
const noexcept;
54 std::formatter<T, char_t> valueFormatter;
57 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
63 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
66 if (type != other.type)
69 if constexpr (std::is_floating_point_v<T>)
70 return float_compare(value, other.value);
72 return value == other.value;
75 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
80 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
82 : m_From({ value, eFrom })
86 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
89 return units::traits<unit_t>::template normalize<T>(unit);
92 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
98 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
99 std::optional<qx::unit<T, unit_t>>
qx::unit_from_string(basic_string_view<char_t> svValue) noexcept
101 auto remove_suffix = [](basic_string_view<char_t> svValue,
102 auto predicate) -> std::optional<basic_string_view<char_t>>
104 size_t nToErase = predicate(svValue);
108 svValue.remove_suffix(nToErase);
112 auto trim_right = [&remove_suffix](basic_string_view<char_t> svValue)
114 while (std::optional<basic_string_view<char_t>> svErased = remove_suffix(
116 [](basic_string_view<char_t> svValue)
119 while (string_traits::traits<char_t>::is_space(svValue[nToErase]))
133 svValue = trim_right(svValue);
135 const auto& suffixes = units::traits<unit_t>::template get_suffixes<char_t>();
136 auto itSuffix = suffixes.begin();
137 std::optional<unit_t> optUnitType;
138 std::optional<T> optValue;
139 while ((!optUnitType || !optValue) && itSuffix != suffixes.end())
141 auto optValueCandidate = remove_suffix(
143 [&optUnitType, &itSuffix, &suffixes](basic_string_view<char_t> svValue) ->
size_t
145 itSuffix = std::find_if(
148 [svValue](
const std::pair<unit_t, basic_string_view<char_t>>& suffix)
150 return svValue.ends_with(suffix.second);
153 if (itSuffix != suffixes.end())
155 optUnitType = itSuffix->first;
156 return itSuffix->second.size();
167 if (!optValueCandidate)
170 *optValueCandidate = trim_right(*optValueCandidate);
173 basic_string<char_t> sValue = *optValueCandidate;
174 optValue = sValue.template to<T>();
178 if (!optValue || !optUnitType)
181 return unit(*optValue, *optUnitType);
184 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
187 return unit_from_string<T, unit_t, char_t>(basic_string_view<char_t>(pszValue));
191 template<qx::unit_enum_c unit_t,
class char_t>
192 constexpr std::optional<qx::basic_string_view<char_t>>
qx::get_unit_suffix(unit_t eUnit) noexcept
194 const auto& suffixes = units::traits<unit_t>::template get_suffixes<char_t>();
195 auto itSuffix = std::ranges::find_if(
197 [eUnit](
const std::pair<unit_t, basic_string_view<char_t>>& pair)
199 return pair.first == eUnit;
201 if (itSuffix != suffixes.end())
202 return itSuffix->second;
207 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
208 template<
class format_parse_context_t>
209 constexpr
auto std::formatter<qx::unit<T, unit_t>, char_t>::parse(format_parse_context_t& context) noexcept
211 return valueFormatter.parse(context);
215 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
216 template<
class format_context_type_t>
217 constexpr
auto std::formatter<qx::unit<T, unit_t>, char_t>::format(
219 format_context_type_t& ctx)
const noexcept
221 auto outIt = valueFormatter.format(unit.value, ctx);
222 return std::format_to(outIt,
QX_STR_PREFIX(char_t,
"{}"), unit.type);
225 template<qx::unit_enum_c unit_t,
class char_t>
226 template<
class format_context_type_t>
230 auto out = ctx.out();
232 if (std::optional<basic_string_view<char_t>> optSuffix = get_unit_suffix<unit_t, char_t>(eUnit))
233 out = std::format_to(out,
QX_STR_PREFIX(char_t,
"{}"), *optSuffix);
constexpr unit< T, unit_t > normalize_unit(unit< T, unit_t > unit) noexcept
The function returns the closest value greater than one from the SI for the unit of measurement.
std::optional< unit< T, unit_t > > unit_from_string(basic_string_view< char_t > svValue) noexcept
Creates a unit from a string.
constexpr std::optional< basic_string_view< char_t > > get_unit_suffix(unit_t eUnit) noexcept
Get a unit suffix if exists.
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.