]> git.stg.codes - stg.git/commitdiff
Implemented --add-admin.
authorMaxim Mamontov <faust.madf@gmail.com>
Wed, 28 May 2014 20:01:41 +0000 (23:01 +0300)
committerMaxim Mamontov <faust.madf@gmail.com>
Wed, 28 May 2014 20:01:41 +0000 (23:01 +0300)
14 files changed:
include/stg/admin_conf.h
projects/sgconf/action.h
projects/sgconf/actions.h
projects/sgconf/admins.cpp
projects/sgconf/api_action.cpp
projects/sgconf/api_action.h
projects/sgconf/corps.cpp
projects/sgconf/main.cpp
projects/sgconf/options.cpp
projects/sgconf/options.h
projects/sgconf/services.cpp
projects/sgconf/tariffs.cpp
projects/sgconf/users.cpp
projects/sgconf/utils.h [new file with mode: 0644]

index 8b1a988e1877ff79c77e73bfd404b67e22710583..7fbf44408c72ea45807a8b8f5ae5c1d942df6f6e 100644 (file)
@@ -78,6 +78,7 @@ struct ADMIN_CONF
 //-----------------------------------------------------------------------------
 struct ADMIN_CONF_RES
 {
+    ADMIN_CONF_RES() {}
     ADMIN_CONF_RES(const ADMIN_CONF & conf)
         : priv(conf.priv),
           login(conf.login),
index b45ac4703f91867039f77f3dc8e67e67cf8b1555..940ea7f6272673bad87ab08aa12819e8e86a602f 100644 (file)
@@ -41,7 +41,7 @@ class ACTION
         virtual std::string ParamDescription() const = 0;
         virtual std::string DefaultDescription() const = 0;
         virtual OPTION_BLOCK & Suboptions() = 0;
-        virtual PARSER_STATE Parse(int argc, char ** argv) = 0;
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0;
         virtual void ParseValue(const std::string &) {}
 
         class ERROR : public std::runtime_error
index c47f9776090b7adde79252cbb931bb26cde65cc7..07bcfb8b22b19c58f803d03e8c8d85a53975a31a 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <string>
 
+#include <cassert>
+
 namespace SGCONF
 {
 
@@ -46,7 +48,7 @@ class FUNC0_ACTION : public ACTION
         virtual std::string ParamDescription() const { return ""; }
         virtual std::string DefaultDescription() const { return ""; }
         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv)
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/)
         {
         m_func();
         return PARSER_STATE(true, argc, argv);
@@ -88,7 +90,7 @@ class PARAM_ACTION : public ACTION
         virtual std::string ParamDescription() const { return m_description; }
         virtual std::string DefaultDescription() const;
         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv);
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
         virtual void ParseValue(const std::string & value);
 
     private:
@@ -117,7 +119,7 @@ return m_hasDefault ? " (default: '" + m_defaltValue + "')"
 
 template <typename T>
 inline
-PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv)
+PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv, void * /*data*/)
 {
 if (argc == 0 ||
     argv == NULL ||
@@ -151,7 +153,7 @@ m_param = stringValue;
 
 template <>
 inline
-PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv)
+PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv, void * /*data*/)
 {
 if (argc == 0 ||
     argv == NULL ||
@@ -182,10 +184,8 @@ class KV_ACTION : public ACTION
 {
     public:
         KV_ACTION(const std::string & name,
-                  std::map<std::string, std::string> & kvs,
                   const std::string & paramDescription)
             : m_name(name),
-              m_kvs(kvs),
               m_description(paramDescription)
         {}
 
@@ -194,32 +194,32 @@ class KV_ACTION : public ACTION
         virtual std::string ParamDescription() const { return m_description; }
         virtual std::string DefaultDescription() const { return ""; }
         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv);
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * data);
 
     private:
         std::string m_name;
-        std::map<std::string, std::string> & m_kvs;
         std::string m_description;
         OPTION_BLOCK m_suboptions;
 };
 
 inline
-PARSER_STATE KV_ACTION::Parse(int argc, char ** argv)
+PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data)
 {
 if (argc == 0 ||
     argv == NULL ||
     *argv == NULL)
     throw ERROR("Missing argument.");
-m_kvs[m_name] = *argv;
+assert(data != NULL && "Expecting container pointer.");
+std::map<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(data);
+kvs[m_name] = *argv;
 return PARSER_STATE(false, --argc, ++argv);
 }
 
 inline
 KV_ACTION * MakeKVAction(const std::string & name,
-                         std::map<std::string, std::string> & kvs,
                          const std::string & paramDescription)
 {
-return new KV_ACTION(name, kvs, paramDescription);
+return new KV_ACTION(name, paramDescription);
 }
 
 } // namespace SGCONF
