From: Maksym Mamontov Date: Sun, 24 Jul 2022 15:51:46 +0000 (+0300) Subject: Fight Optional X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/a91e9542b384905187890f161d4da5396996fcfd?hp=c02633d77cb05a5deb05440d77b12ccc5bc19b85 Fight Optional --- diff --git a/include/stg/admin_conf.h b/include/stg/admin_conf.h index 8531647e..b402e241 100644 --- a/include/stg/admin_conf.h +++ b/include/stg/admin_conf.h @@ -1,8 +1,7 @@ #pragma once -#include "stg/optional.h" - #include +#include #include @@ -78,9 +77,9 @@ struct AdminConf //----------------------------------------------------------------------------- struct AdminConfOpt { - Optional priv; - Optional login; - Optional password; + std::optional priv; + std::optional login; + std::optional password; }; } diff --git a/include/stg/corp_conf.h b/include/stg/corp_conf.h index 6b1cbb83..8ff4094f 100644 --- a/include/stg/corp_conf.h +++ b/include/stg/corp_conf.h @@ -20,9 +20,8 @@ #pragma once -#include "stg/optional.h" - #include +#include namespace STG { @@ -46,8 +45,8 @@ struct CorpConf struct CorpConfOpt { - Optional name; - Optional cash; + std::optional name; + std::optional cash; }; } diff --git a/include/stg/optional.h b/include/stg/optional.h deleted file mode 100644 index 105d7e2f..00000000 --- a/include/stg/optional.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -namespace STG -{ - -template -class Optional -{ -public: - using value_type = T; - - Optional() noexcept : m_isSet(false) {} - explicit Optional(const T& value) noexcept : m_value(value), m_isSet(true) {} - - Optional(const Optional&) = default; - Optional& operator=(const Optional&) = default; - - Optional(Optional&&) = default; - Optional& operator=(Optional&&) = default; - - Optional& operator=(const T & rhs) noexcept - { - m_value = rhs; - m_isSet = true; - return *this; - } - - const T & const_data() const noexcept { return m_value; } - T & data() noexcept { return m_value; } - const T & data() const noexcept { return m_value; } - bool empty() const noexcept { return !m_isSet; } - void reset() noexcept { m_isSet = false; } - void splice(const Optional& rhs) noexcept - { - if (rhs.m_isSet) - { - m_value = rhs.m_value; - m_isSet = true; - } - } - const T& get(const T& defaultValue) const noexcept - { - if (m_isSet) - return m_value; - else - return defaultValue; - } - -private: - value_type m_value; - bool m_isSet; -}; - -} diff --git a/include/stg/service_conf.h b/include/stg/service_conf.h index 6be8e70b..d5661c09 100644 --- a/include/stg/service_conf.h +++ b/include/stg/service_conf.h @@ -20,9 +20,10 @@ #pragma once -#include "stg/optional.h" +#include "splice.h" #include +#include #include namespace STG @@ -85,26 +86,26 @@ struct ServiceConfOpt void splice(const ServiceConfOpt& rhs) { - name.splice(rhs.name); - comment.splice(rhs.comment); - cost.splice(rhs.cost); - payDay.splice(rhs.payDay); + STG::splice(name, rhs.name); + STG::splice(comment, rhs.comment); + STG::splice(cost, rhs.cost); + STG::splice(payDay, rhs.payDay); } ServiceConf get(const ServiceConf& defaultValue) const noexcept { ServiceConf res; - res.name = name.get(defaultValue.name); - res.comment = comment.get(defaultValue.comment); - res.cost = cost.get(defaultValue.cost); - res.payDay = payDay.get(defaultValue.payDay); + res.name = name.value_or(defaultValue.name); + res.comment = comment.value_or(defaultValue.comment); + res.cost = cost.value_or(defaultValue.cost); + res.payDay = payDay.value_or(defaultValue.payDay); return res; } - Optional name; - Optional comment; - Optional cost; - Optional payDay; + std::optional name; + std::optional comment; + std::optional cost; + std::optional payDay; }; } diff --git a/include/stg/splice.h b/include/stg/splice.h new file mode 100644 index 00000000..8d646301 --- /dev/null +++ b/include/stg/splice.h @@ -0,0 +1,36 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#pragma once + +#include + +namespace STG +{ + +template +inline +void splice(std::optional& lhs, const std::optional& rhs) noexcept +{ + if (rhs) + lhs = rhs.value(); +} + +} diff --git a/include/stg/tariff_conf.h b/include/stg/tariff_conf.h index d7336157..0a4f988b 100644 --- a/include/stg/tariff_conf.h +++ b/include/stg/tariff_conf.h @@ -21,11 +21,12 @@ #pragma once #include "tariff.h" -#include "stg/optional.h" #include "const.h" +#include "splice.h" #include #include +#include namespace STG { @@ -105,47 +106,47 @@ struct DirPriceDataOpt void splice(const DirPriceDataOpt & rhs) noexcept { - hDay.splice(rhs.hDay); - mDay.splice(rhs.mDay); - hNight.splice(rhs.hNight); - mNight.splice(rhs.mNight); - priceDayA.splice(rhs.priceDayA); - priceNightA.splice(rhs.priceNightA); - priceDayB.splice(rhs.priceDayB); - priceNightB.splice(rhs.priceNightB); - threshold.splice(rhs.threshold); - singlePrice.splice(rhs.singlePrice); - noDiscount.splice(rhs.noDiscount); + STG::splice(hDay, rhs.hDay); + STG::splice(mDay, rhs.mDay); + STG::splice(hNight, rhs.hNight); + STG::splice(mNight, rhs.mNight); + STG::splice(priceDayA, rhs.priceDayA); + STG::splice(priceNightA, rhs.priceNightA); + STG::splice(priceDayB, rhs.priceDayB); + STG::splice(priceNightB, rhs.priceNightB); + STG::splice(threshold, rhs.threshold); + STG::splice(singlePrice, rhs.singlePrice); + STG::splice(noDiscount, rhs.noDiscount); } DirPriceData get(const DirPriceData& defaultValue) const noexcept { DirPriceData res; - res.hDay = hDay.get(defaultValue.hDay); - res.mDay = mDay.get(defaultValue.mDay); - res.hNight = hNight.get(defaultValue.hNight); - res.mNight = mNight.get(defaultValue.mNight); - res.priceDayA = priceDayA.get(defaultValue.priceDayA); - res.priceNightA = priceNightA.get(defaultValue.priceNightA); - res.priceDayB = priceDayB.get(defaultValue.priceDayB); - res.priceNightB = priceNightB.get(defaultValue.priceNightB); - res.threshold = threshold.get(defaultValue.threshold); - res.singlePrice = singlePrice.get(defaultValue.singlePrice); - res.noDiscount = noDiscount.get(defaultValue.noDiscount); + res.hDay = hDay.value_or(defaultValue.hDay); + res.mDay = mDay.value_or(defaultValue.mDay); + res.hNight = hNight.value_or(defaultValue.hNight); + res.mNight = mNight.value_or(defaultValue.mNight); + res.priceDayA = priceDayA.value_or(defaultValue.priceDayA); + res.priceNightA = priceNightA.value_or(defaultValue.priceNightA); + res.priceDayB = priceDayB.value_or(defaultValue.priceDayB); + res.priceNightB = priceNightB.value_or(defaultValue.priceNightB); + res.threshold = threshold.value_or(defaultValue.threshold); + res.singlePrice = singlePrice.value_or(defaultValue.singlePrice); + res.noDiscount = noDiscount.value_or(defaultValue.noDiscount); return res; } - Optional hDay; - Optional mDay; - Optional hNight; - Optional mNight; - Optional priceDayA; - Optional priceNightA; - Optional priceDayB; - Optional priceNightB; - Optional threshold; - Optional singlePrice; - Optional noDiscount; + std::optional hDay; + std::optional mDay; + std::optional hNight; + std::optional mNight; + std::optional priceDayA; + std::optional priceNightA; + std::optional priceDayB; + std::optional priceNightB; + std::optional threshold; + std::optional singlePrice; + std::optional noDiscount; }; //----------------------------------------------------------------------------- struct TariffConf @@ -220,25 +221,25 @@ struct TariffConfOpt TariffConf get(const TariffConf& defaultValue) const noexcept { TariffConf res; - res.fee = fee.get(defaultValue.fee); - res.free = free.get(defaultValue.free); - res.traffType = traffType.get(defaultValue.traffType); - res.passiveCost = passiveCost.get(defaultValue.passiveCost); - res.name = name.get(defaultValue.name); - res.period = period.get(defaultValue.period); - res.changePolicy = changePolicy.get(defaultValue.changePolicy); - res.changePolicyTimeout = changePolicyTimeout.get(defaultValue.changePolicyTimeout); + res.fee = fee.value_or(defaultValue.fee); + res.free = free.value_or(defaultValue.free); + res.traffType = traffType.value_or(defaultValue.traffType); + res.passiveCost = passiveCost.value_or(defaultValue.passiveCost); + res.name = name.value_or(defaultValue.name); + res.period = period.value_or(defaultValue.period); + res.changePolicy = changePolicy.value_or(defaultValue.changePolicy); + res.changePolicyTimeout = changePolicyTimeout.value_or(defaultValue.changePolicyTimeout); return res; } - Optional fee; - Optional free; - Optional traffType; - Optional passiveCost; - Optional name; - Optional period; - Optional changePolicy; - Optional changePolicyTimeout; + std::optional fee; + std::optional free; + std::optional traffType; + std::optional passiveCost; + std::optional name; + std::optional period; + std::optional changePolicy; + std::optional changePolicyTimeout; }; //----------------------------------------------------------------------------- struct TariffData diff --git a/include/stg/user_conf.h b/include/stg/user_conf.h index db5773b8..a82c4f1f 100644 --- a/include/stg/user_conf.h +++ b/include/stg/user_conf.h @@ -1,10 +1,10 @@ #pragma once #include "user_ips.h" -#include "stg/optional.h" #include #include +#include #include #include "const.h" @@ -110,25 +110,25 @@ struct UserConfOpt UserConfOpt(UserConfOpt&&) = default; UserConfOpt& operator=(UserConfOpt&&) = default; - Optional password; - Optional passive; - Optional disabled; - Optional disabledDetailStat; - Optional alwaysOnline; - Optional tariffName; - Optional address; - Optional phone; - Optional email; - Optional note; - Optional realName; - Optional corp; - Optional group; - Optional credit; - Optional nextTariff; - std::vector > userdata; - Optional > services; - Optional creditExpire; - Optional ips; + std::optional password; + std::optional passive; + std::optional disabled; + std::optional disabledDetailStat; + std::optional alwaysOnline; + std::optional tariffName; + std::optional address; + std::optional phone; + std::optional email; + std::optional note; + std::optional realName; + std::optional corp; + std::optional group; + std::optional credit; + std::optional nextTariff; + std::vector > userdata; + std::optional > services; + std::optional creditExpire; + std::optional ips; }; //----------------------------------------------------------------------------- } diff --git a/include/stg/user_stat.h b/include/stg/user_stat.h index a486a56e..0ecd9e15 100644 --- a/include/stg/user_stat.h +++ b/include/stg/user_stat.h @@ -20,7 +20,6 @@ #pragma once -#include "stg/optional.h" #include "user_traff.h" #include @@ -28,6 +27,7 @@ #include #include #include +#include namespace STG { @@ -180,14 +180,14 @@ struct UserStatOpt UserStatOpt(UserStatOpt&&) = default; UserStatOpt& operator=(UserStatOpt&&) = default; - Optional cash; - Optional cashAdd; - Optional cashSet; - Optional freeMb; - Optional lastCashAdd; - Optional lastCashAddTime; - Optional passiveTime; - Optional lastActivityTime; + std::optional cash; + std::optional cashAdd; + std::optional cashSet; + std::optional freeMb; + std::optional lastCashAdd; + std::optional lastCashAddTime; + std::optional passiveTime; + std::optional lastActivityTime; DirTraffOpt sessionUp; DirTraffOpt sessionDown; DirTraffOpt monthUp; diff --git a/include/stg/user_traff.h b/include/stg/user_traff.h index b949da5f..af5a0b64 100644 --- a/include/stg/user_traff.h +++ b/include/stg/user_traff.h @@ -20,11 +20,11 @@ #pragma once -#include "stg/optional.h" #include "const.h" #include #include +#include #include namespace STG @@ -74,7 +74,7 @@ std::ostream& operator<<(std::ostream& stream, const DirTraff& traff) class DirTraffOpt { public: - using ValueType = Optional; + using ValueType = std::optional; using ContainerType = std::vector; using IndexType = ContainerType::size_type; diff --git a/libs/srvconf/parsers/chg_admin.cpp b/libs/srvconf/parsers/chg_admin.cpp index 31fbd4a4..bb4d8682 100644 --- a/libs/srvconf/parsers/chg_admin.cpp +++ b/libs/srvconf/parsers/chg_admin.cpp @@ -30,11 +30,11 @@ using namespace STG; std::string ChgAdmin::serialize(const AdminConfOpt& conf, const std::string& /*encoding*/) { std::string params; - if (!conf.login.empty()) - params += " login=\"" + conf.login.data() + "\""; - if (!conf.password.empty()) - params += " password=\"" + conf.password.data() + "\""; - if (!conf.priv.empty()) - params += " priv=\"" + std::to_string(conf.priv.data().toInt()) + "\""; + if (conf.login) + params += " login=\"" + conf.login.value() + "\""; + if (conf.password) + params += " password=\"" + conf.password.value() + "\""; + if (conf.priv) + params += " priv=\"" + std::to_string(conf.priv.value().toInt()) + "\""; return params; } diff --git a/libs/srvconf/parsers/chg_tariff.cpp b/libs/srvconf/parsers/chg_tariff.cpp index 63c2b1fd..fc81dd52 100644 --- a/libs/srvconf/parsers/chg_tariff.cpp +++ b/libs/srvconf/parsers/chg_tariff.cpp @@ -40,11 +40,11 @@ void appendSlashedResetable(std::ostream& stream, const std::string& name, const std::string res; for (typename A::size_type i = 0; i < array.size(); ++i) { - if ((array[i].*field).empty()) // All values must be set + if (!(array[i].*field)) // All values must be set return; if (!res.empty()) res += "/"; - res += std::to_string((array[i].*field).data()); + res += std::to_string((array[i].*field).value()); } stream << "<" << name << " value=\"" << res << "\"/>"; } @@ -59,18 +59,18 @@ std::string ChgTariff::serialize(const TariffDataOpt& data, const std::string& / appendResetableTag(stream, "passiveCost", data.tariffConf.passiveCost); appendResetableTag(stream, "free", data.tariffConf.free); - if (!data.tariffConf.traffType.empty()) - stream << ""; + if (data.tariffConf.traffType) + stream << ""; - if (!data.tariffConf.period.empty()) - switch (data.tariffConf.period.data()) + if (data.tariffConf.period) + switch (data.tariffConf.period.value()) { case Tariff::DAY: stream << ""; break; case Tariff::MONTH: stream << ""; break; } - if (!data.tariffConf.changePolicy.empty()) - switch (data.tariffConf.changePolicy.data()) + if (data.tariffConf.changePolicy) + switch (data.tariffConf.changePolicy.value()) { case Tariff::ALLOW: stream << ""; break; case Tariff::TO_CHEAP: stream << ""; break; @@ -80,14 +80,14 @@ std::string ChgTariff::serialize(const TariffDataOpt& data, const std::string& / appendResetableTag(stream, "changePolicyTimeout", data.tariffConf.changePolicyTimeout); for (size_t i = 0; i < DIR_NUM; ++i) - if (!data.dirPrice[i].hDay.empty() && - !data.dirPrice[i].mDay.empty() && - !data.dirPrice[i].hNight.empty() && - !data.dirPrice[i].mNight.empty()) - stream << ""; + if (data.dirPrice[i].hDay || + data.dirPrice[i].mDay || + data.dirPrice[i].hNight || + data.dirPrice[i].mNight) + stream << ""; appendSlashedResetable(stream, "priceDayA", data.dirPrice, &DirPriceDataOpt::priceDayA); appendSlashedResetable(stream, "priceDayB", data.dirPrice, &DirPriceDataOpt::priceDayB); diff --git a/libs/srvconf/parsers/chg_user.cpp b/libs/srvconf/parsers/chg_user.cpp index c0a08382..42682f58 100644 --- a/libs/srvconf/parsers/chg_user.cpp +++ b/libs/srvconf/parsers/chg_user.cpp @@ -86,10 +86,10 @@ std::string ChgUser::serialize(const UserConfOpt& conf, const UserStatOpt& stat, appendResetableTag(stream, "aonline", conf.alwaysOnline); // TODO: aonline -> alwaysOnline appendResetableTag(stream, "ip", conf.ips); // TODO: ip -> ips - if (!conf.nextTariff.empty()) - stream << ""; - else if (!conf.tariffName.empty()) - stream << ""; + if (conf.nextTariff) + stream << ""; + else if (conf.tariffName) + stream << ""; appendResetableTag(stream, "note", maybeEncode(maybeIconv(conf.note, encoding, "koi8-ru"))); appendResetableTag(stream, "name", maybeEncode(maybeIconv(conf.realName, encoding, "koi8-ru"))); // TODO: name -> realName @@ -102,36 +102,36 @@ std::string ChgUser::serialize(const UserConfOpt& conf, const UserStatOpt& stat, for (size_t i = 0; i < conf.userdata.size(); ++i) appendResetableTag(stream, "userdata", i, maybeEncode(maybeIconv(conf.userdata[i], encoding, "koi8-ru"))); - if (!conf.services.empty()) + if (conf.services) { stream << ""; - for (size_t i = 0; i < conf.services.data().size(); ++i) - stream << ""; + for (const auto& service : conf.services.value()) + stream << ""; stream << ""; } // Stat - if (!stat.cashAdd.empty()) - stream << ""; - else if (!stat.cashSet.empty()) - stream << ""; + if (stat.cashAdd) + stream << ""; + else if (stat.cashSet) + stream << ""; appendResetableTag(stream, "freeMb", stat.freeMb); std::ostringstream traff; for (size_t i = 0; i < stat.sessionUp.size(); ++i) - if (!stat.sessionUp[i].empty()) - traff << " SU" << i << "=\"" << stat.sessionUp[i].data() << "\""; + if (stat.sessionUp[i]) + traff << " SU" << i << "=\"" << stat.sessionUp[i].value() << "\""; for (size_t i = 0; i < stat.sessionDown.size(); ++i) - if (!stat.sessionDown[i].empty()) - traff << " SD" << i << "=\"" << stat.sessionDown[i].data() << "\""; + if (stat.sessionDown[i]) + traff << " SD" << i << "=\"" << stat.sessionDown[i].value() << "\""; for (size_t i = 0; i < stat.monthUp.size(); ++i) - if (!stat.monthUp[i].empty()) - traff << " MU" << i << "=\"" << stat.monthUp[i].data() << "\""; + if (stat.monthUp[i]) + traff << " MU" << i << "=\"" << stat.monthUp[i].value() << "\""; for (size_t i = 0; i < stat.monthDown.size(); ++i) - if (!stat.monthDown[i].empty()) - traff << " MD" << i << "=\"" << stat.monthDown[i].data() << "\""; + if (stat.monthDown[i]) + traff << " MD" << i << "=\"" << stat.monthDown[i].value() << "\""; std::string traffData = traff.str(); if (!traffData.empty()) diff --git a/libs/srvconf/parsers/get_tariff.cpp b/libs/srvconf/parsers/get_tariff.cpp index 30492968..af92da0b 100644 --- a/libs/srvconf/parsers/get_tariff.cpp +++ b/libs/srvconf/parsers/get_tariff.cpp @@ -39,7 +39,7 @@ class AoSParser : public BasePropertyParser public: using Func = bool (*)(const char**, A &, T A::value_type::*); AoSParser(A& a, T A::value_type::* fld, Func f) : array(a), field(fld), func(f) {} - virtual bool Parse(const char** attr, const std::string& /*attrName*/, const std::string& /*fromEncoding*/) { return func(attr, array, field); } + bool Parse(const char** attr, const std::string& /*attrName*/, const std::string& /*fromEncoding*/) override { return func(attr, array, field); } private: A& array; T A::value_type::* field; diff --git a/libs/srvconf/parsers/optional_utils.h b/libs/srvconf/parsers/optional_utils.h index 9b6054bc..9cffc1ed 100644 --- a/libs/srvconf/parsers/optional_utils.h +++ b/libs/srvconf/parsers/optional_utils.h @@ -20,11 +20,11 @@ #pragma once -#include "stg/optional.h" #include "stg/common.h" #include #include +#include namespace STG { @@ -87,51 +87,51 @@ void appendAttr(std::ostream& stream, const std::string& name, const int template inline -void appendResetableTag(std::ostream& stream, const std::string& name, const T& value) +void appendResetableTag(std::ostream& stream, const std::string& name, const std::optional& value) { - if (!value.empty()) - appendTag(stream, name, value.const_data()); + if (value) + appendTag(stream, name, value.value()); } template inline -void appendResetableTag(std::ostream& stream, const std::string& name, size_t suffix, const T& value) +void appendResetableTag(std::ostream& stream, const std::string& name, size_t suffix, const std::optional& value) { - if (!value.empty()) - appendTag(stream, name, suffix, value.const_data()); + if (value) + appendTag(stream, name, suffix, value.value()); } template inline -void appendResetableAttr(std::ostream& stream, const std::string& name, const T& value) +void appendResetableAttr(std::ostream& stream, const std::string& name, const std::optional& value) { - if (!value.empty()) - appendAttr(stream, name, value.const_data()); + if (value) + appendAttr(stream, name, value.value()); } template inline -void appendResetableAttr(std::ostream& stream, const std::string& name, size_t suffix, const T& value) +void appendResetableAttr(std::ostream& stream, const std::string& name, size_t suffix, const std::optional& value) { - if (!value.empty()) - appendAttr(stream, name, suffix, value.const_data()); + if (value) + appendAttr(stream, name, suffix, value.value()); } inline -Optional maybeEncode(const Optional& value) +std::optional maybeEncode(const std::optional& value) { - Optional res; - if (!value.empty()) - res = Encode12str(value.data()); + std::optional res; + if (value) + res = Encode12str(value.value()); return res; } inline -Optional maybeIconv(const Optional& value, const std::string& fromEncoding, const std::string& toEncoding) +std::optional maybeIconv(const std::optional& value, const std::string& fromEncoding, const std::string& toEncoding) { - Optional res; - if (!value.empty()) - res = IconvString(value.data(), fromEncoding, toEncoding); + std::optional res; + if (value) + res = IconvString(value.value(), fromEncoding, toEncoding); return res; } diff --git a/libs/srvconf/servconf.cpp b/libs/srvconf/servconf.cpp index c4e4bdf6..c038fd29 100644 --- a/libs/srvconf/servconf.cpp +++ b/libs/srvconf/servconf.cpp @@ -108,7 +108,7 @@ bool ServConf::Impl::ParserRecv(const std::string& chunk, bool last, void* data) strprintf(&sc->errorMsg, "XML parse error at line %d, %d: %s. Is last: %d", static_cast(XML_GetCurrentLineNumber(sc->parser)), static_cast(XML_GetCurrentColumnNumber(sc->parser)), - XML_ErrorString(XML_GetErrorCode(sc->parser)), (int)last); + XML_ErrorString(XML_GetErrorCode(sc->parser)), static_cast(last)); return false; } @@ -195,7 +195,7 @@ int ServConf::GetTariff(const std::string& name, GetTariff::Callback f, void* da int ServConf::ChgTariff(const TariffDataOpt& tariffData, Simple::Callback f, void* data) { - return pImpl->Exec("SetTariff", "" + ChgTariff::serialize(tariffData, pImpl->Encoding()) + "", f, data); + return pImpl->Exec("SetTariff", "" + ChgTariff::serialize(tariffData, pImpl->Encoding()) + "", f, data); } int ServConf::AddTariff(const std::string& name, @@ -310,7 +310,7 @@ int ServConf::GetCorp(const std::string& name, GetCorp::Callback f, void* data) int ServConf::ChgCorp(const CorpConfOpt & conf, Simple::Callback f, void* data) { - return pImpl->Exec("SetCorp", "" + ChgCorp::serialize(conf, pImpl->Encoding()) + "", f, data); + return pImpl->Exec("SetCorp", "" + ChgCorp::serialize(conf, pImpl->Encoding()) + "", f, data); } int ServConf::AddCorp(const std::string& name, diff --git a/projects/sgconf/actions.h b/projects/sgconf/actions.h index f23e566d..a078e6b2 100644 --- a/projects/sgconf/actions.h +++ b/projects/sgconf/actions.h @@ -25,9 +25,9 @@ #include "parser_state.h" #include "stg/common.h" -#include "stg/optional.h" #include +#include #include @@ -67,7 +67,7 @@ template class PARAM_ACTION : public ACTION { public: - PARAM_ACTION(STG::Optional & param, + PARAM_ACTION(std::optional & param, const T & defaultValue, const std::string & paramDescription) : m_param(param), @@ -75,11 +75,11 @@ class PARAM_ACTION : public ACTION m_description(paramDescription), m_hasDefault(true) {} - explicit PARAM_ACTION(STG::Optional & param) + explicit PARAM_ACTION(std::optional & param) : m_param(param), m_hasDefault(false) {} - PARAM_ACTION(STG::Optional & param, + PARAM_ACTION(std::optional & param, const std::string & paramDescription) : m_param(param), m_description(paramDescription), @@ -93,7 +93,7 @@ class PARAM_ACTION : public ACTION void ParseValue(const std::string & value) override; private: - STG::Optional & m_param; + std::optional & m_param; T m_defaltValue; std::string m_description; bool m_hasDefault; @@ -172,7 +172,7 @@ return PARSER_STATE(false, --argc, ++argv); template inline -std::unique_ptr MakeParamAction(STG::Optional & param, +std::unique_ptr MakeParamAction(std::optional & param, const T & defaultValue, const std::string & paramDescription) { @@ -181,14 +181,14 @@ return std::make_unique>(param, defaultValue, paramDescription); template inline -std::unique_ptr MakeParamAction(STG::Optional & param) +std::unique_ptr MakeParamAction(std::optional & param) { return std::make_unique>(param); } template inline -std::unique_ptr MakeParamAction(STG::Optional & param, +std::unique_ptr MakeParamAction(std::optional & param, const std::string & paramDescription) { return std::make_unique>(param, paramDescription); diff --git a/projects/sgconf/admins.cpp b/projects/sgconf/admins.cpp index ea796214..c0700e31 100644 --- a/projects/sgconf/admins.cpp +++ b/projects/sgconf/admins.cpp @@ -2,6 +2,7 @@ #include "api_action.h" #include "options.h" +#include "makeproto.h" #include "config.h" #include "utils.h" @@ -53,7 +54,7 @@ params.push_back(SGCONF::API_ACTION::PARAM("priv", "", "priviledges")); return params; } -void ConvPriv(const std::string & value, STG::Optional & res) +void ConvPriv(const std::string & value, std::optional & res) { if (value.length() != 9) throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number."); @@ -119,42 +120,24 @@ bool GetAdminsFunction(const SGCONF::CONFIG & config, const std::string & /*arg*/, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetAdmins(GetAdminsCallback, NULL) == STG::st_ok; +return makeProto(config).GetAdmins(GetAdminsCallback, NULL) == STG::st_ok; } bool GetAdminFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); // STG currently doesn't support . // So get a list of admins and filter it. 'data' param holds a pointer to 'login'. std::string login(arg); -return proto.GetAdmins(GetAdminCallback, &login) == STG::st_ok; +return makeProto(config).GetAdmins(GetAdminCallback, &login) == STG::st_ok; } bool DelAdminFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok; } bool AddAdminFunction(const SGCONF::CONFIG & config, @@ -165,13 +148,7 @@ STG::AdminConfOpt conf; conf.login = arg; SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv); SGCONF::MaybeSet(options, "password", conf.password); -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok; } bool ChgAdminFunction(const SGCONF::CONFIG & config, @@ -182,13 +159,7 @@ STG::AdminConfOpt conf; conf.login = arg; SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv); SGCONF::MaybeSet(options, "password", conf.password); -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok; } } // namespace anonymous diff --git a/projects/sgconf/config.h b/projects/sgconf/config.h index f5313ef9..6c259334 100644 --- a/projects/sgconf/config.h +++ b/projects/sgconf/config.h @@ -20,10 +20,11 @@ #pragma once +#include "stg/splice.h" #include "stg/common.h" -#include "stg/optional.h" #include +#include #include namespace SGCONF @@ -31,53 +32,51 @@ namespace SGCONF struct CONFIG { - STG::Optional configFile; - STG::Optional server; - STG::Optional port; - STG::Optional localAddress; - STG::Optional localPort; - STG::Optional userName; - STG::Optional userPass; - STG::Optional showConfig; + std::optional configFile; + std::optional server; + std::optional port; + std::optional localAddress; + std::optional localPort; + std::optional userName; + std::optional userPass; + std::optional showConfig; - CONFIG & operator=(const CONFIG & rhs) + CONFIG() = default; + CONFIG(const CONFIG&) = default; + CONFIG(CONFIG&&) = default; + + CONFIG& operator=(const CONFIG&) = delete; + CONFIG& operator=(CONFIG&&) = delete; + + void splice(const CONFIG & rhs) noexcept { - if (!rhs.configFile.empty()) - configFile = rhs.configFile; - if (!rhs.server.empty()) - server = rhs.server; - if (!rhs.port.empty()) - port = rhs.port; - if (!rhs.localAddress.empty()) - localAddress = rhs.localAddress; - if (!rhs.localPort.empty()) - localPort = rhs.localPort; - if (!rhs.userName.empty()) - userName = rhs.userName; - if (!rhs.userPass.empty()) - userPass = rhs.userPass; - if (!rhs.showConfig.empty()) - showConfig = rhs.showConfig; - return *this; + STG::splice(configFile, rhs.configFile); + STG::splice(server, rhs.server); + STG::splice(port, rhs.port); + STG::splice(localAddress, rhs.localAddress); + STG::splice(localPort, rhs.localPort); + STG::splice(userName, rhs.userName); + STG::splice(userPass, rhs.userPass); + STG::splice(showConfig, rhs.showConfig); } std::string Serialize() const { std::string res; - if (!configFile.empty()) - res += "configFile: '" + configFile.data() + "'\n"; - if (!server.empty()) - res += "server: '" + server.data() + "'\n"; - if (!port.empty()) - res += "port: " + std::to_string(port.data()) + "\n"; - if (!localAddress.empty()) - res += "local address: '" + localAddress.data() + "'\n"; - if (!localPort.empty()) - res += "local port: " + std::to_string(localPort.data()) + "\n"; - if (!userName.empty()) - res += "userName: '" + userName.data() + "'\n"; - if (!userPass.empty()) - res += "userPass: '" + userPass.data() + "\n"; + if (configFile) + res += "configFile: '" + configFile.value() + "'\n"; + if (server) + res += "server: '" + server.value() + "'\n"; + if (port) + res += "port: " + std::to_string(port.value()) + "\n"; + if (localAddress) + res += "local address: '" + localAddress.value() + "'\n"; + if (localPort) + res += "local port: " + std::to_string(localPort.value()) + "\n"; + if (userName) + res += "userName: '" + userName.value() + "'\n"; + if (userPass) + res += "userPass: '" + userPass.value() + "\n"; return res; } }; diff --git a/projects/sgconf/corps.cpp b/projects/sgconf/corps.cpp index 586ddcd5..2dd0ffff 100644 --- a/projects/sgconf/corps.cpp +++ b/projects/sgconf/corps.cpp @@ -2,6 +2,7 @@ #include "api_action.h" #include "options.h" +#include "makeproto.h" #include "config.h" #include "utils.h" @@ -81,39 +82,21 @@ bool GetCorpsFunction(const SGCONF::CONFIG & config, const std::string & /*arg*/, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetCorporations(GetCorpsCallback, NULL) == STG::st_ok; +return makeProto(config).GetCorporations(GetCorpsCallback, NULL) == STG::st_ok; } bool GetCorpFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok; +return makeProto(config).GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok; } bool DelCorpFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.DelCorp(arg, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).DelCorp(arg, SimpleCallback, NULL) == STG::st_ok; } bool AddCorpFunction(const SGCONF::CONFIG & config, @@ -123,13 +106,7 @@ bool AddCorpFunction(const SGCONF::CONFIG & config, STG::CorpConfOpt conf; conf.name = arg; SGCONF::MaybeSet(options, "cash", conf.cash); -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok; } bool ChgCorpFunction(const SGCONF::CONFIG & config, @@ -139,13 +116,7 @@ bool ChgCorpFunction(const SGCONF::CONFIG & config, STG::CorpConfOpt conf; conf.name = arg; SGCONF::MaybeSet(options, "cash", conf.cash); -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok; +return makeProto(config).ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok; } } // namespace anonymous diff --git a/projects/sgconf/info.cpp b/projects/sgconf/info.cpp index 421e4389..cf6d44a4 100644 --- a/projects/sgconf/info.cpp +++ b/projects/sgconf/info.cpp @@ -2,6 +2,7 @@ #include "api_action.h" #include "options.h" +#include "makeproto.h" #include "config.h" #include "stg/servconf.h" @@ -42,13 +43,7 @@ bool InfoFunction(const SGCONF::CONFIG & config, const std::string& /*arg*/, const std::map & /*options*/) { -STG::ServConf proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ServerInfo(InfoCallback, NULL) == STG::st_ok; +return makeProto(config).ServerInfo(InfoCallback, NULL) == STG::st_ok; } } diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp index 3413dbd9..60cc15fa 100644 --- a/projects/sgconf/main.cpp +++ b/projects/sgconf/main.cpp @@ -236,227 +236,88 @@ return std::make_unique(config, paramDescription); //----------------------------------------------------------------------------- int main(int argc, char **argv) { -std::string self(basename(argv[0])); -SGCONF::CONFIG config; -SGCONF::COMMANDS commands; - -SGCONF::OPTION_BLOCKS blocks; -blocks.Add("General options") - .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), ""), "override default config file") - .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit") - //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit") - .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit"); -SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options") - .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "
"), "\t\thost to connect") - .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), ""), "\t\tport to connect") - .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "
"), "\tlocal address to bind") - .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), ""), "\t\tlocal port to bind") - .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), ""), "\tadministrative login") - .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, ""), "\tpassword for the administrative login") - .Add("a", "address", SGCONF::MakeParamAction(config, ""), "connection params as a single string in format: :@:"); -blocks.Add("Debug options") - .Add("show-config", SGCONF::MakeParamAction(config.showConfig), "\tshow config and exit"); -SGCONF::AppendXMLOptionBlock(commands, blocks); -SGCONF::AppendServerInfoBlock(commands, blocks); -SGCONF::AppendAdminsOptionBlock(commands, blocks); -SGCONF::AppendTariffsOptionBlock(commands, blocks); -SGCONF::AppendUsersOptionBlock(commands, blocks); -SGCONF::AppendServicesOptionBlock(commands, blocks); -SGCONF::AppendCorpsOptionBlock(commands, blocks); - -SGCONF::PARSER_STATE state(false, argc, argv); - -try -{ -state = blocks.Parse(--argc, ++argv); // Skipping self name -} -catch (const SGCONF::OPTION::ERROR& ex) -{ -std::cerr << ex.what() << "\n"; -return -1; -} - -if (state.stop) - return 0; - -if (state.argc > 0) + std::string self(basename(argv[0])); + SGCONF::CONFIG config; + SGCONF::COMMANDS commands; + + SGCONF::OPTION_BLOCKS blocks; + blocks.Add("General options") + .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), ""), "override default config file") + .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit") + //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit") + .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit"); + SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options") + .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "
"), "\t\thost to connect") + .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), ""), "\t\tport to connect") + .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "
"), "\tlocal address to bind") + .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), ""), "\t\tlocal port to bind") + .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), ""), "\tadministrative login") + .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, ""), "\tpassword for the administrative login") + .Add("a", "address", SGCONF::MakeParamAction(config, ""), "connection params as a single string in format: :@:"); + blocks.Add("Debug options") + .Add("show-config", SGCONF::MakeParamAction(config.showConfig), "\tshow config and exit"); + SGCONF::AppendXMLOptionBlock(commands, blocks); + SGCONF::AppendServerInfoBlock(commands, blocks); + SGCONF::AppendAdminsOptionBlock(commands, blocks); + SGCONF::AppendTariffsOptionBlock(commands, blocks); + SGCONF::AppendUsersOptionBlock(commands, blocks); + SGCONF::AppendServicesOptionBlock(commands, blocks); + SGCONF::AppendCorpsOptionBlock(commands, blocks); + + SGCONF::PARSER_STATE state(false, argc, argv); + + try + { + state = blocks.Parse(--argc, ++argv); // Skipping self name + } + catch (const SGCONF::OPTION::ERROR& ex) { - std::cerr << "Unknown option: '" << *state.argv << "'\n"; - return -1; + std::cerr << ex.what() << "\n"; + return -1; } -try -{ -SGCONF::CONFIG configOverride(config); + if (state.stop) + return 0; -if (config.configFile.empty()) + if (state.argc > 0) { - const char * mainConfigFile = "/etc/sgconf/sgconf.conf"; - if (access(mainConfigFile, R_OK) == 0) - block.ParseFile(mainConfigFile); - ReadUserConfigFile(block); + std::cerr << "Unknown option: '" << *state.argv << "'\n"; + return -1; } -else + + try { - block.ParseFile(config.configFile.data()); - } + // Preserve config values parsed from the command line + SGCONF::CONFIG configOverride(config); + + if (!config.configFile) + { + // Read main config file. + const char * mainConfigFile = "/etc/sgconf/sgconf.conf"; + if (access(mainConfigFile, R_OK) == 0) + block.ParseFile(mainConfigFile); + // Read XDG-stuff. + ReadUserConfigFile(block); + } + else + { + // Read user-supplied file. + block.ParseFile(config.configFile.value()); + } -config = configOverride; + // Apply overrides from the command line + config.splice(configOverride); -if (!config.showConfig.empty() && config.showConfig.data()) + if (config.showConfig && config.showConfig.value()) + { + std::cout << config.Serialize() << std::endl; + return 0; + } + return commands.Execute(config) ? 0 : -1; + } + catch (const std::exception& ex) { - std::cout << config.Serialize() << std::endl; - return 0; + std::cerr << ex.what() << "\n"; + return -1; } -return commands.Execute(config) ? 0 : -1; } -catch (const std::exception& ex) -{ -std::cerr << ex.what() << "\n"; -return -1; -} -} -//----------------------------------------------------------------------------- - -namespace -{ - -/*void UsageTariffs(bool full) -{ -std::cout << "Tariffs management options:\n" - << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n"; -if (full) - std::cout << "\t\t--name\t\t\t\tshow tariff's name\n" - << "\t\t--fee\t\t\t\tshow tariff's fee\n" - << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n" - << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n" - << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n"; -std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to show\n" - << "\t\t--fee\t\t\t\tshow tariff's fee\n" - << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n" - << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n" - << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n"; -std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to add\n" - << "\t\t--fee \t\t\tstariff's fee\n" - << "\t\t--free \t\t\ttariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost \t\ttariff's cost of \"freeze\"\n" - << "\t\t--traff-type \t\twhat type of traffi will be accounted by the tariff\n" - << "\t\t--times \t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n" - << "\t\t--prices-day-a \t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n" - << "\t\t--prices-night-a \tslash-separated list of prices for \"night\" traffic before threshold for each direction\n" - << "\t\t--prices-day-b \t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n" - << "\t\t--prices-night-b \tslash-separated list of prices for \"night\" traffic after threshold for each direction\n" - << "\t\t--single-prices \tslash-separated list of \"single price\" flags for each direction\n" - << "\t\t--no-discounts \t\tslash-separated list of \"no discount\" flags for each direction\n" - << "\t\t--thresholds \tslash-separated list of thresholds (in Mb) for each direction\n\n"; -std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to delete\n\n"; -std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to change\n" - << "\t\t--fee \t\t\tstariff's fee\n" - << "\t\t--free \t\t\ttariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost \t\ttariff's cost of \"freeze\"\n" - << "\t\t--traff-type \t\twhat type of traffix will be accounted by the tariff\n" - << "\t\t--dir \t\t\tnumber of direction data to change\n" - << "\t\t\t--time