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 -> decltype(ctx.out());
44 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
45 struct QX_FMT_NS::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
52 -> decltype(ctx.out());
55 QX_FMT_NS::formatter<T, char_t> m_ValueFormatter;
58 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
64 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
67 if (type != other.type)
70 if constexpr (std::is_floating_point_v<T>)
71 return float_compare(value, other.value);
73 return value == other.value;
76 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
81 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
83 : m_From({ value, eFrom })
87 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
90 return units::traits<unit_t>::template normalize<T>(unit);
93 template<qx::arithmetic_c T, qx::unit_enum_c unit_t>
99 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
100 std::optional<qx::unit<T, unit_t>>
qx::unit_from_string(basic_string_view<char_t> svValue) noexcept
102 auto remove_suffix = [](basic_string_view<char_t> svValue,
103 auto predicate) -> std::optional<basic_string_view<char_t>>
105 size_t nToErase = predicate(svValue);
109 svValue.remove_suffix(nToErase);
113 auto trim_right = [&remove_suffix](basic_string_view<char_t> svValue)
115 while (std::optional<basic_string_view<char_t>> svErased = remove_suffix(
117 [](basic_string_view<char_t> svValue)
120 while (string_traits::default_traits<char_t>::is_space(svValue[nToErase]))
134 svValue = trim_right(svValue);
136 const auto& suffixes = units::traits<unit_t>::template get_suffixes<char_t>();
137 auto itSuffix = suffixes.begin();
138 std::optional<unit_t> optUnitType;
139 std::optional<T> optValue;
140 while ((!optUnitType || !optValue) && itSuffix != suffixes.end())
142 auto optValueCandidate = remove_suffix(
144 [&optUnitType, &itSuffix, &suffixes](basic_string_view<char_t> svValue) ->
size_t
146 itSuffix = std::find_if(
149 [svValue](
const std::pair<unit_t, basic_string_view<char_t>>& suffix)
151 return svValue.ends_with(suffix.second);
154 if (itSuffix != suffixes.end())
156 optUnitType = itSuffix->first;
157 return itSuffix->second.size();
168 if (!optValueCandidate)
171 *optValueCandidate = trim_right(*optValueCandidate);
174 basic_string<char_t> sValue = *optValueCandidate;
175 optValue = sValue.template to<T>();
179 if (!optValue || !optUnitType)
182 return unit(*optValue, *optUnitType);
185 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
188 return unit_from_string<T, unit_t, char_t>(basic_string_view<char_t>(pszValue));
192 template<qx::unit_enum_c unit_t,
class char_t>
193 constexpr std::optional<qx::basic_string_view<char_t>>
qx::get_unit_suffix(unit_t eUnit) noexcept
195 const auto& suffixes = units::traits<unit_t>::template get_suffixes<char_t>();
196 auto itSuffix = std::ranges::find_if(
198 [eUnit](
const std::pair<unit_t, basic_string_view<char_t>>& pair)
200 return pair.first == eUnit;
202 if (itSuffix != suffixes.end())
203 return itSuffix->second;
208 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
209 template<
class format_parse_context_t>
210 constexpr
auto QX_FMT_NS::formatter<qx::unit<T, unit_t>, char_t>::parse(format_parse_context_t& context) noexcept
212 return m_ValueFormatter.parse(context);
216 template<qx::arithmetic_c T, qx::unit_enum_c unit_t,
class char_t>
217 template<
class format_context_type_t>
218 constexpr
auto QX_FMT_NS::formatter<qx::unit<T, unit_t>, char_t>::format(
220 format_context_type_t& ctx)
const noexcept -> decltype(ctx.out())
222 auto outIt = m_ValueFormatter.format(unit.value, ctx);
223 return QX_FMT_NS::format_to(outIt,
QX_STR_PREFIX(char_t,
"{}"), unit.type);
226 template<qx::unit_enum_c unit_t,
class char_t>
227 template<
class format_context_type_t>
229 const noexcept -> decltype(ctx.out())
231 auto out = ctx.out();
233 if (std::optional<basic_string_view<char_t>> optSuffix = get_unit_suffix<unit_t, char_t>(eUnit))
234 out = QX_FMT_NS::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.