index b560f581286269d6dc102cb18efa7630ff4ee048..6a59fa28b182f6c90e4389fe2743d67be64cef01 100644 (file)
@@ -3,6 +3,7 @@
 #include "api_action.h"
 #include "options.h"
 #include "config.h"
+#include "utils.h"
 
 #include "stg/servconf.h"
 #include "stg/servconf_types.h"
@@ -46,10 +47,28 @@ std::cout << Indent(level, true) << "login: " << info.login << "\n"
 std::vector<SGCONF::API_ACTION::PARAM> GetAdminParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"priv", "<priv>", "priviledges"});
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
+params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
 return params;
 }
 
+void ConvPriv(const std::string & value, RESETABLE<PRIV> & res)
+{
+if (value.length() != 9)
+    throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number.");
+PRIV priv;
+priv.corpChg = (value[0] == '0' ? 0 : 1);
+priv.serviceChg = (value[1] == '0' ? 0 : 1);
+priv.tariffChg = (value[2] == '0' ? 0 : 1);
+priv.adminChg = (value[3] == '0' ? 0 : 1);
+priv.userAddDel = (value[4] == '0' ? 0 : 1);
+priv.userPasswd = (value[5] == '0' ? 0 : 1);
+priv.userCash = (value[6] == '0' ? 0 : 1);
+priv.userConf = (value[7] == '0' ? 0 : 1);
+priv.userStat = (value[8] == '0' ? 0 : 1);
+res = priv;
+}
+
 void SimpleCallback(bool result,
                     const std::string & reason,
                     void * /*data*/)
@@ -133,11 +152,17 @@ return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok;
 
 bool AddAdminFunction(const SGCONF::CONFIG & config,
                       const std::string & arg,
-                      const std::map<std::string, std::string> & /*options*/)
+                      const std::map<std::string, std::string> & options)
 {
 // TODO
-std::cerr << "Unimplemented.\n";
-return false;
+ADMIN_CONF_RES conf;
+conf.login = arg;
+SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
+STG::SERVCONF proto(config.server.data(),
+                    config.port.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok;
 }
 
 bool ChgAdminFunction(const SGCONF::CONFIG & config,
index 420f5f0a91029e5d258c5c25677108b8764aeef6..d5b1e8e65089b668f0b42c033d47a5f2e627487a 100644 (file)
@@ -3,7 +3,7 @@
 #include "actions.h"
 #include "parser_state.h"
 
-SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv)
+SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/)
 {
 PARSER_STATE state(false, argc, argv);
 if (!m_argument.empty())
@@ -16,7 +16,7 @@ if (!m_argument.empty())
     --state.argc;
     ++state.argv;
     }
-m_suboptions.Parse(state.argc, state.argv);
+state = m_suboptions.Parse(state.argc, state.argv, &m_params);
 m_commands.Add(m_funPtr, m_argument, m_params);
 return state;
 }
@@ -34,7 +34,7 @@ SGCONF::API_ACTION::API_ACTION(COMMANDS & commands,
 std::vector<PARAM>::const_iterator it(params.begin());
 while (it != params.end())
     {
-    m_suboptions.Add(it->name, MakeKVAction(it->name, m_params, it->shortDescr), it->longDescr);
+    m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
     ++it;
     }
 }
index e5f95b2c98402d25e75b68d99943b02a63da1ce3..f27715ca5f58bf65b042f8591796a71f5bbc185f 100644 (file)
@@ -63,6 +63,13 @@ class API_ACTION : public ACTION
     public:
         struct PARAM
         {
+            PARAM(const std::string & n,
+                  const std::string & s,
+                  const std::string & l)
+                : name(n),
+                  shortDescr(s),
+                  longDescr(l)
+            {}
             std::string name;
             std::string shortDescr;
             std::string longDescr;
@@ -88,7 +95,7 @@ class API_ACTION : public ACTION
         virtual std::string ParamDescription() const { return m_description; }
         virtual std::string DefaultDescription() const { return ""; }
         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv);
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
 
     private:
         COMMANDS & m_commands;
