diff --git a/mcc_concepts.h b/mcc_concepts.h index fbbc2b2..7156946 100644 --- a/mcc_concepts.h +++ b/mcc_concepts.h @@ -147,6 +147,11 @@ concept mcc_fp_type_like_c = /* GEOMETRICAL ANGLE REPRESENTATION CLASS CONCEPT */ +/* REQUIREMENT: in the MCC-library it is assumed that an arithmetic representation of angles are measured in the + radians!!! This means that possible conversion operator 'SOME_USER_ANGLE_CLASS::operator double()' + must return an angle in radians! + */ + template concept mcc_angle_c = mcc_fp_type_like_c && requires(T v, double vd) { // mandatory arithmetic operations @@ -783,6 +788,13 @@ struct mcc_telemetry_interface_t { { return std::forward(self).setTarget(pt); } + + // get entered target position + template SelfT> + RetT setTarget(this SelfT&& self, mcc_skypoint_c auto* pt) + { + return std::forward(self).getTarget(pt); + } }; template diff --git a/mcc_constants.h b/mcc_constants.h index bc62a65..4e521f1 100644 --- a/mcc_constants.h +++ b/mcc_constants.h @@ -26,6 +26,8 @@ constexpr double MCC_TWO_PI = std::numbers::pi * 2.0; static constexpr double MCC_SIDERAL_TO_UT1_RATIO = 1.002737909350795; // sideral/UT1 +static constexpr double MCC_J2000_MJD = 51544.5; + // a value to represent of infinite time duration according to type of duration representation template diff --git a/mcc_ser.h b/mcc_ser.h new file mode 100644 index 0000000..32dac55 --- /dev/null +++ b/mcc_ser.h @@ -0,0 +1,447 @@ +#pragma once + +#include "mcc_coordinate.h" +#include "mcc_serialization_common.h" + +namespace mcc::impl +{ + +enum class MccSerializerErrorCode : int { + ERROR_OK, + ERROR_UNDERLYING_SERIALIZER, + ERROR_INVALID_EPOCH, + ERROR_COORD_TRANSFORM +}; + +} // namespace mcc::impl + + + +namespace std +{ + +template <> +class is_error_code_enum : public true_type +{ +}; + +} // namespace std + + +namespace mcc::impl +{ + +// error category +struct MccSerializerCategory : public std::error_category { + MccSerializerCategory() : std::error_category() {} + + const char* name() const noexcept + { + return "MCC-SERIALIZER-ERR-CATEGORY"; + } + + std::string message(int ec) const + { + MccSerializerErrorCode err = static_cast(ec); + + switch (err) { + case MccSerializerErrorCode::ERROR_OK: + return "OK"; + case MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER: + return "error returned by underlying serializer"; + case MccSerializerErrorCode::ERROR_INVALID_EPOCH: + return "invalid coordinate epoch"; + case MccSerializerErrorCode::ERROR_COORD_TRANSFORM: + return "coordinates transformation error"; + default: + return "UNKNOWN"; + } + } + + static const MccSerializerCategory& get() + { + static const MccSerializerCategory constInst; + return constInst; + } +}; + + +inline std::error_code make_error_code(MccSerializerErrorCode ec) +{ + return std::error_code(static_cast(ec), MccSerializerCategory::get()); +} + + +/* BASE SERIALIZER CLASS (FOR IMPLEMENTATIONS BELOW) */ + +struct MccSerializerBase : mcc_serializer_interface_t { + virtual ~MccSerializerBase() = default; + + using typename mcc_serializer_interface_t::error_t; + +protected: + MccSerializerBase() = default; + + enum CoordType { CO_LON, CO_LAT }; + + static void addElemDelimiter(traits::mcc_output_char_range auto& output, + mcc_serialization_params_c auto const& params) + { + std::format_to(std::back_inserter(output), "{}", params.elem_delim); + } + + + static void addSeqDelimiter(traits::mcc_output_char_range auto& output, + mcc_serialization_params_c auto const& params) + { + std::format_to(std::back_inserter(output), "{}", params.seq_delim); + } + + + // set serialized angle format according to coordinates pair format and type of + // serializing mcc_coord_pair_c::pairKind + template + static void angleFormatFromCoordPairType(mcc_serialization_params_c auto& pars) + { + if (pars.coordpair_format == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES) { + pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES; + } else { // format to sexagesimal form according to celestial coordinate type + if constexpr (TYPE == MccSerializerBase::CO_LON) { + if (pars.coordpair_format == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGDEG) { + pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS; + } else if (pars.coordpair_format == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG) { + if constexpr (PAIRKIND == MccCoordPairKind::COORDS_KIND_AZZD || + PAIRKIND == MccCoordPairKind::COORDS_KIND_AZALT || + PAIRKIND == MccCoordPairKind::COORDS_KIND_XY || + PAIRKIND == MccCoordPairKind::COORDS_KIND_GENERIC) { // azimuth is in degrees + pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS; + } else { // RA or HA + pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS; + } + } else { + // !!!!!!!!!!!!!!!!!! + } + } else { // Y-coordinates (co-latitude one, DEC, ALT, ZD, generic X) is always in degrees for celestial + // point + pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS; + } + } + } + + template + requires(std::ranges::input_range && std::same_as>) + static error_t serializeRange(mcc_serializer_c auto& sr, + R const& r, + traits::mcc_output_char_range auto& output, + mcc_serialization_params_c auto const& params) + { + size_t i = 0, N = std::ranges::size(r); + + for (auto const& el : r) { + auto err = sr(output, el, params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + if (++i < N) { + MccSerializerBase::addSeqDelimiter(output, params); + } + } + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +/* MAIN (FALLBACK) TEMPLATED IMPLEMENTATION */ + +template +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-FALLBACK-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + if constexpr (std::formattable) { + } else if constexpr (std::convertible_to) { + auto err = MccSerializer{}(output, static_cast(value), params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + } else if constexpr (std::ranges::range) { + using value_t = std::remove_cv_t>; + + // special range (character sequence) + if constexpr (std::same_as) { + std::string str; + std::ranges::copy(value, std::back_inserter(str)); + + auto err = MccSerializer{}(output, str, params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + } else { + MccSerializer sr; + + return MccSerializerBase::serializeRange(sr, value, output, params); + } + } else { + static_assert(false, "UNSUPPORTED TYPE!!!"); + } + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +/* SPECIALIZATION FOR THE SOME CONCEPTS */ + +/* std::chrono::sys_time variants and its sequence */ + +template + requires traits::mcc_systime_c +struct MccSerializer : MccSerializerBase { + virtual ~MccSerializer() = default; + + constexpr static std::string_view serializerName{"MCC-SYSTIME-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(value)); + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +template + requires(!std::is_arithmetic_v && mcc_angle_c) +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-ANGLE-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + double v = (double)value; // radians (see mcc_angle_c concept) + std::string sgm; + + switch (params.angle_format) { + case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES: + v *= MCC_RADS_TO_DEGRESS; + return MccSerializer{}(output, v, params); + case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS: + if (params.norm_sxgm) { + sgm = utils::rad2sxg(v, false, params.angle_prec.deg_prec); + } else { + sgm = utils::rad2sxg(v, false, params.angle_prec.deg_prec); + } + + break; + case MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS: + if (params.norm_sxgm) { + sgm = utils::rad2sxg(v, true, params.angle_prec.hour_prec); + } else { + sgm = utils::rad2sxg(v, true, params.angle_prec.hour_prec); + } + + break; + default: + break; + } + + auto err = MccSerializer{}(output, sgm, params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + return MccSerializerErrorCode::ERROR_OK; + }; +}; + + +template +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-COORD-EPOCH-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + double jd; + + switch (params.timepoint_format) { + case MccTimePointFormat::MCC_TIMEPOINT_FORMAT_DATE: { + auto tp = value.UTC(); + auto err = MccSerializer{}(output, tp, params); + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + case MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JEPOCH: { + auto ep = value.JEpoch(); + auto err = MccSerializer{}(output, ep, params); + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + case MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JD: + jd = value.MJD() + MCC_J2000_MJD; + break; + case MccTimePointFormat::MCC_TIMEPOINT_FORMAT_MJD: + jd = value.MJD(); + break; + } + + + auto err = MccSerializer{}(output, jd, params); + + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +template +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-COORD-PAIR-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + std::conditional_t, std::nullptr_t, mcc_serialization_params_t> pars = + std::is_null_pointer_v ? nullptr : params; + + pars.norm_sxgm = true; + pars.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG; + + // X-coordinate + MccSerializerBase::angleFormatFromCoordPairType(pars); + + auto err = MccSerializer{}(output, value.x(), params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + MccSerializerBase::addElemDelimiter(output, params); + + pars.norm_sxgm = false; // do not normalize co-latitude angle + + // Y-coordinate + MccSerializerBase::angleFormatFromCoordPairType(pars); + + err = MccSerializer{}(output, value.y(), params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + MccSerializerBase::addElemDelimiter(output, params); + + // epoch + auto ep = value.epoch(); + auto ep_err = MccSerializer{}(output, ep, params); + if (ep_err) { + return mcc_deduced_err(ep_err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + + MccSerializerBase::addElemDelimiter(output, params); + + // pair kind + return mcc_deduced_err(MccSerializer{}(output, MccCoordPairKindToStr(VT::pairKind), params), + MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + + return MccSerializerErrorCode::ERROR_OK; + } +}; + + +template +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-SKYPOINT-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + auto serialize_cpair = [&](T& cp) { + auto ccte_err = value.to(cp); + if (ccte_err) { + return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM); + } + + auto err = MccSerializer{}(output, cp, params); + if (err) { + return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER); + } + + return MccSerializerErrorCode::ERROR_OK; + }; + + switch (value.pairKind()) { + case MccCoordPairKind::COORDS_KIND_RADEC_ICRS: { + MccSkyRADEC_ICRS cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_RADEC_OBS: { + MccSkyRADEC_OBS cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_RADEC_APP: { + MccSkyRADEC_APP cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_HADEC_OBS: { + MccSkyHADEC_OBS cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_HADEC_APP: { + MccSkyHADEC_APP cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_AZZD: { + MccSkyAZZD cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_AZALT: { + MccSkyAZALT cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_XY: { + MccGenXY cp; + return serialize_cpair(cp); + } + case MccCoordPairKind::COORDS_KIND_GENERIC: { + MccGenXY cp; + return serialize_cpair(cp); + } + default: + // !!!!!!!!!!!! + } + } +}; + + +template +struct MccSerializer : MccSerializerBase { + constexpr static std::string_view serializerName{"MCC-TELEMETRY-DATA-SERIALIZER"}; + + template + error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr) + { + // FORMAT: RA_OBS_MOUNT, DEC_OBS_MOUNT, RA_APP_MOUNT, DEC_APP_MOUNT, HA_APP_MOUNT, AZ_MOUNT, ZD_MOUNT, + // REFR_CORR_MOUNT, LAST, ENC_X, ENC_Y, PCM_X, PCM_Y, RA_APP_TAG, DEC_APP_TAG, AZ_TAG, ZD_TAG, TIMEPOINT + + // NOTE: One must assume that the returned RA coordinates are in format of underlying celestial coordinate + // transformation engine used in the mcc_skypoint_c class implementation. E.g. ERFA-library uses the + // CIO-based representation of RA + + std::conditional_t, std::nullptr_t, mcc_serialization_params_t> pars = + std::is_null_pointer_v ? nullptr : params; + + pars.norm_sxgm = true; + pars.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG; + + // RA_OBS_MOUNT + MccSerializerBase::angleFormatFromCoordPairType(pars); + } +}; + +} // namespace mcc::impl diff --git a/mcc_serialization_common.h b/mcc_serialization_common.h index 42ab720..bed1243 100644 --- a/mcc_serialization_common.h +++ b/mcc_serialization_common.h @@ -17,6 +17,51 @@ namespace mcc { + +/* celestial angle serialization */ + +enum class MccSerializedAngleFormat { + MCC_SERIALIZED_FORMAT_DEGREES, // degrees as floating-point number + MCC_SERIALIZED_FORMAT_SXGM_HOURS, // sexagesimal representation: hours:mins:secs + MCC_SERIALIZED_FORMAT_SXGM_DEGS, // sexagesimal representation: degs:arcmins:arcsecs + MCC_SERIALIZED_FORMAT_UNKNOWN +}; + +static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR = "SRANG-FORMAT-DEGREES"; +static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR = "SRANG-FORMAT-SXGM_HOURDEG"; +static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR = "SRANG-FORMAT-SXGM_DEGDEG"; + + +static constexpr std::string_view MccSerializedAngleFormatToStr(MccSerializedAngleFormat fmt) +{ + return fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES ? MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR + : fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS + ? MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR + : fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS ? MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR + : MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR; +} + +template +static constexpr MccSerializedAngleFormat MccSerializedAngleFormatStrToValue(R&& str) +{ + if constexpr (std::is_array_v>) { + return MccSerializedAngleFormatStrToValue(std::string_view{str}); + } + + const auto hash = mcc::utils::FNV1aHash(std::forward(str)); + + return hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR) + ? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES + : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR) + ? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS + : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR) + ? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS + : MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_UNKNOWN; +} + + +/* coordinates pair serialization */ + enum class MccSerializedCoordPairFormat { MCC_SERIALIZED_FORMAT_DEGREES, // both angles are in degrees as floating-point number MCC_SERIALIZED_FORMAT_SXGM_HOURDEG, // X is in hour and Y is in degree sexagesimal representation @@ -24,19 +69,19 @@ enum class MccSerializedCoordPairFormat { MCC_SERIALIZED_FORMAT_UNKNOWN }; -static constexpr std::string_view MCC_SERIALIZED_FORMAT_DEGREES_STR = "SRCP-FORMAT-DEGREES"; -static constexpr std::string_view MCC_SERIALIZED_FORMAT_SXGM_HOURDEG_STR = "SRCP-FORMAT-SXGM_HOURDEG"; -static constexpr std::string_view MCC_SERIALIZED_FORMAT_SXGM_DEGDEG_STR = "SRCP-FORMAT-SXGM_DEGDEG"; +static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_DEGREES_STR = "SRCP-FORMAT-DEGREES"; +static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR = "SRCP-FORMAT-SXGM_HOURDEG"; +static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR = "SRCP-FORMAT-SXGM_DEGDEG"; static constexpr std::string_view MccSerializedCoordPairFormatToStr(MccSerializedCoordPairFormat fmt) { - return fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES ? MCC_SERIALIZED_FORMAT_DEGREES_STR + return fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES ? MCC_SERIALIZED_CP_FORMAT_DEGREES_STR : fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG - ? MCC_SERIALIZED_FORMAT_SXGM_HOURDEG_STR + ? MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR : fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGDEG - ? MCC_SERIALIZED_FORMAT_SXGM_DEGDEG_STR - : MCC_SERIALIZED_FORMAT_DEGREES_STR; + ? MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR + : MCC_SERIALIZED_CP_FORMAT_DEGREES_STR; } template @@ -48,17 +93,19 @@ static constexpr MccSerializedCoordPairFormat MccSerializedCoordPairFormatStrToV const auto hash = mcc::utils::FNV1aHash(std::forward(str)); - return hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_FORMAT_DEGREES_STR) + return hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_DEGREES_STR) ? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES - : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_FORMAT_SXGM_HOURDEG_STR) + : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR) ? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG - : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_FORMAT_SXGM_DEGDEG_STR) + : hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR) ? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGDEG : MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN; } -struct MccSerializedCoordPairFormatPrec { +/* precision of representation of serialized celestial angle/coordinates pair */ + +struct MccSerializedAngleFormatPrec { uint8_t hour_prec = 2; // number of decimal places in hour seconds (sexagesimal format) uint8_t deg_prec = 1; // number of decimal places in arcseconds (sexagesimal format) // slightly better than 0.1 arcsecond precision @@ -120,10 +167,14 @@ concept mcc_serialization_params_c = requires(T t) { requires traits::mcc_output_char_range; requires traits::mcc_output_char_range; + requires std::same_as; + requires std::same_as; requires std::same_as; - requires std::same_as; requires std::same_as; + // a format string for mcc_systime_c types (std;:chrono::sys_time) + requires std::same_as; + // if true - normalize angle in sexagesimal format (to control rounding) // (to avoid something like "24:00:00.0" for sexagesimal 'hours:minutes:seconds' format) requires std::convertible_to; @@ -148,6 +199,12 @@ struct mcc_serializer_interface_t { return std::forward(self)(output, value); } + template SelfT, traits::mcc_output_char_range R, typename ValueT> + RetT operator()(this SelfT&& self, R& output, ValueT const& value, mcc_serialization_params_c auto const& params) + { + return std::forward(self)(output, value, params); + } + protected: mcc_serializer_interface_t() = default; }; @@ -159,12 +216,12 @@ concept mcc_serializer_c = // static const variable with name of the serializer requires std::formattable && std::is_const_v; - // must define a type "params_t" - requires mcc_serialization_params_c; + // // must define a type "params_t" + // requires mcc_serialization_params_c; - { t.setParams(std::declval()) }; + // { t.setParams(std::declval()) }; - { t_const.getParams() } -> std::same_as; + // { t_const.getParams() } -> std::same_as; }; @@ -181,6 +238,12 @@ struct mcc_deserializer_interface_t { return std::forward(self)(input, value); } + template SelfT, traits::mcc_input_char_range R, typename ValueT> + RetT operator()(this SelfT&& self, R const& input, ValueT& value, mcc_serialization_params_c auto& params) + { + return std::forward(self)(input, value, params); + } + protected: mcc_deserializer_interface_t() = default; }; @@ -193,12 +256,12 @@ concept mcc_deserializer_c = requires std::formattable && std::is_const_v; - // must define a type "params_t" - requires mcc_serialization_params_c; + // // must define a type "params_t" + // requires mcc_serialization_params_c; - { t.setParams(std::declval()) }; + // { t.setParams(std::declval()) }; - { t_const.getParams() } -> std::same_as; + // { t_const.getParams() } -> std::same_as; }; @@ -213,19 +276,24 @@ struct mcc_serialization_params_t { std::string seq_delim{MCC_SERIALIZING_DEFAULT_SEQ_DELIMITER}; std::string elem_delim{MCC_SERIALIZING_DEFAULT_ELEM_DELIMITER}; + MccSerializedAngleFormat angle_format{MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES}; + + MccSerializedAngleFormatPrec angle_prec{MccSerializedAngleFormatPrec{.hour_prec = 2, .deg_prec = 1, .decimals = 6}}; + MccSerializedCoordPairFormat coordpair_format{MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG}; - MccSerializedCoordPairFormatPrec coordpair_prec{ - MccSerializedCoordPairFormatPrec{.hour_prec = 2, .deg_prec = 1, .decimals = 6}}; - MccTimePointFormat timepoint_format{MccTimePointFormat::MCC_TIMEPOINT_FORMAT_DATE}; + std::string_view systime_format{"{:%FT%T}"}; + bool norm_sxgm{false}; bool sxgm_hms{false}; }; +static_assert(mcc_serialization_params_c, "!!!"); + namespace details { @@ -244,7 +312,7 @@ struct _params_manipulator_t { _params.seq_delim = pars.seq_delim; _params.elem_delim = pars.elem_delim; _params.coordpair_format = pars.coordpair_format; - _params.coordpair_prec = pars.coordpair_prec; + _params.angle_prec = pars.angle_prec; _params.timepoint_format = pars.timepoint_format; _params.norm_sxgm = pars.norm_sxgm; _params.sxgm_hms = pars.sxgm_hms; @@ -260,7 +328,7 @@ struct _params_manipulator_t { pars.seq_delim = _params.seq_delim; pars.elem_delim = _params.elem_delim; pars.coordpair_format = _params.coordpair_format; - pars.coordpair_prec = _params.coordpair_prec; + pars.angle_prec = _params.angle_prec; pars.timepoint_format = _params.timepoint_format; pars.norm_sxgm = _params.norm_sxgm; pars.sxgm_hms = _params.sxgm_hms; @@ -283,30 +351,40 @@ protected: } // namespace details -template -struct MccSerializerBase : mcc_serializer_interface_t, details::_params_manipulator_t { - virtual ~MccSerializerBase() = default; - using typename mcc_serializer_interface_t::error_t; - - using typename details::_params_manipulator_t::params_t; - -protected: - MccSerializerBase() = default; -}; - -template -struct MccDeserializerBase : mcc_deserializer_interface_t, details::_params_manipulator_t { +struct MccDeserializerBase : mcc_deserializer_interface_t { virtual ~MccDeserializerBase() = default; using typename mcc_deserializer_interface_t::error_t; - using typename details::_params_manipulator_t::params_t; - protected: MccDeserializerBase() = default; }; +// template +// struct MccSerializerBase : mcc_serializer_interface_t, details::_params_manipulator_t { +// virtual ~MccSerializerBase() = default; + +// using typename mcc_serializer_interface_t::error_t; + +// using typename details::_params_manipulator_t::params_t; + +// protected: +// MccSerializerBase() = default; +// }; + +// template +// struct MccDeserializerBase : mcc_deserializer_interface_t, details::_params_manipulator_t { +// virtual ~MccDeserializerBase() = default; + +// using typename mcc_deserializer_interface_t::error_t; + +// using typename details::_params_manipulator_t::params_t; + +// protected: +// MccDeserializerBase() = default; +// }; + } // namespace impl } // namespace mcc diff --git a/mcc_telemetry.h b/mcc_telemetry.h index 72491ab..333fcab 100644 --- a/mcc_telemetry.h +++ b/mcc_telemetry.h @@ -286,6 +286,14 @@ public: } + error_t getTarget(mcc_skypoint_c auto* sp) + { + sp = _enteredTargetPos; + + return MccTelemetryErrorCode::ERROR_OK; + } + + // // blocks the current thread until telemetry data is received. // the maximum blocking time is equal to the set timeout (see setTelemetryDataTimeout method)