Compare commits
21 Commits
537207cd16
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| cd97ed875f | |||
| b3c7584205 | |||
| 5984bc5204 | |||
| d865e51ffb | |||
| 6e6f230f4d | |||
| a1f17f0d76 | |||
| e1a136a839 | |||
| 3497850e1f | |||
| e9c329d88f | |||
| 445a029a2f | |||
| 8e5e3631ba | |||
| 304464dbda | |||
| 4b5a390987 | |||
| 47ba7342e7 | |||
| c5f17b7403 | |||
| 8d36444c51 | |||
| d40ecb5df7 | |||
| d8130cede2 | |||
| 056c152d49 | |||
|
|
9630751a4d | ||
| 3dbe4c12b7 |
@@ -355,6 +355,9 @@ if(BUILD_TESTS)
|
|||||||
|
|
||||||
add_executable(mcc_pcm_z1000_test tests/mcc_pcm_z1000_test.cpp)
|
add_executable(mcc_pcm_z1000_test tests/mcc_pcm_z1000_test.cpp)
|
||||||
target_link_libraries(mcc_pcm_z1000_test PRIVATE ${PROJECT_NAME})
|
target_link_libraries(mcc_pcm_z1000_test PRIVATE ${PROJECT_NAME})
|
||||||
|
|
||||||
|
add_executable(mcc_keyvalue_test tests/mcc_keyvalue_test.cpp)
|
||||||
|
target_link_libraries(mcc_keyvalue_test PRIVATE ${PROJECT_NAME})
|
||||||
else()
|
else()
|
||||||
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
||||||
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ include(FortranCInterface)
|
|||||||
FortranCInterface_HEADER(
|
FortranCInterface_HEADER(
|
||||||
FortranCInterface.h
|
FortranCInterface.h
|
||||||
MACRO_NAMESPACE "FC_"
|
MACRO_NAMESPACE "FC_"
|
||||||
# SYMBOL_NAMESPACE "fp_"
|
SYMBOL_NAMESPACE "fitpack_"
|
||||||
SYMBOL_NAMESPACE ""
|
#SYMBOL_NAMESPACE ""
|
||||||
# SYMBOLS ${func_str}
|
# SYMBOLS ${func_str}
|
||||||
SYMBOLS ${func_name}
|
SYMBOLS ${func_name}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,139 +8,147 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* fitting on XY-grid */
|
/* fitting on XY-grid */
|
||||||
void surfit(int* iopt,
|
void fitpack_surfit(int* iopt,
|
||||||
int* m,
|
// void surfit(int* iopt,
|
||||||
double* x,
|
int* m,
|
||||||
double* y,
|
double* x,
|
||||||
double* z,
|
double* y,
|
||||||
double* w,
|
double* z,
|
||||||
double* xb,
|
double* w,
|
||||||
double* xe,
|
double* xb,
|
||||||
double* yb,
|
double* xe,
|
||||||
double* ye,
|
double* yb,
|
||||||
int* kx,
|
double* ye,
|
||||||
int* ky,
|
int* kx,
|
||||||
double* s,
|
int* ky,
|
||||||
int* nxest,
|
double* s,
|
||||||
int* nyest,
|
int* nxest,
|
||||||
int* nmax,
|
int* nyest,
|
||||||
double* eps,
|
int* nmax,
|
||||||
int* nx,
|
double* eps,
|
||||||
double* tx,
|
int* nx,
|
||||||
int* ny,
|
double* tx,
|
||||||
double* ty,
|
int* ny,
|
||||||
double* c,
|
double* ty,
|
||||||
double* fp,
|
double* c,
|
||||||
double* wrk1,
|
double* fp,
|
||||||
int* lwrk1,
|
double* wrk1,
|
||||||
double* wrk2,
|
int* lwrk1,
|
||||||
int* lwrk2,
|
double* wrk2,
|
||||||
int* iwrk,
|
int* lwrk2,
|
||||||
int* kwrk,
|
int* iwrk,
|
||||||
int* ier);
|
int* kwrk,
|
||||||
|
int* ier);
|
||||||
|
|
||||||
/* XY-grid */
|
/* XY-grid */
|
||||||
void bispev(double* tx,
|
void fitpack_bispev(double* tx,
|
||||||
int* nx,
|
// void bispev(double* tx,
|
||||||
double* ty,
|
int* nx,
|
||||||
int* ny,
|
double* ty,
|
||||||
double* c,
|
int* ny,
|
||||||
int* kx,
|
double* c,
|
||||||
int* ky,
|
int* kx,
|
||||||
double* x,
|
int* ky,
|
||||||
int* mx,
|
double* x,
|
||||||
double* y,
|
int* mx,
|
||||||
int* my,
|
double* y,
|
||||||
double* z,
|
int* my,
|
||||||
double* wrk,
|
double* z,
|
||||||
int* lwrk,
|
double* wrk,
|
||||||
int* iwrk,
|
int* lwrk,
|
||||||
int* kwrk,
|
int* iwrk,
|
||||||
int* ier);
|
int* kwrk,
|
||||||
|
int* ier);
|
||||||
|
|
||||||
/* XY-grid */
|
/* XY-grid */
|
||||||
void parder(double* tx,
|
void fitpack_parder(double* tx,
|
||||||
int* nx,
|
// void parder(double* tx,
|
||||||
double* ty,
|
int* nx,
|
||||||
int* ny,
|
double* ty,
|
||||||
double* c,
|
int* ny,
|
||||||
int* kx,
|
double* c,
|
||||||
int* ky,
|
int* kx,
|
||||||
int* nux,
|
int* ky,
|
||||||
int* nuy,
|
int* nux,
|
||||||
double* x,
|
int* nuy,
|
||||||
int* mx,
|
double* x,
|
||||||
double* y,
|
int* mx,
|
||||||
int* my,
|
double* y,
|
||||||
double* z,
|
int* my,
|
||||||
double* wrk,
|
double* z,
|
||||||
int* lwrk,
|
double* wrk,
|
||||||
int* iwrk,
|
int* lwrk,
|
||||||
int* kwrk,
|
int* iwrk,
|
||||||
int* ier);
|
int* kwrk,
|
||||||
|
int* ier);
|
||||||
|
|
||||||
/* fitting on sphere */
|
/* fitting on sphere */
|
||||||
void sphere(int* iopt,
|
void fitpack_sphere(int* iopt,
|
||||||
int* m,
|
// void sphere(int* iopt,
|
||||||
double* teta,
|
int* m,
|
||||||
double* phi,
|
double* teta,
|
||||||
double* r,
|
double* phi,
|
||||||
double* w,
|
double* r,
|
||||||
double* s,
|
double* w,
|
||||||
int* ntest,
|
double* s,
|
||||||
int* npest,
|
int* ntest,
|
||||||
double* eps,
|
int* npest,
|
||||||
int* nt,
|
double* eps,
|
||||||
double* tt,
|
int* nt,
|
||||||
int* np,
|
double* tt,
|
||||||
double* tp,
|
int* np,
|
||||||
double* c,
|
double* tp,
|
||||||
double* fp,
|
double* c,
|
||||||
double* wrk1,
|
double* fp,
|
||||||
int* lwrk1,
|
double* wrk1,
|
||||||
double* wrk2,
|
int* lwrk1,
|
||||||
int* lwrk2,
|
double* wrk2,
|
||||||
int* iwrk,
|
int* lwrk2,
|
||||||
int* kwrk,
|
int* iwrk,
|
||||||
int* ier);
|
int* kwrk,
|
||||||
|
int* ier);
|
||||||
|
|
||||||
/* calculation for set of points (not grid) */
|
/* calculation for set of points (not grid) */
|
||||||
void bispeu(double* tx,
|
void fitpack_bispeu(double* tx,
|
||||||
int* nx,
|
// void bispeu(double* tx,
|
||||||
double* ty,
|
int* nx,
|
||||||
int* ny,
|
double* ty,
|
||||||
double* c,
|
int* ny,
|
||||||
int* kx,
|
double* c,
|
||||||
int* ky,
|
int* kx,
|
||||||
double* x,
|
int* ky,
|
||||||
double* y,
|
double* x,
|
||||||
double* z,
|
double* y,
|
||||||
int* m,
|
double* z,
|
||||||
double* wrk,
|
int* m,
|
||||||
int* lwrk,
|
double* wrk,
|
||||||
int* ier);
|
int* lwrk,
|
||||||
|
int* ier);
|
||||||
|
|
||||||
|
|
||||||
/* calculation for set of points (not grid) */
|
/* calculation for set of points (not grid) */
|
||||||
void pardeu(double* tx,
|
void fitpack_pardeu(double* tx,
|
||||||
int* nx,
|
// void pardeu(double* tx,
|
||||||
double* ty,
|
int* nx,
|
||||||
int* ny,
|
double* ty,
|
||||||
double* c,
|
int* ny,
|
||||||
int* kx,
|
double* c,
|
||||||
int* ky,
|
int* kx,
|
||||||
int* nux,
|
int* ky,
|
||||||
int* nuy,
|
int* nux,
|
||||||
double* x,
|
int* nuy,
|
||||||
double* y,
|
double* x,
|
||||||
double* z,
|
double* y,
|
||||||
int* m,
|
double* z,
|
||||||
double* wrk,
|
int* m,
|
||||||
int* lwrk,
|
double* wrk,
|
||||||
int* iwrk,
|
int* lwrk,
|
||||||
int* kwrk,
|
int* iwrk,
|
||||||
int* ier);
|
int* kwrk,
|
||||||
|
int* ier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -257,23 +265,15 @@ int fitpack_sphere_smooth(const TethaT& tetha,
|
|||||||
if constexpr (std::ranges::contiguous_range<WeightT>) {
|
if constexpr (std::ranges::contiguous_range<WeightT>) {
|
||||||
auto weight_ptr = const_cast<double*>(std::ranges::data(weight));
|
auto weight_ptr = const_cast<double*>(std::ranges::data(weight));
|
||||||
|
|
||||||
sphere(&iopt, &m, tetha_ptr, phi_ptr, func_ptr, weight_ptr, &s_par, &nt, &np, &eps, &ntest, tetha_knots_ptr,
|
fitpack_sphere(&iopt, &m, tetha_ptr, phi_ptr, func_ptr, weight_ptr, &s_par, &nt, &np, &eps, &ntest,
|
||||||
&npest, phi_knots_ptr, std::ranges::data(coeffs), &resi2_sum, wrk1.data(), &lwrk1, wrk2.data(), &lwrk2,
|
tetha_knots_ptr, &npest, phi_knots_ptr, std::ranges::data(coeffs), &resi2_sum, wrk1.data(),
|
||||||
iwrk.data(), &kwrk, &res);
|
&lwrk1, wrk2.data(), &lwrk2, iwrk.data(), &kwrk, &res);
|
||||||
// sphere(&iopt, &m, std::ranges::data(tetha), std::ranges::data(phi), std::ranges::data(func),
|
|
||||||
// std::ranges::data(weight), &s_par, &ntest, &npest, &eps, &ntest, std::ranges::data(tetha_knots),
|
|
||||||
// &npest, std::ranges::data(phi_knots), std::ranges::data(coeffs), &resi2_sum, wrk1.data(), &lwrk1,
|
|
||||||
// wrk2.data(), &lwrk2, iwrk.data(), &kwrk, &res);
|
|
||||||
} else {
|
} else {
|
||||||
std::vector<double> weight_vec(m, weight);
|
std::vector<double> weight_vec(m, weight);
|
||||||
|
|
||||||
sphere(&iopt, &m, tetha_ptr, phi_ptr, func_ptr, weight_vec.data(), &s_par, &nt, &np, &eps, &ntest,
|
fitpack_sphere(&iopt, &m, tetha_ptr, phi_ptr, func_ptr, weight_vec.data(), &s_par, &nt, &np, &eps, &ntest,
|
||||||
tetha_knots_ptr, &npest, phi_knots_ptr, std::ranges::data(coeffs), &resi2_sum, wrk1.data(), &lwrk1,
|
tetha_knots_ptr, &npest, phi_knots_ptr, std::ranges::data(coeffs), &resi2_sum, wrk1.data(),
|
||||||
wrk2.data(), &lwrk2, iwrk.data(), &kwrk, &res);
|
&lwrk1, wrk2.data(), &lwrk2, iwrk.data(), &kwrk, &res);
|
||||||
// res = sphere(&iopt, &m, std::ranges::data(tetha), std::ranges::data(phi), std::ranges::data(func),
|
|
||||||
// weight_vec.data(), &s_par, &ntest, &npest, &eps, &ntest, std::ranges::data(tetha_knots), &npest,
|
|
||||||
// std::ranges::data(phi_knots), std::ranges::data(coeffs), &resi2_sum, wrk1.get(), &lwrk1,
|
|
||||||
// wrk2.get(), &lwrk2, iwrk.get(), &kwrk, &res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -367,8 +367,8 @@ int fitpack_eval_spl2d_grid(const TXT& tx,
|
|||||||
auto x_ptr = const_cast<double*>(std::ranges::data(x));
|
auto x_ptr = const_cast<double*>(std::ranges::data(x));
|
||||||
auto y_ptr = const_cast<double*>(std::ranges::data(y));
|
auto y_ptr = const_cast<double*>(std::ranges::data(y));
|
||||||
|
|
||||||
bispev(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, x_ptr, &mx, y_ptr, &my, std::ranges::data(func),
|
fitpack_bispev(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, x_ptr, &mx, y_ptr, &my, std::ranges::data(func),
|
||||||
wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
||||||
|
|
||||||
return ier;
|
return ier;
|
||||||
}
|
}
|
||||||
@@ -431,8 +431,10 @@ int fitpack_eval_spl2d(const TXT& tx,
|
|||||||
int lwrk = kx + ky + 2;
|
int lwrk = kx + ky + 2;
|
||||||
std::vector<double> wrk(lwrk);
|
std::vector<double> wrk(lwrk);
|
||||||
|
|
||||||
bispeu(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, x_ptr, y_ptr, std::ranges::data(func), &m, wrk.data(),
|
fitpack_bispeu(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, x_ptr, y_ptr, std::ranges::data(func), &m,
|
||||||
&lwrk, &ier);
|
wrk.data(), &lwrk, &ier);
|
||||||
|
// bispeu(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, x_ptr, y_ptr, std::ranges::data(func), &m, wrk.data(),
|
||||||
|
// &lwrk, &ier);
|
||||||
|
|
||||||
return ier;
|
return ier;
|
||||||
}
|
}
|
||||||
@@ -536,8 +538,8 @@ int fitpack_parder_spl2d_grid(const TXT& tx,
|
|||||||
|
|
||||||
int ier = 0;
|
int ier = 0;
|
||||||
|
|
||||||
parder(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, &dx, &dy, x_ptr, &mx, y_ptr, &my, std::ranges::data(pder),
|
fitpack_parder(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, &dx, &dy, x_ptr, &mx, y_ptr, &my,
|
||||||
wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
std::ranges::data(pder), wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
||||||
|
|
||||||
return ier;
|
return ier;
|
||||||
}
|
}
|
||||||
@@ -604,8 +606,8 @@ int fitpack_parder_spl2d(const TXT& tx,
|
|||||||
int kwrk = 2 * m;
|
int kwrk = 2 * m;
|
||||||
std::vector<int> iwrk(kwrk);
|
std::vector<int> iwrk(kwrk);
|
||||||
|
|
||||||
pardeu(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, &dx, &dy, x_ptr, y_ptr, std::ranges::data(pder), &m,
|
fitpack_pardeu(tx_ptr, &ntx, ty_ptr, &nty, coeffs_ptr, &kx, &ky, &dx, &dy, x_ptr, y_ptr, std::ranges::data(pder),
|
||||||
wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
&m, wrk.data(), &lwrk, iwrk.data(), &kwrk, &ier);
|
||||||
|
|
||||||
return ier;
|
return ier;
|
||||||
}
|
}
|
||||||
@@ -645,5 +647,4 @@ int fitpack_parder_spl2d(const TXT& tx,
|
|||||||
return fitpack_parder_spl2d(tx, ty, coeffs, xv, yv, pv, dx, dy, kx, ky);
|
return fitpack_parder_spl2d(tx, ty, coeffs, xv, yv, pv, dx, dy, kx, ky);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace mcc::bsplines
|
} // namespace mcc::bsplines
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -126,19 +126,23 @@ protected:
|
|||||||
return MccDeserializerErrorCode::ERROR_OK;
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r_str = std::views::split(input, params.seq_delim);
|
// auto r_str = std::views::split(input, params.seq_delim);
|
||||||
|
auto r_str = std::views::split(input, params.elem_delim);
|
||||||
VT val;
|
VT val;
|
||||||
|
|
||||||
auto it = r.begin();
|
auto it = r.begin();
|
||||||
for (auto const& el : r_str) {
|
for (auto const& el : r_str) {
|
||||||
auto err = dsr(el, val, std::forward<DeserParamsT>(params)...);
|
// auto err = dsr(el, val, std::forward<DeserParamsT>(params)...);
|
||||||
|
auto err = dsr(el, val, params);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it == r.end()) {
|
if (it == r.end()) {
|
||||||
std::back_inserter(r) = val;
|
if constexpr (!traits::mcc_fixed_size_range<R>) {
|
||||||
it = r.end();
|
std::back_inserter(r) = val;
|
||||||
|
it = r.end();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*it = val;
|
*it = val;
|
||||||
++it;
|
++it;
|
||||||
|
|||||||
@@ -62,6 +62,26 @@ public:
|
|||||||
fromTimePoint(std::forward<decltype(other)>(other).UTC());
|
fromTimePoint(std::forward<decltype(other)>(other).UTC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MccCelestialCoordEpoch(traits::mcc_input_char_range auto&& str)
|
||||||
|
{
|
||||||
|
// ignore possible errors!!!
|
||||||
|
fromCharRange(std::forward<decltype(str)>(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ClockT, typename DurT>
|
||||||
|
MccCelestialCoordEpoch(std::chrono::time_point<ClockT, DurT> const& tp) : MccCelestialCoordEpoch()
|
||||||
|
{
|
||||||
|
fromTimePoint(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
MccCelestialCoordEpoch(VT&& mjd)
|
||||||
|
requires std::is_arithmetic_v<std::remove_cvref_t<VT>>
|
||||||
|
{
|
||||||
|
// ignore possible errors!!!
|
||||||
|
fromMJD(std::forward<decltype(mjd)>(mjd));
|
||||||
|
}
|
||||||
|
|
||||||
MccCelestialCoordEpoch& operator=(mcc_coord_epoch_c auto&& other)
|
MccCelestialCoordEpoch& operator=(mcc_coord_epoch_c auto&& other)
|
||||||
{
|
{
|
||||||
fromTimePoint(std::forward<decltype(other)>(other).UTC());
|
fromTimePoint(std::forward<decltype(other)>(other).UTC());
|
||||||
@@ -79,17 +99,17 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
template <typename ClockT, typename DurT>
|
template <typename ClockT, typename DurT>
|
||||||
MccCelestialCoordEpoch& operator=(std::chrono::time_point<ClockT, DurT>&& tp)
|
MccCelestialCoordEpoch& operator=(std::chrono::time_point<ClockT, DurT> const& tp)
|
||||||
{
|
{
|
||||||
// ignore possible errors!!!
|
// ignore possible errors!!!
|
||||||
auto ok = fromTimePoint(std::forward<decltype(tp)>(tp));
|
auto ok = fromTimePoint(tp);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
MccCelestialCoordEpoch& operator=(VT&& mjd)
|
MccCelestialCoordEpoch& operator=(VT&& mjd)
|
||||||
requires std::is_arithmetic_v<VT>
|
requires std::is_arithmetic_v<std::remove_cvref_t<VT>>
|
||||||
{
|
{
|
||||||
// ignore possible errors!!!
|
// ignore possible errors!!!
|
||||||
auto ok = fromMJD(std::forward<decltype(mjd)>(mjd));
|
auto ok = fromMJD(std::forward<decltype(mjd)>(mjd));
|
||||||
@@ -139,17 +159,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ClockT, typename DurT>
|
template <typename ClockT, typename DurT>
|
||||||
bool fromTimePoint(std::chrono::time_point<ClockT, DurT>&& tp)
|
bool fromTimePoint(std::chrono::time_point<ClockT, DurT> const& tp)
|
||||||
{
|
{
|
||||||
if constexpr (std::same_as<ClockT, std::chrono::system_clock>) {
|
if constexpr (std::same_as<ClockT, std::chrono::system_clock>) {
|
||||||
_UTC = std::chrono::time_point_cast<decltype(_UTC)::duration>(std::forward<decltype(tp)>(tp));
|
_UTC = std::chrono::time_point_cast<decltype(_UTC)::duration>(tp);
|
||||||
} else if constexpr (std::same_as<ClockT, std::chrono::utc_clock>) {
|
} else if constexpr (std::same_as<ClockT, std::chrono::utc_clock>) {
|
||||||
auto stp = std::chrono::utc_clock::to_sys(std::forward<decltype(tp)>(tp));
|
auto stp = std::chrono::utc_clock::to_sys(tp);
|
||||||
_UTC = std::chrono::time_point_cast<decltype(_UTC)::duration>(std::forward<decltype(tp)>(stp));
|
_UTC = std::chrono::time_point_cast<decltype(_UTC)::duration>(stp);
|
||||||
} else if constexpr (std::same_as<ClockT, std::chrono::tai_clock>) {
|
} else if constexpr (std::same_as<ClockT, std::chrono::tai_clock>) {
|
||||||
return fromTimePoint(ClockT::to_utc(std::forward<decltype(tp)>(tp)));
|
return fromTimePoint(ClockT::to_utc(tp));
|
||||||
} else if constexpr (std::same_as<ClockT, std::chrono::gps_clock>) {
|
} else if constexpr (std::same_as<ClockT, std::chrono::gps_clock>) {
|
||||||
return fromTimePoint(ClockT::to_utc(std::forward<decltype(tp)>(tp)));
|
return fromTimePoint(ClockT::to_utc(tp));
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNSUPPORTED CLOCK!!!");
|
static_assert(false, "UNSUPPORTED CLOCK!!!");
|
||||||
}
|
}
|
||||||
@@ -407,6 +427,5 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
static_assert(mcc_coord_epoch_c<MccCelestialCoordEpoch>, "!!!");
|
static_assert(mcc_coord_epoch_c<MccCelestialCoordEpoch>, "!!!");
|
||||||
|
static_assert(requires(MccCelestialCoordEpoch ep) { ep = std::chrono::system_clock::now(); });
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
****************************************************************************************/
|
****************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "mcc_constants.h"
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "mcc_deserializer.h"
|
#include "mcc_deserializer.h"
|
||||||
#include "mcc_serializer.h"
|
#include "mcc_serializer.h"
|
||||||
#include "mcc_utils.h"
|
#include "mcc_utils.h"
|
||||||
@@ -19,7 +21,13 @@
|
|||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
{
|
{
|
||||||
|
|
||||||
enum class MccKeyValueHolderErrorCode : int { ERROR_OK, ERROR_INVALID_KEY, ERROR_INCOMPATIBLE_TYPE, ERROR_DESERIAL };
|
enum class MccKeyValueHolderErrorCode : int {
|
||||||
|
ERROR_OK,
|
||||||
|
ERROR_INVALID_KEY,
|
||||||
|
ERROR_INCOMPATIBLE_TYPE,
|
||||||
|
ERROR_DESERIAL,
|
||||||
|
ERROR_SERIAL
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|
||||||
@@ -41,12 +49,12 @@ namespace mcc::impl
|
|||||||
struct MccKeyValueHolderCategory : public std::error_category {
|
struct MccKeyValueHolderCategory : public std::error_category {
|
||||||
MccKeyValueHolderCategory() : std::error_category() {}
|
MccKeyValueHolderCategory() : std::error_category() {}
|
||||||
|
|
||||||
const char* name() const noexcept
|
const char* name() const noexcept override
|
||||||
{
|
{
|
||||||
return "MCC-KEYVALUEHOLDER-ERR-CATEGORY";
|
return "MCC-KEYVALUEHOLDER-ERR-CATEGORY";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string message(int ec) const
|
std::string message(int ec) const override
|
||||||
{
|
{
|
||||||
MccKeyValueHolderErrorCode err = static_cast<MccKeyValueHolderErrorCode>(ec);
|
MccKeyValueHolderErrorCode err = static_cast<MccKeyValueHolderErrorCode>(ec);
|
||||||
|
|
||||||
@@ -59,6 +67,8 @@ struct MccKeyValueHolderCategory : public std::error_category {
|
|||||||
return "incompatible type";
|
return "incompatible type";
|
||||||
case MccKeyValueHolderErrorCode::ERROR_DESERIAL:
|
case MccKeyValueHolderErrorCode::ERROR_DESERIAL:
|
||||||
return "deserialization error";
|
return "deserialization error";
|
||||||
|
case MccKeyValueHolderErrorCode::ERROR_SERIAL:
|
||||||
|
return "serialization error";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
@@ -80,68 +90,117 @@ inline std::error_code make_error_code(MccKeyValueHolderErrorCode ec)
|
|||||||
|
|
||||||
// to follow std::variant requirements (not references, not array, not void)
|
// to follow std::variant requirements (not references, not array, not void)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_variant_valid_type_c = requires { !std::is_array_v<T> && !std::is_void_v<T> && !std::is_reference_v<T>; };
|
concept mcc_record_value_c = requires { !std::is_array_v<T> && !std::is_void_v<T> && !std::is_reference_v<T>; };
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_keyvalue_record_c = requires(T t) {
|
concept mcc_keyvalue_record_c = requires(T t) {
|
||||||
requires std::same_as<decltype(t.key), std::string_view>;
|
requires std::same_as<decltype(t.key), const std::string_view>; // key name is immutable!!!
|
||||||
requires mcc_variant_valid_type_c<decltype(t.value)>;
|
requires mcc_record_value_c<decltype(t.value)>; // value is mutable
|
||||||
|
requires mcc_record_value_c<decltype(t.default_value)>; // default value is mutable
|
||||||
|
requires mcc_serialization_params_c<decltype(t.serial_pars)>; // serialization parameters
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// must be a std::tuple of mcc_keyvalue_record_c
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_keyvalue_desc_c = requires(T t) { []<mcc_keyvalue_record_c... Ts>(std::tuple<Ts...>) {}(t); };
|
concept mcc_keyvalue_desc_c = requires(T t) { []<mcc_keyvalue_record_c... Ts>(std::tuple<Ts...>) {}(t); };
|
||||||
|
|
||||||
|
|
||||||
namespace constants
|
// use of 'inline' here to avoid '-Wsubobject-linkage' GCC-warning
|
||||||
{
|
inline constexpr char MCC_KV_COMMENT_SEQ_ARR[] = "#";
|
||||||
|
inline constexpr char MCC_KV_KEY_VALUE_DELIM_SEQ_ARR[] = "=";
|
||||||
static constexpr char MCC_KV_COMMENT_SEQ_ARR[] = "#";
|
inline constexpr char MCC_KV_COMPOSITE_VALUE_DELIM_SEQ_ARR[] = ",";
|
||||||
static constexpr char MCC_KV_KEY_VALUE_DELIM_SEQ_ARR[] = "=";
|
|
||||||
static constexpr char MCC_KV_VALUE_ARRAY_DELIM_SEQ_ARR[] = ",";
|
|
||||||
|
|
||||||
} // namespace constants
|
|
||||||
|
|
||||||
|
|
||||||
template <mcc_keyvalue_desc_c DESCR_T,
|
template <mcc_keyvalue_desc_c DESCR_T,
|
||||||
const char* COMM_SEQ = constants::MCC_KV_COMMENT_SEQ_ARR,
|
const char* COMM_SEQ = MCC_KV_COMMENT_SEQ_ARR, // comment char sequence
|
||||||
const char* KV_DELIM = constants::MCC_KV_KEY_VALUE_DELIM_SEQ_ARR,
|
const char* KV_DELIM = MCC_KV_KEY_VALUE_DELIM_SEQ_ARR // key-value delimiter
|
||||||
const char* ARR_DELIM = constants::MCC_KV_VALUE_ARRAY_DELIM_SEQ_ARR>
|
>
|
||||||
class MccKeyValueHolder
|
class MccKeyValueHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr std::string_view COMMENT_SEQ{COMM_SEQ == nullptr ? constants::MCC_KV_COMMENT_SEQ_ARR
|
enum OutputPolicy {
|
||||||
: COMM_SEQ[0] == '\0' ? constants::MCC_KV_COMMENT_SEQ_ARR
|
OPOLICY_CHANGED_ONLY, // serialize only changed and previously deserialized (by fromCharRange method) key-value
|
||||||
|
// pairs
|
||||||
|
OPOLICY_FULL // serialize entire set of key-value pairs
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::string_view DEFAULT_RECORD_DELIMITER{"\n"};
|
||||||
|
|
||||||
|
static constexpr std::string_view COMMENT_SEQ{COMM_SEQ == nullptr ? MCC_KV_COMMENT_SEQ_ARR
|
||||||
|
: COMM_SEQ[0] == '\0' ? MCC_KV_COMMENT_SEQ_ARR
|
||||||
: COMM_SEQ};
|
: COMM_SEQ};
|
||||||
|
|
||||||
static constexpr std::string_view KEY_VALUE_DELIM{KV_DELIM == nullptr ? constants::MCC_KV_KEY_VALUE_DELIM_SEQ_ARR
|
static constexpr std::string_view KEY_VALUE_DELIM{KV_DELIM == nullptr ? MCC_KV_KEY_VALUE_DELIM_SEQ_ARR
|
||||||
: KV_DELIM[0] == '\0' ? constants::MCC_KV_KEY_VALUE_DELIM_SEQ_ARR
|
: KV_DELIM[0] == '\0' ? MCC_KV_KEY_VALUE_DELIM_SEQ_ARR
|
||||||
: KV_DELIM};
|
: KV_DELIM};
|
||||||
|
|
||||||
static constexpr std::string_view VALUE_ARRAY_DELIM{
|
static constexpr size_t NUMBER_OF_RECORDS = std::tuple_size_v<DESCR_T>;
|
||||||
ARR_DELIM == nullptr ? constants::MCC_KV_VALUE_ARRAY_DELIM_SEQ_ARR
|
|
||||||
: ARR_DELIM[0] == '\0' ? constants::MCC_KV_VALUE_ARRAY_DELIM_SEQ_ARR
|
|
||||||
: ARR_DELIM};
|
|
||||||
|
|
||||||
|
|
||||||
MccKeyValueHolder(DESCR_T desc) : _keyValue(desc)
|
MccKeyValueHolder(DESCR_T desc) : _keyValue(desc)
|
||||||
{
|
{
|
||||||
[this]<size_t... I>(std::index_sequence<I...>) {
|
[this]<size_t... I>(std::index_sequence<I...>) {
|
||||||
((_hashes[I] = utils::FNV1aHash(std::get<I>(_keyValue).key)), ...);
|
((_hashes[I] = utils::FNV1aHash(std::get<I>(_keyValue).key)), ...);
|
||||||
}(std::make_index_sequence<std::tuple_size_v<DESCR_T>>());
|
}(std::make_index_sequence<NUMBER_OF_RECORDS>());
|
||||||
|
|
||||||
|
_changedKey.insert_range(_hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MccKeyValueHolder(MccKeyValueHolder const& other) : MccKeyValueHolder(other._keyValue)
|
||||||
|
{
|
||||||
|
copyInst(other);
|
||||||
|
};
|
||||||
|
|
||||||
|
MccKeyValueHolder(MccKeyValueHolder&& other)
|
||||||
|
{
|
||||||
|
moveInst(std::move(other));
|
||||||
|
};
|
||||||
|
|
||||||
|
MccKeyValueHolder& operator=(MccKeyValueHolder const& other)
|
||||||
|
{
|
||||||
|
copyInst(other);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
|
||||||
|
MccKeyValueHolder& operator=(MccKeyValueHolder&& other)
|
||||||
|
{
|
||||||
|
moveInst(std::move(other));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<std::string_view, NUMBER_OF_RECORDS> keys() const
|
||||||
|
{
|
||||||
|
return [this]<size_t... Is>(std::index_sequence<Is...>) {
|
||||||
|
return std::array<std::string_view, NUMBER_OF_RECORDS>{std::get<Is>(_keyValue).key...};
|
||||||
|
}(std::make_index_sequence<NUMBER_OF_RECORDS>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setToDefaults()
|
||||||
|
{
|
||||||
|
[this]<size_t... Is>(std::index_sequence<Is...>) {
|
||||||
|
((std::get<Is>(_keyValue).value = std::get<Is>(_keyValue).default_value), ...);
|
||||||
|
}(std::make_index_sequence<NUMBER_OF_RECORDS>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, std::ranges::contiguous_range R>
|
||||||
|
std::expected<T, std::error_code> getValue(R const& key) const
|
||||||
|
{
|
||||||
|
return getValue<T>(std::string_view{key});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::expected<T, std::error_code> getValue(std::string_view key) const
|
std::expected<T, std::error_code> getValue(std::string_view key) const
|
||||||
{
|
{
|
||||||
T v;
|
// ugly, but works for non-default constructible values
|
||||||
auto err = forKey(key, [&v]<typename VT>(const VT& val) -> std::error_code {
|
alignas(T) unsigned char buff[sizeof(T)];
|
||||||
if constexpr (std::convertible_to<VT, T>) {
|
auto err = forKey(key, [&buff](auto const& rec) -> std::error_code {
|
||||||
v = val;
|
using VT = decltype(rec.value);
|
||||||
} else if constexpr (std::constructible_from<T, VT>) {
|
if constexpr (std::constructible_from<T, VT>) {
|
||||||
v = T(val);
|
new (buff) T(rec.value);
|
||||||
} else {
|
} else {
|
||||||
return MccKeyValueHolderErrorCode::ERROR_INCOMPATIBLE_TYPE;
|
return MccKeyValueHolderErrorCode::ERROR_INCOMPATIBLE_TYPE;
|
||||||
}
|
}
|
||||||
@@ -152,33 +211,107 @@ public:
|
|||||||
if (err) {
|
if (err) {
|
||||||
return std::unexpected(err);
|
return std::unexpected(err);
|
||||||
} else {
|
} else {
|
||||||
|
auto ptr = reinterpret_cast<T*>(&buff[0]);
|
||||||
|
auto v = std::move(*ptr);
|
||||||
|
ptr->~T(); // one needs explicitly call destructor here to avvoid side effects!!!
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// std::expected<T, std::error_code> getValue(std::string_view key) const
|
||||||
|
// {
|
||||||
|
// T v;
|
||||||
|
// auto err = forKey(key, [&v](auto const& rec) -> std::error_code {
|
||||||
|
// using VT = decltype(rec.value);
|
||||||
|
// if constexpr (std::convertible_to<VT, T>) {
|
||||||
|
// v = rec.value;
|
||||||
|
// } else if constexpr (std::constructible_from<T, VT>) {
|
||||||
|
// v = T(rec.value);
|
||||||
|
// } else {
|
||||||
|
// return MccKeyValueHolderErrorCode::ERROR_INCOMPATIBLE_TYPE;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return MccKeyValueHolderErrorCode::ERROR_OK;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (err) {
|
||||||
|
// return std::unexpected(err);
|
||||||
|
// } else {
|
||||||
|
// return v;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
template <std::ranges::contiguous_range R, typename T>
|
||||||
|
std::error_code setValue(R const& key, const T& value)
|
||||||
|
{
|
||||||
|
return setValue(std::string_view{key}, value);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::error_code setValue(std::string_view key, const T& value)
|
std::error_code setValue(std::string_view key, const T& value)
|
||||||
{
|
{
|
||||||
return forKey(key, [value]<typename VT>(VT& val) -> std::error_code {
|
const size_t hash = utils::FNV1aHash(key);
|
||||||
if constexpr (std::convertible_to<T, VT>) {
|
|
||||||
val = value;
|
auto ec = forHash(hash, [&value](auto& rec) -> std::error_code {
|
||||||
|
using VT = decltype(rec.value);
|
||||||
|
if constexpr (requires { rec.value = value; }) {
|
||||||
|
rec.value = value;
|
||||||
} else if constexpr (std::constructible_from<VT, T>) {
|
} else if constexpr (std::constructible_from<VT, T>) {
|
||||||
val = VT(value);
|
rec.value = VT(value);
|
||||||
|
} else if constexpr (std::ranges::range<VT> && std::ranges::range<T> &&
|
||||||
|
requires(std::ranges::range_value_t<VT> v, std::ranges::range_value_t<T> t) {
|
||||||
|
v = t;
|
||||||
|
}) {
|
||||||
|
const auto& val = std::is_pointer_v<std::decay_t<T>> ? std::span{value} : value;
|
||||||
|
|
||||||
|
size_t N = std::ranges::distance(rec.value.begin(), rec.value.end());
|
||||||
|
size_t M = std::ranges::distance(val.begin(), val.end());
|
||||||
|
|
||||||
|
auto it = std::ranges::begin(rec.value);
|
||||||
|
std::ranges::for_each_n(val.begin(), N > M ? M : N, [&it](auto const& el) {
|
||||||
|
*it = el;
|
||||||
|
++it;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (N >= M) { // resize to match the size of the input range
|
||||||
|
if constexpr (!traits::mcc_non_resizable_range<VT>) {
|
||||||
|
rec.value.resize(M);
|
||||||
|
}
|
||||||
|
} else { // append if allowed
|
||||||
|
if constexpr (!traits::mcc_fixed_size_range<VT>) {
|
||||||
|
std::ranges::for_each_n(val.begin(), N, [&it](auto const& el) {
|
||||||
|
*it = el;
|
||||||
|
++it;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::ranges::for_each(val | std::views::drop(N),
|
||||||
|
[&rec](auto const& el) { std::back_inserter(rec.value) = el; });
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return MccKeyValueHolderErrorCode::ERROR_INCOMPATIBLE_TYPE;
|
return MccKeyValueHolderErrorCode::ERROR_INCOMPATIBLE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MccKeyValueHolderErrorCode::ERROR_OK;
|
return MccKeyValueHolderErrorCode::ERROR_OK;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!ec) {
|
||||||
|
_changedKey.insert(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R,
|
||||||
template <std::ranges::contiguous_range R,
|
traits::mcc_input_char_range RecDelimT = std::string_view,
|
||||||
std::ranges::input_range RecDelimT = std::string_view,
|
|
||||||
mcc_serialization_params_c SerParamsT = mcc_serialization_params_t>
|
mcc_serialization_params_c SerParamsT = mcc_serialization_params_t>
|
||||||
std::error_code fromCharRange(const R& buffer,
|
std::error_code fromCharRange(const R& buffer,
|
||||||
RecDelimT rec_delim = std::string_view("\n"),
|
size_t skip_records = 0, // number of skipped records (from the beginning)
|
||||||
SerParamsT const& ser_params = mcc_serialization_params_t{})
|
RecDelimT rec_delim = DEFAULT_RECORD_DELIMITER // records delimiter
|
||||||
|
)
|
||||||
|
requires std::ranges::contiguous_range<R>
|
||||||
{
|
{
|
||||||
if constexpr (std::is_array_v<std::decay_t<R>>) { // char*, const char*
|
if constexpr (std::is_array_v<std::decay_t<R>>) { // char*, const char*
|
||||||
if constexpr (std::is_array_v<std::decay_t<RecDelimT>>) {
|
if constexpr (std::is_array_v<std::decay_t<RecDelimT>>) {
|
||||||
@@ -193,50 +326,147 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
std::string_view rec, key, value;
|
std::string_view rec, key, svalue, inline_comm;
|
||||||
|
std::vector<std::optional<std::string>> head_comm;
|
||||||
|
size_t key_hash;
|
||||||
|
|
||||||
|
_headComment.clear();
|
||||||
|
_inlineComment.clear();
|
||||||
|
_changedKey.clear();
|
||||||
|
|
||||||
|
// set values to its defaults
|
||||||
|
setToDefaults();
|
||||||
|
|
||||||
|
auto recs = std::views::split(buffer, std::move(rec_delim)) | std::views::drop(skip_records);
|
||||||
|
|
||||||
auto recs = std::views::split(buffer, std::move(rec_delim));
|
|
||||||
for (auto const& el : recs) {
|
for (auto const& el : recs) {
|
||||||
rec = mcc::utils::trimSpaces(el, utils::TrimType::TRIM_LEFT);
|
rec = mcc::utils::trimSpaces(el, utils::TrimType::TRIM_LEFT);
|
||||||
|
|
||||||
|
inline_comm = {};
|
||||||
|
|
||||||
if (rec.size()) {
|
if (rec.size()) {
|
||||||
auto found = std::ranges::search(rec, COMMENT_SEQ);
|
auto found = std::ranges::search(rec, COMMENT_SEQ);
|
||||||
if (found.begin() != rec.end()) { // there was the comment sequence in record
|
if (found.begin() != rec.end()) { // there was the comment sequence in record
|
||||||
|
if (found.begin() != rec.begin()) { // inline comment
|
||||||
|
inline_comm =
|
||||||
|
std::string_view{found.begin() + COMMENT_SEQ.size(), rec.end()}; // mark inline comment
|
||||||
|
} else { // head comment
|
||||||
|
head_comm.push_back(std::string{found.end(), rec.end()});
|
||||||
|
}
|
||||||
|
|
||||||
rec = std::string_view(rec.begin(), found.begin());
|
rec = std::string_view(rec.begin(), found.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec.size()) {
|
if (rec.size()) {
|
||||||
found = std::ranges::search(rec, KEY_VALUE_DELIM);
|
found = std::ranges::search(rec, KEY_VALUE_DELIM);
|
||||||
if (found.begin() != rec.begin()) { // ignore an empty key
|
if (found.begin() != rec.begin()) {
|
||||||
key = trimSpaces(std::string_view(rec.begin(), found.begin()), utils::TrimType::TRIM_RIGHT);
|
key = trimSpaces(std::string_view(rec.begin(), found.begin()), utils::TrimType::TRIM_RIGHT);
|
||||||
value = std::string_view(found.end(), rec.end());
|
svalue = std::string_view(found.end(), rec.end());
|
||||||
|
|
||||||
ec = forKey(key, [value, &ser_params]<typename VT>(VT& v) {
|
key_hash = utils::FNV1aHash(key);
|
||||||
auto err = MccDeserializer<VT>(value, v, ser_params);
|
|
||||||
|
ec = forHash(key_hash, [&key_hash, svalue, this]<typename REC_T>(REC_T& v) {
|
||||||
|
using VT = decltype(v.value);
|
||||||
|
auto err = MccDeserializer<VT>{}(svalue, v.value, v.serial_pars);
|
||||||
if (err) {
|
if (err) {
|
||||||
return MccKeyValueHolderErrorCode::ERROR_DESERIAL;
|
return MccKeyValueHolderErrorCode::ERROR_DESERIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_changedKey.insert(key_hash);
|
||||||
|
|
||||||
return MccKeyValueHolderErrorCode::ERROR_OK;
|
return MccKeyValueHolderErrorCode::ERROR_OK;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ec) { // exit in the case of error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save head comment
|
||||||
|
_headComment[key_hash] = head_comm;
|
||||||
|
head_comm.clear();
|
||||||
|
_inlineComment[key_hash] = inline_comm;
|
||||||
|
} else { // an empty key
|
||||||
|
ec = MccKeyValueHolderErrorCode::ERROR_INVALID_KEY;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} // just comment string starting from the beginning, just skip it (no error)
|
} // just comment string starting from the beginning, just skip it (no error)
|
||||||
|
|
||||||
} // empty record, just skip it (no error)
|
} else { // empty record, just skip it (no error)
|
||||||
|
// head_comm.push_back({el.begin(), el.end()});
|
||||||
if (ec) {
|
head_comm.push_back(std::nullopt);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <OutputPolicy OPOLICY = MccKeyValueHolder::OPOLICY_CHANGED_ONLY,
|
||||||
|
traits::mcc_output_char_range R,
|
||||||
|
traits::mcc_input_char_range RecDelimT = std::string_view>
|
||||||
|
std::error_code toCharRange(R& output_buffer, RecDelimT rec_delim = DEFAULT_RECORD_DELIMITER)
|
||||||
|
{
|
||||||
|
if (std::is_pointer_v<std::decay_t<RecDelimT>>) { // char*, const char*, char[], conat char[]
|
||||||
|
return toCharRange(output_buffer, std::string_view{rec_delim});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code ec{};
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
// to fix GCC compilation crash for the versions < 16
|
||||||
|
#if GCC_VERSION < 160000
|
||||||
|
auto write_rec = [&output_buffer, &rec_delim, &ec, obj_ptr = this]<size_t I = 0>(this auto& self) -> void {
|
||||||
|
#else
|
||||||
|
auto write_rec = [&output_buffer, &rec_delim, &ec, this]<size_t I = 0>(this auto& self) -> void {
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if constexpr (I < NUMBER_OF_RECORDS) {
|
||||||
|
if constexpr (OPOLICY == MccKeyValueHolder::OPOLICY_CHANGED_ONLY) {
|
||||||
|
#ifdef __GNUG__
|
||||||
|
// to fix GCC compilation crash for the versions < 16
|
||||||
|
#if GCC_VERSION < 160000
|
||||||
|
if (obj_ptr->_changedKey.count(obj_ptr->_hashes[I]) == 0) {
|
||||||
|
#else
|
||||||
|
if (_changedKey.count(_hashes[I]) == 0) {
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
self.template operator()<I + 1>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
// to fix GCC compilation crash for the versions < 16
|
||||||
|
#if GCC_VERSION < 160000
|
||||||
|
ec = obj_ptr->template formatRecord<I>(output_buffer, rec_delim);
|
||||||
|
#else
|
||||||
|
ec = formatRecord<I>(output_buffer, rec_delim);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (ec) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.template operator()<I + 1>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
write_rec();
|
||||||
|
|
||||||
|
// [&write_rec]<size_t... Is>(std::index_sequence<Is...>) {
|
||||||
|
// (write_rec.template operator()<Is>(), ...);
|
||||||
|
// }(std::make_index_sequence<NUMBER_OF_RECORDS>());
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DESCR_T _keyValue;
|
DESCR_T _keyValue;
|
||||||
|
|
||||||
std::array<size_t, std::tuple_size_v<DESCR_T>> _hashes;
|
std::array<size_t, NUMBER_OF_RECORDS> _hashes{}; // key hashes
|
||||||
|
std::unordered_map<size_t, std::vector<std::optional<std::string>>>
|
||||||
|
_headComment{}; // comment string/strings before key
|
||||||
|
std::unordered_map<size_t, std::string> _inlineComment{}; // inline (after key=value pair) comment
|
||||||
|
std::unordered_set<size_t> _changedKey{}; // loaded keys (see fromCharRange)
|
||||||
|
|
||||||
//
|
//
|
||||||
// NOTE: deduced this is needed here to use "forKey" method in getter and setter (const and non-const contexts)!!!
|
// NOTE: deduced this is needed here to use "forKey" method in getter and setter (const and non-const contexts)!!!
|
||||||
@@ -249,13 +479,19 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'func' signature:
|
||||||
|
// std::error func(mcc_keyvalue_record_c&&)
|
||||||
|
// e.g.:
|
||||||
|
// [](auto const& rec)->std::error_code {}
|
||||||
|
// [](auto& rec)->std::error_code {}
|
||||||
|
//
|
||||||
template <size_t I = 0>
|
template <size_t I = 0>
|
||||||
std::error_code forHash(this auto&& self, size_t hash, auto&& func)
|
std::error_code forHash(this auto&& self, size_t hash, auto&& func)
|
||||||
{
|
{
|
||||||
if constexpr (I < std::tuple_size_v<DESCR_T>) {
|
if constexpr (I < NUMBER_OF_RECORDS) {
|
||||||
if (hash == std::forward<decltype(self)>(self)._hashes[I]) {
|
if (hash == std::forward<decltype(self)>(self)._hashes[I]) {
|
||||||
return std::forward<decltype(func)>(func)(
|
return std::forward<decltype(func)>(func)(std::get<I>(std::forward<decltype(self)>(self)._keyValue));
|
||||||
std::get<I>(std::forward<decltype(self)>(self)._keyValue).value);
|
|
||||||
} else {
|
} else {
|
||||||
return std::forward<decltype(self)>(self).template forHash<I + 1>(hash,
|
return std::forward<decltype(self)>(self).template forHash<I + 1>(hash,
|
||||||
std::forward<decltype(func)>(func));
|
std::forward<decltype(func)>(func));
|
||||||
@@ -264,7 +500,116 @@ protected:
|
|||||||
|
|
||||||
return MccKeyValueHolderErrorCode::ERROR_INVALID_KEY;
|
return MccKeyValueHolderErrorCode::ERROR_INVALID_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <size_t I = 0, traits::mcc_output_char_range R, traits::mcc_input_char_range RecDelimT>
|
||||||
|
std::error_code formatRecord(R& output_buffer, RecDelimT rec_delim, bool is_default = false)
|
||||||
|
{
|
||||||
|
if constexpr (I < NUMBER_OF_RECORDS) {
|
||||||
|
auto key = std::get<I>(_keyValue).key;
|
||||||
|
using val_t = std::remove_cvref_t<decltype(std::get<I>(_keyValue).value)>;
|
||||||
|
|
||||||
|
const val_t& val = is_default ? std::get<I>(_keyValue).default_value : std::get<I>(_keyValue).value;
|
||||||
|
|
||||||
|
std::string buff;
|
||||||
|
// auto err = MccSerializer<val_t>{}(buff, std::get<I>(_keyValue).value,
|
||||||
|
// std::get<I>(_keyValue).serial_pars);
|
||||||
|
auto err = MccSerializer<val_t>{}(buff, val, std::get<I>(_keyValue).serial_pars);
|
||||||
|
if (err) {
|
||||||
|
return MccKeyValueHolderErrorCode::ERROR_SERIAL;
|
||||||
|
} else {
|
||||||
|
size_t hash = _hashes[I];
|
||||||
|
// write head comment
|
||||||
|
if (_headComment[hash].size()) {
|
||||||
|
for (auto const& comm : _headComment[hash]) {
|
||||||
|
if (comm.has_value()) {
|
||||||
|
std::format_to(std::back_inserter(output_buffer), "{}{}", COMM_SEQ, comm.value());
|
||||||
|
}
|
||||||
|
std::ranges::copy(rec_delim, std::back_inserter(output_buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// key and value
|
||||||
|
std::format_to(std::back_inserter(output_buffer), "{}{}{}", key, KEY_VALUE_DELIM, buff);
|
||||||
|
|
||||||
|
// inline comment
|
||||||
|
if (_inlineComment[hash].size()) {
|
||||||
|
std::format_to(std::back_inserter(output_buffer), " {}{}", COMMENT_SEQ, _inlineComment[hash]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// record delimiter
|
||||||
|
std::ranges::copy(rec_delim, std::back_inserter(output_buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccKeyValueHolderErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t I = 0>
|
||||||
|
void copyInst(MccKeyValueHolder const& other)
|
||||||
|
{
|
||||||
|
if constexpr (I < NUMBER_OF_RECORDS) {
|
||||||
|
// here one needs check equality of the keys!!!
|
||||||
|
if (_hashes[I] == other._hashes[I]) {
|
||||||
|
auto& orec = std::get<I>(other._keyValue);
|
||||||
|
std::get<I>(_keyValue).value = orec.value;
|
||||||
|
std::get<I>(_keyValue).default_value = orec.default_value;
|
||||||
|
std::get<I>(_keyValue).serial_pars = orec.serial_pars;
|
||||||
|
|
||||||
|
if (auto it = other._headComment.find(_hashes[I]); it != other._headComment.end()) {
|
||||||
|
_headComment[_hashes[I]] = it->second;
|
||||||
|
}
|
||||||
|
if (auto it = other._inlineComment.find(_hashes[I]); it != other._inlineComment.end()) {
|
||||||
|
_inlineComment[_hashes[I]] = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
_changedKey.insert(_hashes[I]);
|
||||||
|
}
|
||||||
|
|
||||||
|
copyInst<I + 1>(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t I = 0>
|
||||||
|
void moveInst(MccKeyValueHolder&& other)
|
||||||
|
{
|
||||||
|
if constexpr (I < NUMBER_OF_RECORDS) {
|
||||||
|
// here one needs check equality of the keys!!!
|
||||||
|
if (_hashes[I] == other._hashes[I]) {
|
||||||
|
auto& orec = std::get<I>(other._keyValue);
|
||||||
|
std::get<I>(_keyValue).value = std::move(orec.value);
|
||||||
|
std::get<I>(_keyValue).default_value = std::move(orec.default_value);
|
||||||
|
std::get<I>(_keyValue).serial_pars = std::move(orec.serial_pars);
|
||||||
|
|
||||||
|
if (auto it = other._headComment.find(_hashes[I]); it != other._headComment.end()) {
|
||||||
|
_headComment[_hashes[I]] = std::move(it->second);
|
||||||
|
}
|
||||||
|
if (auto it = other._inlineComment.find(_hashes[I]); it != other._inlineComment.end()) {
|
||||||
|
_inlineComment[_hashes[I]] = std::move(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
_changedKey.insert(_hashes[I]);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveInst<I + 1>(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <mcc_record_value_c T>
|
||||||
|
struct mcc_simple_kv_record_t {
|
||||||
|
const std::string_view key;
|
||||||
|
T value, default_value;
|
||||||
|
mcc_serialization_params_t serial_pars;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <mcc_record_value_c T>
|
||||||
|
static mcc_simple_kv_record_t<T> mcc_make_simple_kv_record(
|
||||||
|
std::string_view key,
|
||||||
|
T const& def_value,
|
||||||
|
mcc_serialization_params_t const& spars = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
return mcc_simple_kv_record_t<T>{key, def_value, def_value, spars};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "mcc_concepts.h"
|
#include "mcc_concepts.h"
|
||||||
#include "mcc_coordinate.h"
|
#include "mcc_coordinate.h"
|
||||||
|
#include "mcc_deserializer.h"
|
||||||
|
#include "mcc_serializer.h"
|
||||||
|
|
||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
{
|
{
|
||||||
@@ -104,6 +106,24 @@ class is_error_code_enum<mcc::impl::MccDefaultPCMErrorCode> : public true_type
|
|||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// The routine generates a sequence of length 'innerN'+2 elements.
|
||||||
|
// Th e first element is 'start_border' and the last one is 'stop_border'
|
||||||
|
// (i.e. it returns at least 2-elements std::vector)
|
||||||
|
// 'innerN' is a number of inner elements
|
||||||
|
static std::vector<double> mccGenerateBsplineKnots(double start_border, double stop_border, size_t innerN)
|
||||||
|
{
|
||||||
|
std::vector<double> res(innerN + 2);
|
||||||
|
res.front() = start_border;
|
||||||
|
res.back() = stop_border;
|
||||||
|
|
||||||
|
if (innerN) {
|
||||||
|
const double step = (stop_border - start_border) / (innerN + 1);
|
||||||
|
std::ranges::for_each(std::views::iota(1, (int)innerN + 1),
|
||||||
|
[&](auto const& i) { res[i] = start_border + i * step; });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// type of PCM corrections (algorithm used):
|
// type of PCM corrections (algorithm used):
|
||||||
// PCM_TYPE_GEOMETRY - "classic" geometry-based correction coefficients
|
// PCM_TYPE_GEOMETRY - "classic" geometry-based correction coefficients
|
||||||
@@ -131,6 +151,48 @@ static constexpr std::string_view mccDefaultPCMTypeString(MccDefaultPCMType type
|
|||||||
: "UNKNOWN";
|
: "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccSerializer<MccDefaultPCMType> : MccSerializerBase {
|
||||||
|
constexpr static std::string_view serializerName{"MCC-DEFAULT-PCMTYPE-SERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output,
|
||||||
|
MccDefaultPCMType const& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
std::ranges::copy(mccDefaultPCMTypeString(value), std::back_inserter(output));
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccDeserializer<MccDefaultPCMType> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-COORD-EPOCH-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
MccDefaultPCMType& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
auto s = mcc::utils::trimSpaces(input);
|
||||||
|
|
||||||
|
if (s == mcc::impl::MccDefaultPCMTypeString<mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY>) {
|
||||||
|
value = mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::impl::MccDefaultPCMTypeString<mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE>) {
|
||||||
|
value = mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::impl::MccDefaultPCMTypeString<mcc::impl::MccDefaultPCMType::PCM_TYPE_BSPLINE>) {
|
||||||
|
value = mcc::impl::MccDefaultPCMType::PCM_TYPE_BSPLINE;
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <MccMountType MOUNT_TYPE>
|
template <MccMountType MOUNT_TYPE>
|
||||||
class MccDefaultPCM : public mcc_pcm_interface_t<std::error_code>
|
class MccDefaultPCM : public mcc_pcm_interface_t<std::error_code>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
#include "mcc_concepts.h"
|
#include "mcc_concepts.h"
|
||||||
#include "mcc_constants.h"
|
#include "mcc_constants.h"
|
||||||
#include "mcc_coordinate.h"
|
#include "mcc_coordinate.h"
|
||||||
|
#include "mcc_deserializer.h"
|
||||||
|
#include "mcc_serializer.h"
|
||||||
|
|
||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
enum class MccPZoneErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_COORD_TRANSFROM, ERROR_PCM_COMP };
|
enum class MccPZoneErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_COORD_TRANSFROM, ERROR_NO_PCM, ERROR_PCM_COMP };
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|
||||||
@@ -56,6 +58,8 @@ struct MccPZoneCategory : public std::error_category {
|
|||||||
return "input argument os nullptr";
|
return "input argument os nullptr";
|
||||||
case MccPZoneErrorCode::ERROR_COORD_TRANSFROM:
|
case MccPZoneErrorCode::ERROR_COORD_TRANSFROM:
|
||||||
return "coordinate transformation error";
|
return "coordinate transformation error";
|
||||||
|
case MccPZoneErrorCode::ERROR_NO_PCM:
|
||||||
|
return "PCM was not set";
|
||||||
case MccPZoneErrorCode::ERROR_PCM_COMP:
|
case MccPZoneErrorCode::ERROR_PCM_COMP:
|
||||||
return "PCM computation error";
|
return "PCM computation error";
|
||||||
default:
|
default:
|
||||||
@@ -89,6 +93,7 @@ public:
|
|||||||
|
|
||||||
MccAltLimitPZ(mcc_angle_c auto const& alt_limit, mcc_angle_c auto const& latitude)
|
MccAltLimitPZ(mcc_angle_c auto const& alt_limit, mcc_angle_c auto const& latitude)
|
||||||
: _altLimit(MccAngle(alt_limit).normalize<MccAngle::NORM_KIND_90_90>()),
|
: _altLimit(MccAngle(alt_limit).normalize<MccAngle::NORM_KIND_90_90>()),
|
||||||
|
_latitude(MccAngle::normalizeAngle<MccAngle::NORM_KIND_90_90>(latitude)),
|
||||||
_cosALim(cos(_altLimit)),
|
_cosALim(cos(_altLimit)),
|
||||||
_sinAlim(sin(_altLimit)),
|
_sinAlim(sin(_altLimit)),
|
||||||
_cosLat(cos(latitude)),
|
_cosLat(cos(latitude)),
|
||||||
@@ -106,6 +111,32 @@ public:
|
|||||||
: KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE"
|
: KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE"
|
||||||
: "ALTLIMIT-UNKNOWN";
|
: "ALTLIMIT-UNKNOWN";
|
||||||
|
|
||||||
|
MccAltLimitPZ& operator=(MccAltLimitPZ&&) = default;
|
||||||
|
MccAltLimitPZ& operator=(const MccAltLimitPZ&) = default;
|
||||||
|
|
||||||
|
template <mcc_angle_c T>
|
||||||
|
T altLimit() const
|
||||||
|
requires(!std::derived_from<T, MccAngle>)
|
||||||
|
{
|
||||||
|
return _altLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle altLimit() const
|
||||||
|
{
|
||||||
|
return _altLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <mcc_angle_c T>
|
||||||
|
T latitude() const
|
||||||
|
requires(!std::derived_from<T, MccAngle>)
|
||||||
|
{
|
||||||
|
return _latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle latitude() const
|
||||||
|
{
|
||||||
|
return _latitude;
|
||||||
|
}
|
||||||
|
|
||||||
error_t inPZone(mcc_skypoint_c auto const& coords, bool* result)
|
error_t inPZone(mcc_skypoint_c auto const& coords, bool* result)
|
||||||
{
|
{
|
||||||
@@ -230,7 +261,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
double _altLimit, _cosALim, _sinAlim;
|
double _altLimit, _cosALim, _sinAlim;
|
||||||
double _cosLat, _sinLat, _absLat, _latLim;
|
double _latitude, _cosLat, _sinLat, _absLat, _latLim;
|
||||||
|
|
||||||
bool doesObjectReachZone(const double& dec_app)
|
bool doesObjectReachZone(const double& dec_app)
|
||||||
{
|
{
|
||||||
@@ -321,15 +352,88 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_copy_assignable_v<MccAltLimitPZ<MccAltLimitKind::MIN_ALT_LIMIT>>);
|
||||||
|
|
||||||
|
/*
|
||||||
|
to be serialized in format:
|
||||||
|
ALT-LIMIT<seq-delim>LATITUDE
|
||||||
|
*/
|
||||||
|
template <MccAltLimitKind KIND>
|
||||||
|
struct MccSerializer<MccAltLimitPZ<KIND>> : MccSerializerBase {
|
||||||
|
constexpr static std::string_view serializerName{"MCC-ALTITUDE-PZONE-SERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output,
|
||||||
|
MccAltLimitPZ<KIND> const& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
MccSerializer<MccAngle> aser;
|
||||||
|
|
||||||
|
auto err = aser(output, value.altLimit(), params);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", params.seq_delim);
|
||||||
|
|
||||||
|
err = aser(output, value.latitude(), params);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <MccAltLimitKind KIND>
|
||||||
|
struct MccDeserializer<MccAltLimitPZ<KIND>> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-ALTITUDE-PZONE-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
MccAltLimitPZ<KIND>& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
std::vector<std::string_view> s;
|
||||||
|
MccDeserializer<MccAngle> ades;
|
||||||
|
|
||||||
|
auto seq = std::views::split(input, params.seq_delim);
|
||||||
|
if (std::ranges::distance(seq.begin(), seq.end()) > 1) {
|
||||||
|
for (auto const& seq_el : seq) {
|
||||||
|
s.push_back(utils::trimSpaces(seq_el, utils::TrimType::TRIM_BOTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle alt, lat;
|
||||||
|
|
||||||
|
auto err = ades(s[0], alt, params);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ades(s[1], lat, params);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = MccAltLimitPZ<KIND>(alt, lat);
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* co-longitude axis (HA or AZ) limit switch prohibited zone */
|
|
||||||
|
/* co-longitude axis (HA or AZ) and co-latitude (DEC, ZD) limit switch prohibited zone */
|
||||||
|
|
||||||
template <MccCoordKind AXIS_KIND>
|
template <MccCoordKind AXIS_KIND>
|
||||||
class MccAxisLimitSwitchPZ : public mcc_pzone_interface_t<std::error_code>
|
class MccAxisLimitSwitchPZ : public mcc_pzone_interface_t<std::error_code>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static_assert(AXIS_KIND == MccCoordKind::COORDS_KIND_AZ || AXIS_KIND == MccCoordKind::COORDS_KIND_HA_OBS,
|
static_assert(AXIS_KIND == MccCoordKind::COORDS_KIND_AZ || AXIS_KIND == MccCoordKind::COORDS_KIND_HA_OBS ||
|
||||||
|
AXIS_KIND == MccCoordKind::COORDS_KIND_ZD || AXIS_KIND == MccCoordKind::COORDS_KIND_DEC_OBS,
|
||||||
"UNSUPPORTED AXIS TYPE!");
|
"UNSUPPORTED AXIS TYPE!");
|
||||||
|
|
||||||
typedef std::error_code error_t;
|
typedef std::error_code error_t;
|
||||||
@@ -339,33 +443,89 @@ public:
|
|||||||
static constexpr MccProhibitedZonePolicy pzPolicy = MccProhibitedZonePolicy::PZ_POLICY_FLIP;
|
static constexpr MccProhibitedZonePolicy pzPolicy = MccProhibitedZonePolicy::PZ_POLICY_FLIP;
|
||||||
|
|
||||||
//
|
//
|
||||||
// min_limit_val and max_limit_val are hardware encoder angles in radians!
|
// min_limit_val and max_limit_val are hardware encoder angles!
|
||||||
|
// pcm is nullptr or pointer to mcc_pcm_c
|
||||||
//
|
//
|
||||||
MccAxisLimitSwitchPZ(mcc_angle_c auto const& min_limit_val,
|
template <typename PCM_T>
|
||||||
mcc_angle_c auto const& max_limit_val,
|
MccAxisLimitSwitchPZ(mcc_angle_c auto const& min_limit_val, mcc_angle_c auto const& max_limit_val, PCM_T pcm)
|
||||||
mcc_pcm_c auto* pcm)
|
requires(std::is_null_pointer_v<PCM_T> || mcc_pcm_c<std::remove_pointer_t<PCM_T>>)
|
||||||
: _minLimit(min_limit_val), _maxLimit(max_limit_val)
|
: _minLimit(min_limit_val), _maxLimit(max_limit_val)
|
||||||
{
|
{
|
||||||
_correctForPCM = [pcm](MccSkyPoint const& skypt, MccGenXY* hw_coords) {
|
if constexpr (std::is_null_pointer_v<PCM_T>) {
|
||||||
struct pcm_res_t {
|
_correctForPCM = [](MccSkyPoint const&, MccGenXY*) -> error_t { return MccPZoneErrorCode::ERROR_NO_PCM; };
|
||||||
double pcmX, pcmY;
|
} else {
|
||||||
|
_correctForPCM = [pcm](MccSkyPoint const& skypt, MccGenXY* hw_coords) {
|
||||||
|
struct pcm_res_t {
|
||||||
|
double pcmX, pcmY;
|
||||||
|
};
|
||||||
|
|
||||||
|
pcm_res_t res;
|
||||||
|
|
||||||
|
auto err = pcm->computeInversePCM(skypt, &res, hw_coords);
|
||||||
|
|
||||||
|
return mcc_deduced_err(err, MccPZoneErrorCode::ERROR_PCM_COMP);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
pcm_res_t res;
|
|
||||||
|
|
||||||
auto err = pcm->computeInversePCM(skypt, &res, hw_coords);
|
|
||||||
|
|
||||||
return mcc_deduced_err(err, MccPZoneErrorCode::ERROR_PCM_COMP);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static constexpr std::string_view pzoneName = axisKind == MccCoordKind::COORDS_KIND_AZ ? "AZ_AXIS-LIMITSWITCH_ZONE"
|
static constexpr std::string_view pzoneName =
|
||||||
: axisKind == MccCoordKind::COORDS_KIND_HA_OBS
|
axisKind == MccCoordKind::COORDS_KIND_AZ ? "AZ-AXIS-LIMITSWITCH-ZONE"
|
||||||
? "HA_AXIS-LIMITSWITCH_ZONE"
|
: axisKind == MccCoordKind::COORDS_KIND_HA_OBS ? "HA-AXIS-LIMITSWITCH-ZONE"
|
||||||
: "UKNOWN";
|
: axisKind == MccCoordKind::COORDS_KIND_ZD ? "ZD-AXIS-LIMITSWITCH-ZONE"
|
||||||
|
: axisKind == MccCoordKind::COORDS_KIND_DEC_OBS ? "DEC-AXIS-LIMITSWITCH-ZONE"
|
||||||
|
: "UKNOWN";
|
||||||
|
|
||||||
|
MccAxisLimitSwitchPZ(const MccAxisLimitSwitchPZ&) = default;
|
||||||
|
MccAxisLimitSwitchPZ(MccAxisLimitSwitchPZ&&) = default;
|
||||||
|
|
||||||
|
MccAxisLimitSwitchPZ& operator=(const MccAxisLimitSwitchPZ&) = default;
|
||||||
|
MccAxisLimitSwitchPZ& operator=(MccAxisLimitSwitchPZ&&) = default;
|
||||||
|
|
||||||
|
template <mcc_angle_c T>
|
||||||
|
T minLimit() const
|
||||||
|
requires(!std::derived_from<T, MccAngle>)
|
||||||
|
{
|
||||||
|
return _minLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle minLimit() const
|
||||||
|
{
|
||||||
|
return _minLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <mcc_angle_c T>
|
||||||
|
T maxLimit() const
|
||||||
|
requires(!std::derived_from<T, MccAngle>)
|
||||||
|
{
|
||||||
|
return _maxLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle maxLimit() const
|
||||||
|
{
|
||||||
|
return _maxLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PCM_T>
|
||||||
|
void setPCM(PCM_T pcm)
|
||||||
|
requires(std::is_null_pointer_v<PCM_T> || mcc_pcm_c<std::remove_pointer_t<PCM_T>>)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_null_pointer_v<PCM_T>) {
|
||||||
|
_correctForPCM = [](MccSkyPoint const&, MccGenXY*) -> error_t { return MccPZoneErrorCode::ERROR_NO_PCM; };
|
||||||
|
} else {
|
||||||
|
_correctForPCM = [pcm](MccSkyPoint const& skypt, MccGenXY* hw_coords) {
|
||||||
|
struct pcm_res_t {
|
||||||
|
double pcmX, pcmY;
|
||||||
|
};
|
||||||
|
|
||||||
|
pcm_res_t res;
|
||||||
|
|
||||||
|
auto err = pcm->computeInversePCM(skypt, &res, hw_coords);
|
||||||
|
|
||||||
|
return mcc_deduced_err(err, MccPZoneErrorCode::ERROR_PCM_COMP);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_t inPZone(mcc_skypoint_c auto const& coords, bool* result)
|
error_t inPZone(mcc_skypoint_c auto const& coords, bool* result)
|
||||||
{
|
{
|
||||||
@@ -430,15 +590,36 @@ protected:
|
|||||||
coords.to(xy);
|
coords.to(xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
double x = xy.x();
|
|
||||||
|
|
||||||
if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_HA_OBS) {
|
if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_HA_OBS) {
|
||||||
|
double x = xy.x();
|
||||||
|
|
||||||
if (from_time) { // timeFromPZone
|
if (from_time) { // timeFromPZone
|
||||||
time_ang = (_minLimit - x) / MCC_SIDERAL_TO_UT1_RATIO; // to UT1 scale
|
time_ang = (_minLimit - x) / MCC_SIDERAL_TO_UT1_RATIO; // to UT1 scale
|
||||||
} else { // timeToPZone
|
} else { // timeToPZone
|
||||||
time_ang = (_maxLimit - x) / MCC_SIDERAL_TO_UT1_RATIO; // to UT1 scale
|
time_ang = (_maxLimit - x) / MCC_SIDERAL_TO_UT1_RATIO; // to UT1 scale
|
||||||
}
|
}
|
||||||
|
} else if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_DEC_OBS) {
|
||||||
|
double y = xy.y();
|
||||||
|
|
||||||
|
// TODO: !!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
// assume here sideral speed moving! so, observed DEC is near constant
|
||||||
|
if (from_time) { // timeFromPZone
|
||||||
|
if (y < _minLimit || y > _maxLimit) {
|
||||||
|
time_ang = std::numeric_limits<double>::max();
|
||||||
|
} else {
|
||||||
|
time_ang = 0;
|
||||||
|
}
|
||||||
|
} else { // timeToPZone
|
||||||
|
if (y < _minLimit || y > _maxLimit) { // already in the zone
|
||||||
|
time_ang = 0;
|
||||||
|
} else {
|
||||||
|
time_ang = std::numeric_limits<double>::max();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_AZ) {
|
} else if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_AZ) {
|
||||||
|
static_assert(false, "NOT IMPLEMENTED YET!!!");
|
||||||
|
} else {
|
||||||
|
static_assert(false, "NOT IMPLEMENTED YET!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::nanoseconds ns{
|
std::chrono::nanoseconds ns{
|
||||||
@@ -451,5 +632,81 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_copy_assignable_v<MccAxisLimitSwitchPZ<MccCoordKind::COORDS_KIND_HA_OBS>>);
|
||||||
|
static_assert(std::is_copy_assignable_v<MccAxisLimitSwitchPZ<MccCoordKind::COORDS_KIND_DEC_OBS>>);
|
||||||
|
|
||||||
|
/*
|
||||||
|
to be serialized in format:
|
||||||
|
MIN_LIMIT<seq-delim>MAX_LIMIT
|
||||||
|
*/
|
||||||
|
template <MccCoordKind AXIS_KIND>
|
||||||
|
struct MccSerializer<MccAxisLimitSwitchPZ<AXIS_KIND>> : MccSerializerBase {
|
||||||
|
constexpr static std::string_view serializerName{"MCC-AXIS-LIMIT-SWITCH-SERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output,
|
||||||
|
MccAxisLimitSwitchPZ<AXIS_KIND> const& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
MccSerializer<MccAngle> aser;
|
||||||
|
|
||||||
|
auto err = aser(output, value.minLimit(), params);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", params.seq_delim);
|
||||||
|
|
||||||
|
err = aser(output, value.maxLimit(), params);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <MccCoordKind AXIS_KIND>
|
||||||
|
struct MccDeserializer<MccAxisLimitSwitchPZ<AXIS_KIND>> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-AXIS-LIMIT-SWITCH-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
MccAxisLimitSwitchPZ<AXIS_KIND>& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
std::vector<std::string_view> s;
|
||||||
|
MccDeserializer<MccAngle> ades;
|
||||||
|
|
||||||
|
auto seq = std::views::split(input, params.seq_delim);
|
||||||
|
// if (std::ranges::size(seq) < 2) {
|
||||||
|
if (std::ranges::distance(seq.begin(), seq.end()) > 1) {
|
||||||
|
for (auto const& seq_el : seq) {
|
||||||
|
s.push_back(utils::trimSpaces(seq_el, utils::TrimType::TRIM_BOTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
MccAngle minLim, maxLim;
|
||||||
|
|
||||||
|
auto err = ades(s[0], minLim, params);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ades(s[1], maxLim, params);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING: the class below is created without the PCM-class pointer!!!
|
||||||
|
value = MccAxisLimitSwitchPZ<AXIS_KIND>(minLim, maxLim, nullptr);
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -56,7 +56,13 @@ template <typename R>
|
|||||||
concept mcc_range_of_output_char_range =
|
concept mcc_range_of_output_char_range =
|
||||||
std::ranges::range<R> && traits::mcc_output_char_range<std::ranges::range_value_t<R>>;
|
std::ranges::range<R> && traits::mcc_output_char_range<std::ranges::range_value_t<R>>;
|
||||||
|
|
||||||
|
// std::array, std::span(v_t, N), std::tuple
|
||||||
|
template <typename R>
|
||||||
|
concept mcc_fixed_size_range = std::ranges::range<R> && requires { std::tuple_size<std::remove_cvref_t<R>>::value; };
|
||||||
|
|
||||||
|
// non-resizable ranges
|
||||||
|
template <typename R>
|
||||||
|
concept mcc_non_resizable_range = std::ranges::range<R> && !requires(R r, std::size_t n) { r.resize(n); };
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
|
// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
178
tests/mcc_keyvalue_test.cpp
Normal file
178
tests/mcc_keyvalue_test.cpp
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include <mcc/mcc_keyvalue.h>
|
||||||
|
|
||||||
|
using namespace mcc::impl;
|
||||||
|
|
||||||
|
|
||||||
|
// example of non-default constructible class
|
||||||
|
struct VT {
|
||||||
|
VT(int v) : _v(v) {}
|
||||||
|
|
||||||
|
void set(int v)
|
||||||
|
{
|
||||||
|
_v = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int v() const
|
||||||
|
{
|
||||||
|
return _v;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int _v{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct mcc::impl::MccSerializer<VT> : MccSerializerBase {
|
||||||
|
static constexpr std::string_view serializerName{"MCC-VT-SERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output,
|
||||||
|
VT const& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
return MccSerializer<int>{}(output, value.v(), params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct mcc::impl::MccDeserializer<VT> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-VT-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
VT& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
auto err = MccDeserializer<int>{}(input, v, params);
|
||||||
|
if (!err) {
|
||||||
|
value.set(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static auto kv_desc = std::make_tuple(
|
||||||
|
mcc_simple_kv_record_t{"bb", MccAngle{11.5_degs}, MccAngle{11.5_degs}, mcc_serialization_params_t{}},
|
||||||
|
mcc_simple_kv_record_t{"aaa", std::string("AAA"), std::string("AAA"), mcc_serialization_params_t{}},
|
||||||
|
mcc_simple_kv_record_t{"cc", MccCelestialCoordEpoch{}, MccCelestialCoordEpoch{}, mcc_serialization_params_t{}},
|
||||||
|
mcc_simple_kv_record_t{
|
||||||
|
"ddd", MccAngle{11.5_degs}, MccAngle{11.5_degs},
|
||||||
|
mcc_serialization_params_t{.angle_format = mcc::MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS}},
|
||||||
|
mcc_make_simple_kv_record("eee", 1.5),
|
||||||
|
mcc_make_simple_kv_record("arr", std::vector<int>{1, 2, 3, 4, 5, 6, 7}),
|
||||||
|
mcc_make_simple_kv_record("vt", VT(77)),
|
||||||
|
mcc_make_simple_kv_record("sarr", std::array<double, 3>{1, 2, 3}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static std::string STR = R"--(
|
||||||
|
|
||||||
|
aaa = dewl_ewkj23+23998
|
||||||
|
|
||||||
|
#
|
||||||
|
# this is angle
|
||||||
|
bb=1.24534
|
||||||
|
cc= 2026-05-15T05:53:20.921723918 # date UTC
|
||||||
|
|
||||||
|
)--";
|
||||||
|
|
||||||
|
static std::string STR1 = R"--(
|
||||||
|
aaa = dewl_ewkj23+23998
|
||||||
|
|
||||||
|
#
|
||||||
|
# this is obs date
|
||||||
|
cc= 2026-05-15T05:53:20.921723918 # date UTC
|
||||||
|
|
||||||
|
ddd = 01:02:33.434 # HA in hours:mins:secs
|
||||||
|
)--";
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::error_code err;
|
||||||
|
std::string buff;
|
||||||
|
|
||||||
|
MccKeyValueHolder kv(kv_desc);
|
||||||
|
|
||||||
|
err = kv.toCharRange(buff);
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::println("DEFAULT VALUES:");
|
||||||
|
std::println("--(\n{})--", buff);
|
||||||
|
std::println("\n\n");
|
||||||
|
|
||||||
|
|
||||||
|
err = kv.setValue("eee", 15.1515);
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto err = kv.fromCharRange(STR);
|
||||||
|
err = kv.fromCharRange(STR1);
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("{} = {}", "bb", kv.getValue<MccAngle>(std::string{"bb"}).value().sexagesimal());
|
||||||
|
std::println("{} = {}", "cc", kv.getValue<MccCelestialCoordEpoch>("cc").value().UTC());
|
||||||
|
|
||||||
|
err = kv.setValue("cc", std::chrono::system_clock::now());
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = kv.setValue("aaa", "OK");
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = kv.setValue("ddd", 37.5_degs);
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = kv.setValue("arr", std::array{10, 20, 30});
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = kv.setValue("sarr", std::vector{10, 20, 30, 40, 50});
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("------------------------------------");
|
||||||
|
|
||||||
|
|
||||||
|
buff.clear();
|
||||||
|
err = kv.toCharRange<decltype(kv)::OPOLICY_FULL>(buff);
|
||||||
|
// err = kv.toCharRange(buff);
|
||||||
|
if (err) {
|
||||||
|
std::println("ERR = {}", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("--(\n{}\n)--", buff);
|
||||||
|
|
||||||
|
std::print("KEYS: ");
|
||||||
|
for (auto const& k : kv.keys()) {
|
||||||
|
std::print("{} ", k);
|
||||||
|
}
|
||||||
|
std::println("");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user