index 97c3add05701906917128f7e6e8ef91ce3a5cc49..826733770f3f42642c26e389e79e0b1efad93e82 100644 (file)
@@ -32,7 +32,7 @@ std::cout << Indent(level, true) << "name: " << info.name << "\n"
 std::vector<SGCONF::API_ACTION::PARAM> GetCorpParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"cash", "<cash>", "\tcorporation's cash"});
+params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\tcorporation's cash"));
 return params;
 }
 
index 73917852462d27aecbd6c78310ba37c68885baef..22e998f3561336c21cd2cfdf77bdaead854501e8 100644 (file)
@@ -163,7 +163,7 @@ class CONFIG_ACTION : public ACTION
         virtual std::string ParamDescription() const { return m_description; }
         virtual std::string DefaultDescription() const { return ""; }
         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv);
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
 
     private:
         SGCONF::CONFIG & m_config;
@@ -175,7 +175,7 @@ class CONFIG_ACTION : public ACTION
 };
 
 
-PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv)
+PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/)
 {
 if (argc == 0 ||
     argv == NULL ||
@@ -298,15 +298,15 @@ else
     }
 
 config = configOverride;
+
+std::cerr << "Config: " << config.Serialize() << std::endl;
+return commands.Execute(config) ? 0 : -1;
 }
 catch (const std::exception& ex)
 {
 std::cerr << ex.what() << "\n";
 return -1;
 }
-
-std::cerr << "Config: " << config.Serialize() << std::endl;
-return commands.Execute(config) ? 0 : -1;
 }
 //-----------------------------------------------------------------------------
 
index f5e423adc46051bcd93e3b68d29d882d5f5436b6..49e04d648d958c75d7b395cc26a9ef53163d20de 100644 (file)
@@ -134,18 +134,20 @@ if (*arg++ != '-')
     return false;
 
 if (*arg == '-')
+{
     return m_longName == arg + 1;
+}
 
 return m_shortName == arg;
 }
 
-PARSER_STATE OPTION::Parse(int argc, char ** argv)
+PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
 {
 if (!m_action)
     throw ERROR("Option is not defined.");
 try
     {
-    return m_action->Parse(argc, argv);
+    return m_action->Parse(argc, argv, data);
     }
 catch (const ACTION::ERROR & ex)
     {
@@ -199,14 +201,16 @@ std::for_each(m_options.begin(),
               std::bind2nd(std::mem_fun_ref(&OPTION::Help), level + 1));
 }
 
-PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv)
+PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
 {
 PARSER_STATE state(false, argc, argv);
+if (state.argc == 0)
+    return state;
 while (state.argc > 0 && !state.stop)
     {
     std::vector<OPTION>::iterator it = std::find_if(m_options.begin(), m_options.end(), std::bind2nd(std::mem_fun_ref(&OPTION::Check), *state.argv));
     if (it != m_options.end())
-        state = it->Parse(--state.argc, ++state.argv);
+        state = it->Parse(--state.argc, ++state.argv, data);
     else
         break;
     ++it;
@@ -243,7 +247,7 @@ PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv)
 {
 PARSER_STATE state(false, argc, argv);
 std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
-while (!state.stop && it != m_blocks.end())
+while (state.argc > 0 && !state.stop && it != m_blocks.end())
     {
     state = it->Parse(state.argc, state.argv);
     ++it;
index 53875091afd57c67a024ddb903355f92b27969f1..c00707bf2d0887d0e7a279f0125eaeecf47e1071 100644 (file)
@@ -50,7 +50,7 @@ class OPTION
         OPTION & operator=(const OPTION & rhs);
 
         void Help(size_t level = 0) const;
-        PARSER_STATE Parse(int argc, char ** argv);
+        PARSER_STATE Parse(int argc, char ** argv, void * data);
         void ParseValue(const std::string & value);
         bool Check(const char * arg) const;
         const std::string & Name() const { return m_longName; }
@@ -85,7 +85,7 @@ class OPTION_BLOCK
 
         void Help(size_t level) const;
 
-        PARSER_STATE Parse(int argc, char ** argv);
+        PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
         void ParseFile(const std::string & filePath);
 
         class ERROR : public std::runtime_error
index 7989de20941916a67fc26da0636c82a83d49bf27..f5d737428c8960026ef2e0558dffc0c68e1e7de0 100644 (file)
@@ -34,9 +34,9 @@ std::cout << Indent(level, true) << "name: " << info.name << "\n"
 std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"cost", "<cost>", "\tcost of the service"});
-params.push_back({"pay-day", "<month day>", "payment day"});
-params.push_back({"comment", "<text>", "comment"});
+params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
+params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
+params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
 return params;
 }
 
