Simplify/enhance command_line::is_yes etc.

This uses templates to simplify the is_yes (etc.) functions, also
removing a boost dependency and making them more flexible where callers
sometimes want "is_yes or one of these other truthy strings".
This commit is contained in:
Jason Rhinelander 2020-03-20 15:46:32 -03:00
parent 5fd8939c6a
commit d3098ce023
6 changed files with 56 additions and 66 deletions

View file

@ -29,55 +29,11 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "command_line.h"
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "common/i18n.h"
#include "common/string_util.h"
namespace command_line
{
namespace
{
const char* tr(const char* str)
{
return i18n_translate(str, "command_line");
}
}
static bool str_compare_with_boost(const std::string &str, char const *check_str)
{
boost::algorithm::is_iequal ignore_case{};
if (boost::algorithm::equals(check_str, str, ignore_case))
return true;
if (boost::algorithm::equals(command_line::tr(check_str), str, ignore_case))
return true;
return false;
}
bool is_yes(const std::string& str)
{
bool result = (str == "y" || str == "Y") || str_compare_with_boost(str, "yes");
return result;
}
bool is_no(const std::string& str)
{
bool result = (str == "n" || str == "N") || str_compare_with_boost(str, "no");
return result;
}
bool is_cancel(const std::string& str)
{
bool result = (str == "c" || str == "C") || str_compare_with_boost(str, "cancel");
return result;
}
bool is_back(const std::string& str)
{
bool result = (str == "b" || str == "B") || str_compare_with_boost(str, "back");
return result;
}
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
}

View file

@ -40,16 +40,29 @@
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include "include_base_utils.h"
#include "common/string_util.h"
#include "common/i18n.h"
namespace command_line
{
inline const char* tr(const char* str) { return i18n_translate(str, "command_line"); }
//! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`.
bool is_yes(const std::string& str);
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
bool is_no(const std::string& str);
bool is_cancel(const std::string& str);
bool is_back(const std::string& str);
/// @return True if `str` is (case-insensitively) y, yes, a potentially translated yes, or any of
/// the optional extra arguments passed in.
template <typename S, typename... More>
bool is_yes(const S& str, const More&... more) { return tools::string_iequal_any(str, "y", "yes", tr("yes"), more...); }
/// @return True if `str` is (case-insensitively) n, no, or a potentially translated no, or any of
/// the optional extra arguments passed in.
template <typename S, typename... More>
bool is_no(const S& str, const More&... more) { return tools::string_iequal_any(str, "n", "no", tr("no"), more...); }
/// @return True if `str` is (case-insensitively) c, cancel, or a potentially translated cancel,
/// or any of the optional extra arguments passed in.
template <typename S, typename... More>
bool is_cancel(const S& str, const More&... more) { return tools::string_iequal_any(str, "c", "cancel", tr("cancel"), more...); }
/// @return True if `str` is (case-insensitively) b, back, or a potentially translated back, or
/// any of the optional extra arguments passed in.
template <typename S, typename... More>
bool is_back(const S& str, const More&... more) { return tools::string_iequal_any(str, "b", "back", tr("back"), more...); }
template<typename T, bool required = false, bool dependent = false, int NUM_DEPS = 1>
struct arg_descriptor;

View file

@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <string>
#define QT_TRANSLATE_NOOP(context,str) i18n_translate(str,context)

31
src/common/string_util.h Normal file
View file

@ -0,0 +1,31 @@
#pragma once
#include <lokimq/string_view.h>
#include <iterator>
namespace tools {
/// Returns true if the first string is equal to the second string, compared case-insensitively.
inline bool string_iequal(lokimq::string_view s1, lokimq::string_view s2) {
return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(), [](char a, char b) {
return std::tolower(static_cast<unsigned char>(a)) == std::tolower(static_cast<unsigned char>(b)); });
}
/// Returns true if the first string matches any of the given strings case-insensitively. Arguments
/// must be string literals, std::string, or lokimq::string_views
#ifdef __cpp_fold_expressions
template <typename S1, typename... S>
bool string_iequal_any(const S1& s1, const S&... s) {
return (string_iequal(s1, s) || ...);
}
#else
template <typename S1>
constexpr bool string_iequal_any(const S1& s1) {
return false;
}
template <typename S1, typename S2, typename... S>
bool string_iequal_any(const S1& s1, const S2& s2, const S&... s) {
return string_iequal(s1, s2) || string_iequal_any(s1, s...);
}
#endif
}

View file

@ -32,6 +32,7 @@
#include "common/command_line.h"
#include "cryptonote_config.h"
#include "daemonizer/daemonizer.h"
#include "cryptonote_core/cryptonote_core.h"
namespace daemon_args
{

View file

@ -60,6 +60,7 @@
#include "common/base58.h"
#include "common/scoped_message_writer.h"
#include "common/loki_integration_test_hooks.h"
#include "common/string_util.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "cryptonote_core/service_node_voting.h"
#include "cryptonote_core/service_node_list.h"
@ -399,29 +400,16 @@ namespace
bool parse_bool(const std::string& s, bool& result)
{
if (s == "1" || command_line::is_yes(s))
if (command_line::is_yes(s, "1", "true", simple_wallet::tr("true")))
{
result = true;
return true;
}
if (s == "0" || command_line::is_no(s))
if (command_line::is_no(s, "0", "false", simple_wallet::tr("false")))
{
result = false;
return true;
}
boost::algorithm::is_iequal ignore_case{};
if (boost::algorithm::equals("true", s, ignore_case) || boost::algorithm::equals(simple_wallet::tr("true"), s, ignore_case))
{
result = true;
return true;
}
if (boost::algorithm::equals("false", s, ignore_case) || boost::algorithm::equals(simple_wallet::tr("false"), s, ignore_case))
{
result = false;
return true;
}
return false;
}