...
This commit is contained in:
25
mcc_angle.h
25
mcc_angle.h
@@ -657,7 +657,7 @@ static constexpr std::string_view MCC_COORDPAIR_KIND_HADEC_OBS_STR = "HADEC-OBS"
|
|||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_AZALT_STR = "AZALT";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_AZALT_STR = "AZALT";
|
||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_AZZD_STR = "AZZD";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_AZZD_STR = "AZZD";
|
||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_XY_STR = "XY";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_XY_STR = "XY";
|
||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_LATLON_STR = "LATLON";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_LONLAT_STR = "LATLON";
|
||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_GENERIC_STR = "GENERIC";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_GENERIC_STR = "GENERIC";
|
||||||
static constexpr std::string_view MCC_COORDPAIR_KIND_UNKNOWN_STR = "UNKNOWN";
|
static constexpr std::string_view MCC_COORDPAIR_KIND_UNKNOWN_STR = "UNKNOWN";
|
||||||
|
|
||||||
@@ -671,7 +671,7 @@ static constexpr std::string_view MccCoordPairKindStr =
|
|||||||
: KIND == MccCoordPairKind::COORDS_KIND_AZALT ? MCC_COORDPAIR_KIND_AZALT_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_AZALT ? MCC_COORDPAIR_KIND_AZALT_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_AZZD ? MCC_COORDPAIR_KIND_AZZD_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_AZZD ? MCC_COORDPAIR_KIND_AZZD_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_XY ? MCC_COORDPAIR_KIND_XY_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_XY ? MCC_COORDPAIR_KIND_XY_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_LONLAT ? MCC_COORDPAIR_KIND_LATLON_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_LONLAT ? MCC_COORDPAIR_KIND_LONLAT_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_GENERIC ? MCC_COORDPAIR_KIND_GENERIC_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_GENERIC ? MCC_COORDPAIR_KIND_GENERIC_STR
|
||||||
: MCC_COORDPAIR_KIND_UNKNOWN_STR;
|
: MCC_COORDPAIR_KIND_UNKNOWN_STR;
|
||||||
|
|
||||||
@@ -686,7 +686,7 @@ static constexpr std::string_view MccCoordPairKindToStr(MccCoordPairKind KIND)
|
|||||||
: KIND == MccCoordPairKind::COORDS_KIND_AZALT ? MCC_COORDPAIR_KIND_AZALT_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_AZALT ? MCC_COORDPAIR_KIND_AZALT_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_AZZD ? MCC_COORDPAIR_KIND_AZZD_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_AZZD ? MCC_COORDPAIR_KIND_AZZD_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_XY ? MCC_COORDPAIR_KIND_XY_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_XY ? MCC_COORDPAIR_KIND_XY_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_LONLAT ? MCC_COORDPAIR_KIND_LATLON_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_LONLAT ? MCC_COORDPAIR_KIND_LONLAT_STR
|
||||||
: KIND == MccCoordPairKind::COORDS_KIND_GENERIC ? MCC_COORDPAIR_KIND_GENERIC_STR
|
: KIND == MccCoordPairKind::COORDS_KIND_GENERIC ? MCC_COORDPAIR_KIND_GENERIC_STR
|
||||||
: MCC_COORDPAIR_KIND_UNKNOWN_STR;
|
: MCC_COORDPAIR_KIND_UNKNOWN_STR;
|
||||||
}
|
}
|
||||||
@@ -709,10 +709,27 @@ static constexpr MccCoordPairKind MccCoordStrToPairKind(R&& spair)
|
|||||||
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_AZALT_STR) ? MccCoordPairKind::COORDS_KIND_AZALT
|
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_AZALT_STR) ? MccCoordPairKind::COORDS_KIND_AZALT
|
||||||
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_AZZD_STR) ? MccCoordPairKind::COORDS_KIND_AZZD
|
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_AZZD_STR) ? MccCoordPairKind::COORDS_KIND_AZZD
|
||||||
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_XY_STR) ? MccCoordPairKind::COORDS_KIND_XY
|
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_XY_STR) ? MccCoordPairKind::COORDS_KIND_XY
|
||||||
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_LATLON_STR) ? MccCoordPairKind::COORDS_KIND_LONLAT
|
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_LONLAT_STR) ? MccCoordPairKind::COORDS_KIND_LONLAT
|
||||||
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_GENERIC_STR) ? MccCoordPairKind::COORDS_KIND_GENERIC
|
: hash == mcc::utils::FNV1aHash(MCC_COORDPAIR_KIND_GENERIC_STR) ? MccCoordPairKind::COORDS_KIND_GENERIC
|
||||||
: MccCoordPairKind::COORDS_KIND_UNKNOWN;
|
: MccCoordPairKind::COORDS_KIND_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class MccCoordinatePairRep : int {
|
||||||
|
MCC_COORDPAIR_REP_DEGREES, // both angles are in decimal degrees
|
||||||
|
MCC_COORDPAIR_REP_SXGM_HOURDEG, // X is in hour and Y is in degree sexagesimal representation
|
||||||
|
MCC_COORDPAIR_REP_SXGM_DEGDEG // both angles are in sexagesimal degrees
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// default wide-acceptable sexagesimal representation
|
||||||
|
static constexpr MccCoordinatePairRep MccCoordinatePairToSxgmRep(MccCoordPairKind kind)
|
||||||
|
{
|
||||||
|
return kind == MccCoordPairKind::COORDS_KIND_AZALT || kind == MccCoordPairKind::COORDS_KIND_AZZD ||
|
||||||
|
kind == MccCoordPairKind::COORDS_KIND_XY || kind == MccCoordPairKind::COORDS_KIND_LONLAT ||
|
||||||
|
kind == MccCoordPairKind::COORDS_KIND_GENERIC
|
||||||
|
? MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_DEGDEG
|
||||||
|
: MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG; // RA-DEC or HA-DEC
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -10,8 +10,13 @@
|
|||||||
* *
|
* *
|
||||||
****************************************************************************************/
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "mcc_concepts.h"
|
#include "mcc_concepts.h"
|
||||||
#include "mcc_constants.h"
|
#include "mcc_coordinate.h"
|
||||||
|
#include "mcc_epoch.h"
|
||||||
#include "mcc_error.h"
|
#include "mcc_error.h"
|
||||||
|
|
||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
@@ -20,7 +25,7 @@ namespace mcc::impl
|
|||||||
enum class MccDeserializerErrorCode : int {
|
enum class MccDeserializerErrorCode : int {
|
||||||
ERROR_OK,
|
ERROR_OK,
|
||||||
ERROR_UNDERLYING_DESERIALIZER,
|
ERROR_UNDERLYING_DESERIALIZER,
|
||||||
ERROR_INVALID_SERIAL_VALUE,
|
ERROR_INVALID_SERIALIZED_VALUE,
|
||||||
ERROR_COORD_TRANSFORM
|
ERROR_COORD_TRANSFORM
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +66,7 @@ struct MccDeserializerCategory : public std::error_category {
|
|||||||
return "OK";
|
return "OK";
|
||||||
case MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER:
|
case MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER:
|
||||||
return "error returned by underlying deserializer";
|
return "error returned by underlying deserializer";
|
||||||
case MccDeserializerErrorCode::ERROR_INVALID_SERIAL_VALUE:
|
case MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE:
|
||||||
return "invalid serialized value";
|
return "invalid serialized value";
|
||||||
case MccDeserializerErrorCode::ERROR_COORD_TRANSFORM:
|
case MccDeserializerErrorCode::ERROR_COORD_TRANSFORM:
|
||||||
return "coordinates transformation error";
|
return "coordinates transformation error";
|
||||||
@@ -90,8 +95,11 @@ struct mcc_deserializer_interface_t {
|
|||||||
|
|
||||||
typedef RetT error_t;
|
typedef RetT error_t;
|
||||||
|
|
||||||
template <std::derived_from<mcc_deserializer_interface_t> SelfT, traits::mcc_input_char_range R, typename ValueT>
|
template <std::derived_from<mcc_deserializer_interface_t> SelfT,
|
||||||
RetT operator()(this SelfT&& self, R const& input, ValueT& value)
|
traits::mcc_input_char_range R,
|
||||||
|
typename ValueT,
|
||||||
|
typename... DeserParamsT>
|
||||||
|
RetT operator()(this SelfT&& self, R const& input, ValueT& value, DeserParamsT&&... params)
|
||||||
{
|
{
|
||||||
return std::forward<SelfT>(self)(input, value);
|
return std::forward<SelfT>(self)(input, value);
|
||||||
}
|
}
|
||||||
@@ -107,89 +115,46 @@ concept mcc_deserializer_c = std::derived_from<T, mcc_deserializer_interface_t<t
|
|||||||
namespace details
|
namespace details
|
||||||
{
|
{
|
||||||
|
|
||||||
struct MccDeserializerBase : mcc_deserializer_interface_t<impl::MccError> {
|
struct MccDeserializerBase : mcc_deserializer_interface_t<impl::MccError>, utils::mcc_elem_sequence_with_delim_t {
|
||||||
using typename mcc_deserializer_interface_t<impl::MccError>::error_t;
|
using typename mcc_deserializer_interface_t<impl::MccError>::error_t;
|
||||||
|
|
||||||
virtual ~MccDeserializerBase() = default;
|
virtual ~MccDeserializerBase() = default;
|
||||||
|
|
||||||
// set delimiter for elements of the range-type serialized value
|
|
||||||
template <traits::mcc_input_char_range R>
|
|
||||||
void setSeqDelimiter(R const& delim)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
|
||||||
setSeqDelimiter(std::string_view{delim});
|
|
||||||
} else {
|
|
||||||
_seqDelimiter.clear();
|
|
||||||
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::mcc_view_or_output_char_range R>
|
|
||||||
R getSeqDelimiter() const
|
|
||||||
{
|
|
||||||
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
|
||||||
return _seqDelimiter;
|
|
||||||
} else if constexpr (std::ranges::view<R>) {
|
|
||||||
return R{_seqDelimiter.begin(), _seqDelimiter.end()};
|
|
||||||
} else {
|
|
||||||
R r;
|
|
||||||
std::ranges::copy(_seqDelimiter, std::back_inserter(r));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getSeqDelimiter() const
|
|
||||||
{
|
|
||||||
return getSeqDelimiter<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <traits::mcc_input_char_range R>
|
|
||||||
void setElemDelimiter(R const& delim)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
|
||||||
setElemDelimiter(std::string_view{delim});
|
|
||||||
} else {
|
|
||||||
_elementDelimiter.clear();
|
|
||||||
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::mcc_view_or_output_char_range R>
|
|
||||||
R getElemDelimiter() const
|
|
||||||
{
|
|
||||||
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
|
||||||
return _elementDelimiter;
|
|
||||||
} else if constexpr (std::ranges::view<R>) {
|
|
||||||
return R{_elementDelimiter.begin(), _elementDelimiter.end()};
|
|
||||||
} else {
|
|
||||||
R r;
|
|
||||||
std::ranges::copy(_elementDelimiter, std::back_inserter(r));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getElemDelimiter() const
|
|
||||||
{
|
|
||||||
return getElemDelimiter<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MccDeserializerBase() = default;
|
MccDeserializerBase() = default;
|
||||||
|
|
||||||
// delimiter for sequence of serialized values
|
//
|
||||||
std::string _seqDelimiter{MCC_DEFAULT_SEQ_DELIMITER};
|
// empty == true, if the 'input' is empty or if all elements consist of only spaces
|
||||||
|
//
|
||||||
// delimiter for aggregative (multi-element) serialized value
|
std::vector<std::string_view> splitAggregateValue(traits::mcc_input_char_range auto const& input, bool& empty) const
|
||||||
std::string _elementDelimiter{MCC_DEFAULT_ELEM_DELIMITER};
|
|
||||||
|
|
||||||
template <typename VT, typename R>
|
|
||||||
requires(std::ranges::input_range<R> && std::same_as<VT, std::ranges::range_value_t<R>>)
|
|
||||||
error_t deserializingRange(mcc_deserializer_c auto& dsr, traits::mcc_input_char_range auto const& input, R& r) const
|
|
||||||
{
|
{
|
||||||
if (std::ranges::size(input) == 0) { // ignore empy input
|
std::vector<std::string_view> res;
|
||||||
|
|
||||||
|
if (std::ranges::size(input)) {
|
||||||
|
empty = true;
|
||||||
|
|
||||||
|
std::ranges::for_each(std::views::split(input, this->_elementDelimiter), [&res, &empty](auto const& el) {
|
||||||
|
std::back_inserter(res) = utils::trimSpaces(std::string_view{el.begin(), el.end()});
|
||||||
|
if (empty && res.back().size()) {
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VT, std::ranges::output_range<VT> R, typename... DeserParamsT>
|
||||||
|
error_t deserializingRange(mcc_deserializer_c auto& dsr,
|
||||||
|
traits::mcc_input_char_range auto const& input,
|
||||||
|
R& r,
|
||||||
|
DeserParamsT&&... params) const
|
||||||
|
{
|
||||||
|
if (std::ranges::size(input) == 0) { // ignore an empty input, just return empty range?!!
|
||||||
|
r = R{};
|
||||||
return MccDeserializerErrorCode::ERROR_OK;
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +163,7 @@ protected:
|
|||||||
|
|
||||||
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);
|
auto err = dsr(el, val, std::forward<DeserParamsT>(params)...);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
}
|
}
|
||||||
@@ -219,7 +184,8 @@ protected:
|
|||||||
} // namespace details
|
} // namespace details
|
||||||
|
|
||||||
|
|
||||||
//
|
/* fallback template: basic deserializer */
|
||||||
|
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
class MccDeserializer : public details::MccDeserializerBase
|
class MccDeserializer : public details::MccDeserializerBase
|
||||||
{
|
{
|
||||||
@@ -234,7 +200,7 @@ public:
|
|||||||
if constexpr (std::is_arithmetic_v<VT>) {
|
if constexpr (std::is_arithmetic_v<VT>) {
|
||||||
auto v = mcc::utils::numFromStr<VT>(trimSpaces(input));
|
auto v = mcc::utils::numFromStr<VT>(trimSpaces(input));
|
||||||
if (!v.has_value()) {
|
if (!v.has_value()) {
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIAL_VALUE;
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v.value();
|
value = v.value();
|
||||||
@@ -267,6 +233,17 @@ public:
|
|||||||
|
|
||||||
MccDeserializer<el_t> dsr;
|
MccDeserializer<el_t> dsr;
|
||||||
return deserializingRange<el_t>(dsr, input, value);
|
return deserializingRange<el_t>(dsr, input, value);
|
||||||
|
} else if constexpr (traits::mcc_time_duration_c<VT>) {
|
||||||
|
typename VT::rep vd;
|
||||||
|
|
||||||
|
MccDeserializer<typename VT::rep> dsr;
|
||||||
|
|
||||||
|
auto err = dsr(trimSpaces(input), vd);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = VT{vd};
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNSUPPORTED VALUE TYPE!!!");
|
static_assert(false, "UNSUPPORTED VALUE TYPE!!!");
|
||||||
}
|
}
|
||||||
@@ -276,4 +253,193 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_coord_epoch_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_coord_epoch_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_coord_epoch_c<VT>) { // scalar
|
||||||
|
bool ok = value.fromCharRange(input);
|
||||||
|
if (!ok) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
return deserializingRange(dsr, input, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(!std::is_arithmetic_v<VT> &&
|
||||||
|
(mcc_angle_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_angle_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>)))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
// if hms == true and the input sequence is a sexagesimal string then it interpretates angle as hours:mins:secs
|
||||||
|
// otherwise the input sequence is interpretated as decimal or sexagesimal degrees
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value, bool hms = false)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_angle_c<VT>) { // scalar
|
||||||
|
auto res = utils::parsAngleString(input, hms);
|
||||||
|
if (res) {
|
||||||
|
value = res.value();
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
if constexpr (std::invocable<MccDeserializer<value_t>, decltype(input), VT&, bool>) {
|
||||||
|
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
||||||
|
// (that is, it can interpret the third argument as a flag "false/true = only
|
||||||
|
// degrees/hour-like")
|
||||||
|
return deserializingRange<value_t>(dsr, input, value, hms);
|
||||||
|
} else {
|
||||||
|
return deserializingRange<value_t>(dsr, input, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_skypoint_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_skypoint_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_skypoint_c<VT>) { // scalar: X[elem-delim]Y{[elem-delim]TIME-POINT[elem-delim]PAIR-KIND}
|
||||||
|
bool empty; // exactly 2 or >3 elements
|
||||||
|
auto elems = splitAggregateValue(input, empty);
|
||||||
|
|
||||||
|
if (empty || (elems.size() < 2) || (elems.size() == 3)) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccCoordPairKind pair_kind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||||
|
MccCelestialCoordEpoch epoch; // J2000.0
|
||||||
|
|
||||||
|
MccAngle x, y;
|
||||||
|
MccDeserializer<MccAngle> dsr_ang;
|
||||||
|
|
||||||
|
typename MccDeserializer<MccAngle>::error_t dsr_err;
|
||||||
|
|
||||||
|
if (elems.size() >= 4) { // X, Y, TIME-POINT, PAIR-KIND
|
||||||
|
// first, get pair-kind
|
||||||
|
pair_kind = MccCoordStrToPairKind(elems[3]);
|
||||||
|
if (pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoch
|
||||||
|
bool ok = epoch.fromCharRange(elems[2]);
|
||||||
|
if (!ok) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elems.size() >= 2) { // if == 2: just X and Y (if so it is interpretated as RADEC_ICRS)
|
||||||
|
if (MccCoordinatePairToSxgmRep(pair_kind) == MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG) {
|
||||||
|
// if input X-angle is in sexagesimal from then interpretate it in hours::mins::secs format
|
||||||
|
if constexpr (std::invocable<MccDeserializer<MccAngle>, decltype(elems[0]), MccAngle&, bool>) {
|
||||||
|
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
||||||
|
// (that is, it can interpret the third argument as a flag "false/true = only
|
||||||
|
// degrees/hour-like")
|
||||||
|
dsr_err = dsr_ang(elems[0], x, true);
|
||||||
|
} else {
|
||||||
|
dsr_err = dsr_ang(elems[0], x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dsr_err = dsr_ang(elems[0], x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dsr_err) {
|
||||||
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dsr_err = dsr_ang(elems[1], y);
|
||||||
|
|
||||||
|
if (dsr_err) {
|
||||||
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (pair_kind) {
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||||
|
value.from(MccSkyRADEC_ICRS{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_OBS:
|
||||||
|
value.from(MccSkyRADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||||
|
value.from(MccSkyRADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_OBS:
|
||||||
|
value.from(MccSkyHADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||||
|
value.from(MccSkyHADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZZD:
|
||||||
|
value.from(MccSkyAZZD{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZALT:
|
||||||
|
value.from(MccSkyAZALT{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_XY:
|
||||||
|
value.from(MccGenXY{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_GENERIC:
|
||||||
|
value.from(MccCoordPair{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_LONLAT:
|
||||||
|
value.from(MccGeoLONLAT{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
return deserializingRange<value_t>(dsr, input, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -122,84 +122,14 @@ concept mcc_serializer_c = std::derived_from<T, mcc_serializer_interface_t<typen
|
|||||||
namespace details
|
namespace details
|
||||||
{
|
{
|
||||||
|
|
||||||
struct MccSerializerBase : mcc_serializer_interface_t<impl::MccError> {
|
struct MccSerializerBase : mcc_serializer_interface_t<impl::MccError>, utils::mcc_elem_sequence_with_delim_t {
|
||||||
using typename mcc_serializer_interface_t<impl::MccError>::error_t;
|
using typename mcc_serializer_interface_t<impl::MccError>::error_t;
|
||||||
|
|
||||||
virtual ~MccSerializerBase() = default;
|
virtual ~MccSerializerBase() = default;
|
||||||
|
|
||||||
// set delimiter for elements of the range-type serialized value
|
|
||||||
template <traits::mcc_input_char_range R>
|
|
||||||
void setSeqDelimiter(R const& delim)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
|
||||||
setSeqDelimiter(std::string_view{delim});
|
|
||||||
} else {
|
|
||||||
_seqDelimiter.clear();
|
|
||||||
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::mcc_view_or_output_char_range R>
|
|
||||||
R getSeqDelimiter() const
|
|
||||||
{
|
|
||||||
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
|
||||||
return _seqDelimiter;
|
|
||||||
} else if constexpr (std::ranges::view<R>) {
|
|
||||||
return R{_seqDelimiter.begin(), _seqDelimiter.end()};
|
|
||||||
} else {
|
|
||||||
R r;
|
|
||||||
std::ranges::copy(_seqDelimiter, std::back_inserter(r));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getSeqDelimiter() const
|
|
||||||
{
|
|
||||||
return getSeqDelimiter<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <traits::mcc_input_char_range R>
|
|
||||||
void setElemDelimiter(R const& delim)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
|
||||||
setElemDelimiter(std::string_view{delim});
|
|
||||||
} else {
|
|
||||||
_elementDelimiter.clear();
|
|
||||||
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::mcc_view_or_output_char_range R>
|
|
||||||
R getElemDelimiter() const
|
|
||||||
{
|
|
||||||
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
|
||||||
return _elementDelimiter;
|
|
||||||
} else if constexpr (std::ranges::view<R>) {
|
|
||||||
return R{_elementDelimiter.begin(), _elementDelimiter.end()};
|
|
||||||
} else {
|
|
||||||
R r;
|
|
||||||
std::ranges::copy(_elementDelimiter, std::back_inserter(r));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getElemDelimiter() const
|
|
||||||
{
|
|
||||||
return getElemDelimiter<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MccSerializerBase() = default;
|
MccSerializerBase() = default;
|
||||||
|
|
||||||
// delimiter for sequence of serializing values
|
|
||||||
std::string _seqDelimiter{MCC_DEFAULT_SEQ_DELIMITER};
|
|
||||||
|
|
||||||
// delimiter for aggregative (multi-element) serializing value
|
|
||||||
std::string _elementDelimiter{MCC_DEFAULT_ELEM_DELIMITER};
|
|
||||||
|
|
||||||
template <typename VT, typename R>
|
template <typename VT, typename R>
|
||||||
requires(std::ranges::input_range<R> && std::same_as<VT, std::ranges::range_value_t<R>>)
|
requires(std::ranges::input_range<R> && std::same_as<VT, std::ranges::range_value_t<R>>)
|
||||||
error_t serializingRange(mcc_serializer_c auto& sr,
|
error_t serializingRange(mcc_serializer_c auto& sr,
|
||||||
|
|||||||
82
mcc_utils.h
82
mcc_utils.h
@@ -8,6 +8,8 @@
|
|||||||
#include <numbers>
|
#include <numbers>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
#include "mcc_constants.h"
|
||||||
#include "mcc_traits.h"
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
namespace mcc::utils
|
namespace mcc::utils
|
||||||
@@ -758,4 +760,84 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* a base class for some sequence of elements with delimiter */
|
||||||
|
|
||||||
|
struct mcc_elem_sequence_with_delim_t {
|
||||||
|
virtual ~mcc_elem_sequence_with_delim_t() = default;
|
||||||
|
|
||||||
|
// set delimiter for elements of the range-type serialized value
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
void setSeqDelimiter(R const& delim)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
setSeqDelimiter(std::string_view{delim});
|
||||||
|
} else {
|
||||||
|
_seqDelimiter.clear();
|
||||||
|
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R getSeqDelimiter() const
|
||||||
|
{
|
||||||
|
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
||||||
|
return _seqDelimiter;
|
||||||
|
} else if constexpr (std::ranges::view<R>) {
|
||||||
|
return R{_seqDelimiter.begin(), _seqDelimiter.end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(_seqDelimiter, std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getSeqDelimiter() const
|
||||||
|
{
|
||||||
|
return getSeqDelimiter<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
void setElemDelimiter(R const& delim)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
setElemDelimiter(std::string_view{delim});
|
||||||
|
} else {
|
||||||
|
_elementDelimiter.clear();
|
||||||
|
std::ranges::copy(delim, std::back_inserter(_seqDelimiter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R getElemDelimiter() const
|
||||||
|
{
|
||||||
|
if constexpr (std::same_as<R, decltype(_seqDelimiter)>) {
|
||||||
|
return _elementDelimiter;
|
||||||
|
} else if constexpr (std::ranges::view<R>) {
|
||||||
|
return R{_elementDelimiter.begin(), _elementDelimiter.end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(_elementDelimiter, std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getElemDelimiter() const
|
||||||
|
{
|
||||||
|
return getElemDelimiter<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mcc_elem_sequence_with_delim_t() = default;
|
||||||
|
|
||||||
|
// delimiter for sequence of serializing values
|
||||||
|
std::string _seqDelimiter{MCC_DEFAULT_SEQ_DELIMITER};
|
||||||
|
|
||||||
|
// delimiter for aggregative (multi-element) serializing value
|
||||||
|
std::string _elementDelimiter{MCC_DEFAULT_ELEM_DELIMITER};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::utils
|
} // namespace mcc::utils
|
||||||
|
|||||||
Reference in New Issue
Block a user