...
This commit is contained in:
parent
31c885ba02
commit
61afd0f4a7
@ -13,4 +13,5 @@ set(COMM_PROTO_LIB_SRC comm_proto.h comm_proto.cpp)
|
||||
set(COMM_PROTO_LIB comm_proto)
|
||||
add_library(${COMM_PROTO_LIB} STATIC ${COMM_PROTO_LIB_SRC}
|
||||
control_proto.h
|
||||
control_proto.cpp)
|
||||
control_proto.cpp
|
||||
utils.h)
|
||||
|
||||
137
cxx/utils.h
Normal file
137
cxx/utils.h
Normal file
@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <ranges>
|
||||
#include <regex>
|
||||
|
||||
namespace mcc::utils
|
||||
{
|
||||
|
||||
static const std::regex decimalNumberRx{" *[-+]?([0-9]*[.])?[0-9]+([eE][-+]?[0-9]+)? *"};
|
||||
static const std::regex sexagesimalReprRx{" *[-+]?[0-9]{1,2}:[0-9]{1,2}:([0-9]{0,2}[.])?[0-9]+ *"};
|
||||
|
||||
enum class TrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
||||
|
||||
template <std::ranges::contiguous_range R>
|
||||
static std::string_view trimSpaces(R&& r, TrimType type = TrimType::TRIM_BOTH)
|
||||
requires std::same_as<char, std::remove_cvref_t<std::ranges::range_value_t<R>>>
|
||||
{
|
||||
auto is_space = [](const auto& ch) { return ch == ' '; };
|
||||
|
||||
auto end = std::forward<R>(r).end();
|
||||
|
||||
auto f1 = std::forward<R>(r).begin();
|
||||
|
||||
if (type != TrimType::TRIM_RIGHT) {
|
||||
// look for the first non-space symbol
|
||||
f1 = std::ranges::find_if_not(std::forward<R>(r), is_space);
|
||||
if (f1 == end) { // all are spaces!
|
||||
return std::string_view();
|
||||
}
|
||||
}
|
||||
|
||||
auto f2 = end;
|
||||
|
||||
if (type != TrimType::TRIM_LEFT) {
|
||||
auto f3 = f1;
|
||||
|
||||
do {
|
||||
f2 = std::ranges::find_if(++f3, end, is_space);
|
||||
if (f2 == end)
|
||||
break;
|
||||
f3 = std::ranges::find_if_not(f2 + 1, end, is_space);
|
||||
} while (f3 != end);
|
||||
}
|
||||
|
||||
return std::string_view(f1, f2);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::ranges::contiguous_range R>
|
||||
std::optional<T> numFromStr(R&& r)
|
||||
requires((std::integral<T> || std::floating_point<T>) &&
|
||||
std::same_as<char, std::remove_cvref_t<std::ranges::range_value_t<R>>>)
|
||||
{
|
||||
T val;
|
||||
const char* end_ptr = &*r.end();
|
||||
|
||||
if constexpr (std::integral<T>) {
|
||||
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val);
|
||||
if (cvt_res.ec != std::errc()) {
|
||||
return std::nullopt;
|
||||
} else if (cvt_res.ptr != end_ptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
#ifdef _LIBCPP_VERSION // clang's libc++ does not have floating-point overloads for std::from_chars
|
||||
std::string s{str.begin(), str.end()};
|
||||
size_t pos;
|
||||
|
||||
try {
|
||||
if constexpr (std::same_as<T, float>) {
|
||||
val = std::stof(s, &pos);
|
||||
} else if constexpr (std::same_as<T, double>) {
|
||||
val = std::stod(s, &pos);
|
||||
} else {
|
||||
val = std::stold(s, &pos);
|
||||
}
|
||||
} catch (...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (pos != s.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
#else
|
||||
auto cvt_res = std::from_chars(&*r.begin(), &*r.end(), val);
|
||||
|
||||
if (cvt_res.ec != std::errc()) {
|
||||
return std::nullopt;
|
||||
} else if (cvt_res.ptr != end_ptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template <std::ranges::contiguous_range R>
|
||||
static std::optional<double> parsAngleString(R&& r, bool hms = false)
|
||||
requires std::same_as<char, std::remove_cvref_t<std::ranges::range_value_t<R>>>
|
||||
{
|
||||
auto str = trimSpaces(std::forward<R>(r));
|
||||
|
||||
bool ok = std::regex_match(str.begin(), str.end(), decimalNumberRx);
|
||||
|
||||
if (ok) {
|
||||
return numFromStr<double>(str);
|
||||
}
|
||||
|
||||
ok = std::regex_match(str.begin(), str.end(), sexagesimalReprRx);
|
||||
|
||||
if (ok) {
|
||||
auto str = trimSpaces(std::forward<R>(r));
|
||||
auto parts = std::views::split(str, ":");
|
||||
|
||||
double val;
|
||||
|
||||
double p1 = numFromStr<double>(parts[0]);
|
||||
val = std::abs(p1);
|
||||
val += numFromStr<double>(parts[1]) / 60.0;
|
||||
val += numFromStr<double>(parts[2]) / 3600.0;
|
||||
if (p1 < 0) {
|
||||
val = -val;
|
||||
}
|
||||
|
||||
if (hms) {
|
||||
val *= 15.0;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace mcc::utils
|
||||
Loading…
x
Reference in New Issue
Block a user