...
This commit is contained in:
parent
9c13def8be
commit
58d62d85b3
@ -473,7 +473,312 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Asibfm700MountConfig : protected ConfigHolder<decltype(Asibfm700MountConfigDefaults)>
|
class Asibfm700MountConfig : public mcc::utils::KeyValueHolder<decltype(Asibfm700MountConfigDefaults)>
|
||||||
|
{
|
||||||
|
using base_t = mcc::utils::KeyValueHolder<decltype(Asibfm700MountConfigDefaults)>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline static auto deserializer = []<typename VT>(std::string_view str, VT& value) {
|
||||||
|
std::error_code ec{};
|
||||||
|
|
||||||
|
if constexpr (std::is_arithmetic_v<VT> || mcc::traits::mcc_output_char_range<VT> || std::ranges::range<VT> ||
|
||||||
|
mcc::traits::mcc_time_duration_c<VT>) {
|
||||||
|
ec = base_t::defaultDeserializeFunc(str, value);
|
||||||
|
} else if constexpr (std::same_as<VT, mcc::MccAngle>) { // assume here all angles are in degrees
|
||||||
|
double vd;
|
||||||
|
ec = base_t::defaultDeserializeFunc(str, vd);
|
||||||
|
if (!ec) {
|
||||||
|
value = mcc::MccAngle(vd, mcc::MccDegreeTag{});
|
||||||
|
}
|
||||||
|
} else if constexpr (std::same_as<VT, mcc::MccDefaultPCMType>) {
|
||||||
|
std::string vstr;
|
||||||
|
ec = base_t::defaultDeserializeFunc(str, vstr);
|
||||||
|
|
||||||
|
if (!ec) {
|
||||||
|
auto s = mcc::utils::trimSpaces(vstr);
|
||||||
|
|
||||||
|
if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_BSPLINE>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_BSPLINE;
|
||||||
|
} else {
|
||||||
|
ec = std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ec = std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
};
|
||||||
|
|
||||||
|
void updateAll()
|
||||||
|
{
|
||||||
|
hardwarePollingPeriod = getValue<decltype(hardwarePollingPeriod)>("hardwarePollingPeriod").value_or({});
|
||||||
|
|
||||||
|
// CCTE
|
||||||
|
|
||||||
|
siteLatitude = getValue<mcc::MccAngle>("siteLatitude").value_or({});
|
||||||
|
siteLongitude = getValue<mcc::MccAngle>("siteLongitude").value_or({});
|
||||||
|
siteElevation = getValue<double>("siteElevation").value_or({});
|
||||||
|
refractWavelength = getValue<double>("refractWavelength").value_or({});
|
||||||
|
|
||||||
|
leapSecondFilename = getValue<std::string>("leapSecondFilename").value_or({});
|
||||||
|
bulletinAFilename = getValue<std::string>("bulletinAFilename").value_or({});
|
||||||
|
|
||||||
|
// prohibited zones
|
||||||
|
|
||||||
|
pzMinAltitude = getValue<mcc::MccAngle>("pzMinAltitude").value_or({});
|
||||||
|
pzLimitSwitchHAMin = getValue<mcc::MccAngle>("pzLimitSwitchHAMin").value_or({});
|
||||||
|
pzLimitSwitchHAMax = getValue<mcc::MccAngle>("pzLimitSwitchHAMax").value_or({});
|
||||||
|
|
||||||
|
|
||||||
|
// hardware config
|
||||||
|
|
||||||
|
servoControllerConfig.hwConfig = {};
|
||||||
|
|
||||||
|
servoControllerConfig.MountDevPath = getValue<std::string>("MountDevPath").value_or({});
|
||||||
|
servoControllerConfig.EncoderDevPath = getValue<std::string>("EncoderDevPath").value_or({});
|
||||||
|
servoControllerConfig.EncoderXDevPath = getValue<std::string>("EncoderXDevPath").value_or({});
|
||||||
|
servoControllerConfig.EncoderYDevPath = getValue<std::string>("EncoderYDevPath").value_or({});
|
||||||
|
|
||||||
|
servoControllerConfig.devConfig.MountDevPath = servoControllerConfig.MountDevPath.data();
|
||||||
|
servoControllerConfig.devConfig.EncoderDevPath = servoControllerConfig.EncoderDevPath.data();
|
||||||
|
servoControllerConfig.devConfig.EncoderXDevPath = servoControllerConfig.EncoderXDevPath.data();
|
||||||
|
servoControllerConfig.devConfig.EncoderYDevPath = servoControllerConfig.EncoderYDevPath.data();
|
||||||
|
|
||||||
|
servoControllerConfig.devConfig.RunModel = getValue<int>("RunModel").value_or({});
|
||||||
|
servoControllerConfig.devConfig.MountDevSpeed = getValue<int>("MountDevSpeed").value_or({});
|
||||||
|
servoControllerConfig.devConfig.EncoderDevSpeed = getValue<int>("EncoderDevSpeed").value_or({});
|
||||||
|
servoControllerConfig.devConfig.SepEncoder = getValue<int>("SepEncoder").value_or({});
|
||||||
|
|
||||||
|
std::chrono::duration<double> secs; // seconds as floating-point
|
||||||
|
|
||||||
|
secs = getValue<std::chrono::milliseconds>("MountReqInterval").value_or({});
|
||||||
|
servoControllerConfig.devConfig.MountReqInterval = secs.count();
|
||||||
|
|
||||||
|
secs = getValue<std::chrono::milliseconds>("EncoderReqInterval").value_or({});
|
||||||
|
servoControllerConfig.devConfig.EncoderReqInterval = secs.count();
|
||||||
|
|
||||||
|
secs = getValue<std::chrono::milliseconds>("EncoderSpeedInterval").value_or({});
|
||||||
|
servoControllerConfig.devConfig.EncoderSpeedInterval = secs.count();
|
||||||
|
|
||||||
|
std::vector<double> pid = getValue<std::vector<double>>("XPIDC").value_or({});
|
||||||
|
if (pid.size() > 2) {
|
||||||
|
servoControllerConfig.devConfig.XPIDC.P = pid[0];
|
||||||
|
servoControllerConfig.devConfig.XPIDC.I = pid[1];
|
||||||
|
servoControllerConfig.devConfig.XPIDC.D = pid[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("XPIDV").value_or({});
|
||||||
|
if (pid.size() > 2) {
|
||||||
|
servoControllerConfig.devConfig.XPIDV.P = pid[0];
|
||||||
|
servoControllerConfig.devConfig.XPIDV.I = pid[1];
|
||||||
|
servoControllerConfig.devConfig.XPIDV.D = pid[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("YPIDC").value_or({});
|
||||||
|
if (pid.size() > 2) {
|
||||||
|
servoControllerConfig.devConfig.YPIDC.P = pid[0];
|
||||||
|
servoControllerConfig.devConfig.YPIDC.I = pid[1];
|
||||||
|
servoControllerConfig.devConfig.YPIDC.D = pid[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("YPIDV").value_or({});
|
||||||
|
if (pid.size() > 2) {
|
||||||
|
servoControllerConfig.devConfig.YPIDV.P = pid[0];
|
||||||
|
servoControllerConfig.devConfig.YPIDV.I = pid[1];
|
||||||
|
servoControllerConfig.devConfig.YPIDV.D = pid[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// slew and track parameters
|
||||||
|
|
||||||
|
movingModelParams.telemetryTimeout =
|
||||||
|
getValue<decltype(movingModelParams.telemetryTimeout)>("telemetryTimeout").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.minTimeToPZone =
|
||||||
|
getValue<decltype(movingModelParams.minTimeToPZone)>("minTimeToPZone").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.updatingPZoneInterval =
|
||||||
|
getValue<decltype(movingModelParams.updatingPZoneInterval)>("updatingPZoneInterval").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.slewToleranceRadius =
|
||||||
|
getValue<decltype(movingModelParams.slewToleranceRadius)>("slewToleranceRadius").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.adjustCoordDiff =
|
||||||
|
getValue<decltype(movingModelParams.adjustCoordDiff)>("adjustCoordDiff").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.adjustCycleInterval =
|
||||||
|
getValue<decltype(movingModelParams.adjustCycleInterval)>("adjustCycleInterval").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.slewTimeout = getValue<decltype(movingModelParams.slewTimeout)>("slewTimeout").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.timeShiftToTargetPoint =
|
||||||
|
getValue<decltype(movingModelParams.timeShiftToTargetPoint)>("timeShiftToTargetPoint").value_or({});
|
||||||
|
|
||||||
|
movingModelParams.trackingCycleInterval =
|
||||||
|
getValue<decltype(movingModelParams.trackingCycleInterval)>("trackingCycleInterval").value_or({});
|
||||||
|
|
||||||
|
|
||||||
|
// PCM data
|
||||||
|
|
||||||
|
pcmData.type = getValue<decltype(pcmData.type)>("pcmType").value_or({});
|
||||||
|
|
||||||
|
pcmData.siteLatitude = getValue<mcc::MccAngle>("siteLatitude").value_or({});
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("pcmGeomCoeffs").value_or({});
|
||||||
|
if (pid.size() >= 9) { // must be 9 coefficients
|
||||||
|
pcmData.geomCoefficients = {.zeroPointX = pid[0],
|
||||||
|
.zeroPointY = pid[1],
|
||||||
|
.collimationErr = pid[2],
|
||||||
|
.nonperpendErr = pid[3],
|
||||||
|
.misalignErr1 = pid[4],
|
||||||
|
.misalignErr2 = pid[5],
|
||||||
|
.tubeFlexure = pid[6],
|
||||||
|
.forkFlexure = pid[7],
|
||||||
|
.DECaxisFlexure = pid[8]};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> dd = getValue<decltype(dd)>("pcmBsplineDegree").value_or({});
|
||||||
|
if (dd.size() >= 2) {
|
||||||
|
pcmData.bspline.bsplDegreeX = dd[0] > 0 ? dd[0] : 3;
|
||||||
|
pcmData.bspline.bsplDegreeY = dd[1] > 0 ? dd[1] : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("pcmBsplineXknots").value_or({});
|
||||||
|
// pid must contains interior and border (single point for each border) knots so minimal length must be 2
|
||||||
|
if (pid.size() >= 2) {
|
||||||
|
// generate full knots array (with border knots)
|
||||||
|
size_t Nknots = pid.size() + pcmData.bspline.bsplDegreeX * 2 - 2;
|
||||||
|
pcmData.bspline.knotsX.resize(Nknots);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= pcmData.bspline.bsplDegreeX; ++i) { // border knots
|
||||||
|
pcmData.bspline.knotsX[i] = pid[0];
|
||||||
|
pcmData.bspline.knotsX[Nknots - i - 1] = pid.back();
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < (pid.size() - 2); ++i) { // interior knots
|
||||||
|
pcmData.bspline.knotsX[i + pcmData.bspline.bsplDegreeX] = pid[1 + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("pcmBsplineYknots").value_or({});
|
||||||
|
// pid must contains interior and border (single point for each border) knots so minimal length must be 2
|
||||||
|
if (pid.size() >= 2) {
|
||||||
|
// generate full knots array (with border knots)
|
||||||
|
size_t Nknots = pid.size() + pcmData.bspline.bsplDegreeY * 2 - 2;
|
||||||
|
pcmData.bspline.knotsY.resize(Nknots);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= pcmData.bspline.bsplDegreeY; ++i) { // border knots
|
||||||
|
pcmData.bspline.knotsY[i] = pid[0];
|
||||||
|
pcmData.bspline.knotsY[Nknots - i - 1] = pid.back();
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < (pid.size() - 2); ++i) { // interior knots
|
||||||
|
pcmData.bspline.knotsY[i + pcmData.bspline.bsplDegreeY] = pid[1 + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// minimal allowed number of B-spline coefficients
|
||||||
|
size_t Ncoeffs = pcmData.type == mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY
|
||||||
|
? 0
|
||||||
|
: (pcmData.bspline.knotsX.size() - pcmData.bspline.bsplDegreeX - 1) *
|
||||||
|
(pcmData.bspline.knotsY.size() - pcmData.bspline.bsplDegreeY - 1);
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("pcmBsplineXcoeffs").value_or({});
|
||||||
|
|
||||||
|
if (pid.size() >= Ncoeffs) {
|
||||||
|
pcmData.bspline.coeffsX.resize(Ncoeffs);
|
||||||
|
for (size_t i = 0; i < Ncoeffs; ++i) {
|
||||||
|
pcmData.bspline.coeffsX[i] = pid[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getValue<std::vector<double>>("pcmBsplineYcoeffs").value_or({});
|
||||||
|
|
||||||
|
if (pid.size() >= Ncoeffs) {
|
||||||
|
pcmData.bspline.coeffsY.resize(Ncoeffs);
|
||||||
|
for (size_t i = 0; i < Ncoeffs; ++i) {
|
||||||
|
pcmData.bspline.coeffsY[i] = pid[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::chrono::milliseconds hardwarePollingPeriod{};
|
||||||
|
|
||||||
|
mcc::MccAngle siteLatitude{};
|
||||||
|
mcc::MccAngle siteLongitude{};
|
||||||
|
double siteElevation{};
|
||||||
|
double refractWavelength{};
|
||||||
|
|
||||||
|
std::string leapSecondFilename{};
|
||||||
|
std::string bulletinAFilename{};
|
||||||
|
|
||||||
|
mcc::MccAngle pzMinAltitude{};
|
||||||
|
mcc::MccAngle pzLimitSwitchHAMin{};
|
||||||
|
mcc::MccAngle pzLimitSwitchHAMax{};
|
||||||
|
|
||||||
|
|
||||||
|
AsibFM700ServoController::hardware_config_t servoControllerConfig{};
|
||||||
|
mcc::MccSimpleMovingModelParams movingModelParams{};
|
||||||
|
Asibfm700PCM::pcm_data_t pcmData{};
|
||||||
|
|
||||||
|
|
||||||
|
Asibfm700MountConfig() : base_t(Asibfm700MountConfigDefaults) {}
|
||||||
|
|
||||||
|
~Asibfm700MountConfig() = default;
|
||||||
|
|
||||||
|
std::error_code load(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
auto sz = std::filesystem::file_size(path, ec);
|
||||||
|
|
||||||
|
if (!ec && sz) {
|
||||||
|
std::ifstream fst(path);
|
||||||
|
|
||||||
|
try {
|
||||||
|
buffer.resize(sz);
|
||||||
|
|
||||||
|
fst.read(buffer.data(), sz);
|
||||||
|
|
||||||
|
fst.close();
|
||||||
|
|
||||||
|
ec = base_t::fromCharRange(buffer, deserializer);
|
||||||
|
if (!ec) {
|
||||||
|
updateAll();
|
||||||
|
}
|
||||||
|
} catch (std::ios_base::failure const& ex) {
|
||||||
|
ec = ex.code();
|
||||||
|
} catch (std::length_error const& ex) {
|
||||||
|
ec = std::make_error_code(std::errc::no_buffer_space);
|
||||||
|
} catch (std::bad_alloc const& ex) {
|
||||||
|
ec = std::make_error_code(std::errc::not_enough_memory);
|
||||||
|
} catch (...) {
|
||||||
|
ec = std::make_error_code(std::errc::operation_canceled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::error_code setValue(std::string_view key, const T& value)
|
||||||
|
{
|
||||||
|
auto ec = base_t::setValue(key, value);
|
||||||
|
if (!ec) {
|
||||||
|
updateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Asibfm700MountConfig2 : protected ConfigHolder<decltype(Asibfm700MountConfigDefaults)>
|
||||||
{
|
{
|
||||||
using base_t = ConfigHolder<decltype(Asibfm700MountConfigDefaults)>;
|
using base_t = ConfigHolder<decltype(Asibfm700MountConfigDefaults)>;
|
||||||
|
|
||||||
@ -481,12 +786,12 @@ public:
|
|||||||
using base_t::update;
|
using base_t::update;
|
||||||
using base_t::value;
|
using base_t::value;
|
||||||
|
|
||||||
Asibfm700MountConfig() : base_t(Asibfm700MountConfigDefaults)
|
Asibfm700MountConfig2() : base_t(Asibfm700MountConfigDefaults)
|
||||||
{
|
{
|
||||||
updateAll();
|
updateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Asibfm700MountConfig() = default;
|
~Asibfm700MountConfig2() = default;
|
||||||
|
|
||||||
std::error_code load(const std::filesystem::path& path)
|
std::error_code load(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -56,15 +56,18 @@ int main()
|
|||||||
fst.close();
|
fst.close();
|
||||||
|
|
||||||
asibfm700::Asibfm700MountConfig acfg;
|
asibfm700::Asibfm700MountConfig acfg;
|
||||||
|
// asibfm700::Asibfm700MountConfig2 acfg;
|
||||||
|
|
||||||
auto ec = acfg.load("/tmp/cfg.cfg");
|
auto ec = acfg.load("/tmp/cfg.cfg");
|
||||||
std::cout << "EC (load) = " << ec.message() << "\n";
|
std::cout << "EC (load) = " << ec.message() << "\n";
|
||||||
|
|
||||||
std::cout << "refr w: " << acfg.refractWavelength << "\n";
|
std::cout << "refr w: " << acfg.refractWavelength << "\n";
|
||||||
|
|
||||||
acfg.update("refractWavelength", 0.3);
|
// acfg.update("refractWavelength", 0.3);
|
||||||
|
acfg.setValue("refractWavelength", 0.3);
|
||||||
|
|
||||||
auto e = acfg.value<double>("refractWavelength");
|
auto e = acfg.getValue<double>("refractWavelength");
|
||||||
|
// auto e = acfg.value<double>("refractWavelength");
|
||||||
std::cout << "refr w: " << e.value_or(0.0) << "\n";
|
std::cout << "refr w: " << e.value_or(0.0) << "\n";
|
||||||
std::cout << "refr w: " << acfg.refractWavelength << "\n";
|
std::cout << "refr w: " << acfg.refractWavelength << "\n";
|
||||||
|
|
||||||
@ -78,5 +81,19 @@ int main()
|
|||||||
std::cout << "kvh[C] = " << vs.value_or("<no value>") << "\n";
|
std::cout << "kvh[C] = " << vs.value_or("<no value>") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ec = kvh.fromCharRange(cfg_str);
|
||||||
|
if (ec) {
|
||||||
|
std::cout << "EC = " << ec.message() << "\n";
|
||||||
|
} else {
|
||||||
|
v3 = kvh.getValue<std::vector<int>>("E");
|
||||||
|
std::cout << "[";
|
||||||
|
for (auto& el : v3.value_or({0, 0, 0})) {
|
||||||
|
std::cout << el << " ";
|
||||||
|
}
|
||||||
|
std::cout << "]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
102
mcc/mcc_utils.h
102
mcc/mcc_utils.h
@ -427,6 +427,56 @@ public:
|
|||||||
static constexpr std::string_view KEY_VALUE_DELIM{"="};
|
static constexpr std::string_view KEY_VALUE_DELIM{"="};
|
||||||
static constexpr std::string_view VALUE_ARRAY_DELIM{","};
|
static constexpr std::string_view VALUE_ARRAY_DELIM{","};
|
||||||
|
|
||||||
|
inline static auto defaultDeserializeFunc = []<typename VT>(this auto&& self, std::string_view str, VT& value) {
|
||||||
|
std::error_code ret{};
|
||||||
|
|
||||||
|
if constexpr (std::is_arithmetic_v<VT>) {
|
||||||
|
auto v = mcc::utils::numFromStr<VT>(trimSpaces(str));
|
||||||
|
if (!v.has_value()) {
|
||||||
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = v.value();
|
||||||
|
} else if constexpr (mcc::traits::mcc_output_char_range<VT>) {
|
||||||
|
VT r;
|
||||||
|
std::ranges::copy(str, std::back_inserter(r));
|
||||||
|
value = r;
|
||||||
|
} else if constexpr (std::ranges::range<VT>) {
|
||||||
|
using el_t = std::ranges::range_value_t<VT>;
|
||||||
|
|
||||||
|
if constexpr (std::is_reference_v<el_t> || std::is_const_v<el_t>) { // no reference or constants allowed
|
||||||
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
VT r;
|
||||||
|
el_t elem;
|
||||||
|
|
||||||
|
auto els = std::views::split(str, VALUE_ARRAY_DELIM);
|
||||||
|
|
||||||
|
for (auto const& el : els) {
|
||||||
|
ret = std::forward<decltype(self)>(self)(std::string_view(el), elem);
|
||||||
|
if (!ret) {
|
||||||
|
std::back_inserter(r) = elem;
|
||||||
|
} else {
|
||||||
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = r;
|
||||||
|
} else if constexpr (mcc::traits::mcc_time_duration_c<VT>) {
|
||||||
|
typename VT::rep vd;
|
||||||
|
|
||||||
|
ret = std::forward<decltype(self)>(self)(trimSpaces(str), vd);
|
||||||
|
if (!ret) {
|
||||||
|
value = VT{vd};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
KeyValueHolder(DESCR_T desc) : _keyValue(desc)
|
KeyValueHolder(DESCR_T desc) : _keyValue(desc)
|
||||||
{
|
{
|
||||||
[this]<size_t... I>(std::index_sequence<I...>) {
|
[this]<size_t... I>(std::index_sequence<I...>) {
|
||||||
@ -468,6 +518,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <std::ranges::contiguous_range R, std::ranges::input_range RecDelimT = std::string_view>
|
||||||
|
std::error_code fromCharRange(const R& buffer, RecDelimT rec_delim = std::string_view("\n"))
|
||||||
|
{
|
||||||
|
return fromCharRange(buffer, KeyValueHolder::defaultDeserializeFunc, std::move(rec_delim));
|
||||||
|
}
|
||||||
|
|
||||||
template <std::ranges::contiguous_range R,
|
template <std::ranges::contiguous_range R,
|
||||||
typename DeserFuncT,
|
typename DeserFuncT,
|
||||||
std::ranges::input_range RecDelimT = std::string_view>
|
std::ranges::input_range RecDelimT = std::string_view>
|
||||||
@ -475,6 +531,8 @@ public:
|
|||||||
DeserFuncT&& deser_func,
|
DeserFuncT&& deser_func,
|
||||||
RecDelimT rec_delim = std::string_view("\n"))
|
RecDelimT rec_delim = std::string_view("\n"))
|
||||||
{
|
{
|
||||||
|
// static_assert(mcc::traits::mcc_callable_c<std::decay_t<DeserFuncT>>, "!!!!!!!");
|
||||||
|
|
||||||
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>>) {
|
||||||
return fromCharRange(std::string_view{buffer}, std::forward<DeserFuncT>(deser_func),
|
return fromCharRange(std::string_view{buffer}, std::forward<DeserFuncT>(deser_func),
|
||||||
@ -489,13 +547,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parse_rec = [this, &deser_func](std::string_view rec) -> std::error_code {
|
|
||||||
std::string_view key, value;
|
std::error_code ec{};
|
||||||
|
std::string_view rec, key, value;
|
||||||
|
|
||||||
|
|
||||||
|
auto recs = std::views::split(buffer, std::move(rec_delim));
|
||||||
|
for (auto const& el : recs) {
|
||||||
|
rec = mcc::utils::trimSpaces(el, TrimType::TRIM_LEFT);
|
||||||
|
|
||||||
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
|
||||||
rec = rec.substr(std::distance(rec.begin(), found.begin()));
|
rec = std::string_view(rec.begin(), found.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec.size()) {
|
if (rec.size()) {
|
||||||
@ -504,35 +568,17 @@ public:
|
|||||||
key = trimSpaces(std::string_view(rec.begin(), found.begin()), TrimType::TRIM_RIGHT);
|
key = trimSpaces(std::string_view(rec.begin(), found.begin()), TrimType::TRIM_RIGHT);
|
||||||
value = std::string_view(found.end(), rec.end());
|
value = std::string_view(found.end(), rec.end());
|
||||||
|
|
||||||
return forKey(key, [value, &deser_func]<typename VT>(VT& v) { return deser_func(value, v); });
|
ec = forKey(key, [value, &deser_func]<typename VT>(VT& v) { return deser_func(value, v); });
|
||||||
}
|
}
|
||||||
}
|
} // just comment string starting from the beginning, just skip it (no error)
|
||||||
|
|
||||||
|
} // empty record, just skip it (no error)
|
||||||
|
|
||||||
|
if (ec) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
auto curr_buffer = std::string_view(buffer.begin(), buffer.end());
|
|
||||||
bool buffer_end = false;
|
|
||||||
std::error_code ec;
|
|
||||||
std::string_view rec;
|
|
||||||
|
|
||||||
auto delim_size = std::ranges::size(rec_delim);
|
|
||||||
if (delim_size == 0) { // just one record
|
|
||||||
return parse_rec(trimSpaces(buffer, TrimType::TRIM_LEFT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
|
||||||
auto found = std::ranges::search(curr_buffer, rec_delim);
|
|
||||||
if (found.begin() == curr_buffer.end()) {
|
|
||||||
buffer_end = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
rec = mcc::utils::trimSpaces(std::string_view(curr_buffer.begin(), found.begin()), TrimType::TRIM_LEFT);
|
|
||||||
|
|
||||||
curr_buffer = {found.end(), curr_buffer.end()};
|
|
||||||
|
|
||||||
ec = parse_rec(rec);
|
|
||||||
} while (!buffer_end || !ec);
|
|
||||||
|
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user