index 75cd169fae66b89b5d687c3956104df02f902e99..3da1001a683e92538f9dff7bd0cc34d0de04981c 100644 (file)
@@ -94,15 +94,15 @@ for (size_t i = 0; i < info.dirPrice.size(); ++i)
 std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"fee", "<fee>", "\t\ttariff fee"});
-params.push_back({"free", "<free mb>", "\tprepaid traff"});
-params.push_back({"passive-cost", "<cost>", "\tpassive cost"});
-params.push_back({"traff-type", "<type>", "\ttraff type (up, dow, up+down, max)"});
-params.push_back({"period", "<period>", "\ttarification period (daily, monthly)"});
-params.push_back({"times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"});
-params.push_back({"day-prices", "<price/price, ...>", "coma-separated day prices for each direction"});
-params.push_back({"night-prices", "<price/price, ...>", "coma-separated day prices for each direction"});
-params.push_back({"thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"});
+params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traff"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
+params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraff type (up, dow, up+down, max)"));
+params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
+params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
 return params;
 }
 
index 4560319998873cd5426ed895d1e649547b1a14f5..9c6c30b5c4c02f94150dd71031e4b0b0a468a639 100644 (file)
@@ -71,42 +71,42 @@ if (!info.authBy.empty())
 std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"password", "<password>", "\tuser's password"});
-params.push_back({"cash", "<cash>", "\t\tuser's cash"});
-params.push_back({"credit", "<amount>", "\tuser's credit"});
-params.push_back({"credit-expire", "<date>", "\tcredit expiration"});
-params.push_back({"free", "<free mb>", "\tprepaid traffic"});
-params.push_back({"disabled", "<flag>", "\tdisable user (y|n)"});
-params.push_back({"passive", "<flag>", "\tmake user passive (y|n)"});
-params.push_back({"disable-detail-stat", "<flag>", "disable detail stat (y|n)"});
-params.push_back({"always-online", "<flag>", "\tmake user always online (y|n)"});
-params.push_back({"ips", "<ips>", "\t\tcoma-separated list of ips"});
-params.push_back({"tariff", "<tariff name>", "\tcurrent tariff"});
-params.push_back({"next-tariff", "<tariff name>", "tariff starting from the next month"});
-params.push_back({"group", "<group>", "\t\tuser's group"});
-params.push_back({"note", "<note>", "\t\tuser's note"});
-params.push_back({"email", "<email>", "\t\tuser's email"});
-params.push_back({"name", "<real name>", "\tuser's real name"});
-params.push_back({"address", "<address>", "\tuser's postal address"});
-params.push_back({"phone", "<phone>", "\t\tuser's phone number"});
-params.push_back({"session-traffic", "<up/dn, ...>", "coma-separated session upload and download"});
-params.push_back({"month-traffic", "<up/dn, ...>", "coma-separated month upload and download"});
-params.push_back({"user-data", "<value, ...>", "coma-separated user data values"});
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\t\tuser's cash"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
+params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
+params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
+params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
+params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
+params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
+params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
+params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
+params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
+params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
 return params;
 }
 
 std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"password", "<password>", "\tuser's password"});
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
 return params;
 }
 
 std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
 {
 std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back({"logins", "<login, ...>", "\tlist of logins to send a message"});
-params.push_back({"text", "<text>", "\t\tmessage text"});
+params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
+params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
 return params;
 }
 
diff --git a/projects/sgconf/utils.h b/projects/sgconf/utils.h
new file mode 100644 (file)
index 0000000..2e16b62
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __STG_SGCONF_UTILS_H__
+#define __STG_SGCONF_UTILS_H__
+
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+#include <map>
+
+namespace SGCONF
+{
+
+template <typename T>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+T value;
+if (str2x(it->second, value) < 0)
+    return;
+res = value;
+}
+
+template <typename T, typename F>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res, F conv)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+conv(it->second, res);
+}
+
+template <>
+inline
+void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<std::string> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+res = it->second;
+}
+
+} // namespace SGCONF
+
+#endif