diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index f12e833f6..5ad75fd23 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -137,22 +137,22 @@ static int exportTopology(const Process &) xmrig::Entry::Id xmrig::Entry::get(const Process &process) { const Arguments &args = process.arguments(); - if (args.hasArg("-h") || args.hasArg("--help")) { + if (args.contains("-h", "--help")) { return Usage; } - if (args.hasArg("-V") || args.hasArg("--version") || args.hasArg("--versions")) { + if (args.contains("-V", "--version", "--versions")) { return Version; } # ifdef XMRIG_FEATURE_HWLOC - if (args.hasArg("--export-topology")) { + if (args.contains("--export-topology")) { return Topo; } # endif # ifdef XMRIG_FEATURE_OPENCL - if (args.hasArg("--print-platforms")) { + if (args.contains("--print-platforms")) { return Platforms; } # endif diff --git a/src/base/net/stratum/SelfSelectClient.cpp b/src/base/net/stratum/SelfSelectClient.cpp index f411f3ec9..19b610318 100644 --- a/src/base/net/stratum/SelfSelectClient.cpp +++ b/src/base/net/stratum/SelfSelectClient.cpp @@ -18,7 +18,6 @@ * along with this program. If not, see . */ - #include "base/net/stratum/SelfSelectClient.h" #include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/error/en.h" diff --git a/src/base/tools/Arguments.cpp b/src/base/tools/Arguments.cpp index b6bcec8de..a4daff597 100644 --- a/src/base/tools/Arguments.cpp +++ b/src/base/tools/Arguments.cpp @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -16,19 +16,27 @@ * along with this program. If not, see . */ - -#include #include #include "base/tools/Arguments.h" +namespace xmrig { + + +const String Arguments::m_empty; + + +} // namespace xmrig + + xmrig::Arguments::Arguments(int argc, char **argv) : m_argv(argv), m_argc(argc) { uv_setup_args(argc, argv); + m_data.reserve(argc); for (size_t i = 0; i < static_cast(argc); ++i) { add(argv[i]); @@ -36,52 +44,127 @@ xmrig::Arguments::Arguments(int argc, char **argv) : } -bool xmrig::Arguments::hasArg(const char *name) const +const xmrig::String &xmrig::Arguments::value(const char *key) const { - if (m_argc == 1) { - return false; + if (size() < 3) { + return m_empty; } - return std::find(m_data.begin() + 1, m_data.end(), name) != m_data.end(); -} + for (size_t i = size() - 2; i > 0; i--) { + if (at(i) == key) { + const auto &v = value(i + 1); - -const char *xmrig::Arguments::value(const char *key1, const char *key2) const -{ - const size_t size = m_data.size(); - if (size < 3) { - return nullptr; - } - - for (size_t i = 1; i < size - 1; ++i) { - if (m_data[i] == key1 || (key2 && m_data[i] == key2)) { - return m_data[i + 1]; + if (!v.isNull()) { + return v; + } } } - return nullptr; + return m_empty; +} + + +const xmrig::String &xmrig::Arguments::value(size_t i) const +{ + const auto &v = at(i); + + return v.size() < 1 || *v.data() == '-' ? m_empty : v; +} + + +size_t xmrig::Arguments::pos(const char *key) const +{ + if (size() < 2) { + return 0; + } + + for (size_t i = size() - 1; i > 0; i--) { + if (at(i) == key) { + return i; + } + } + + return 0; +} + + +std::vector xmrig::Arguments::values(const char *key) const +{ + const size_t n = count(key); + if (!n) { + return {}; + } + + std::vector out; + out.reserve(n); + + for (size_t i = 1; i < size(); ++i) { + if (at(i) == key) { + const auto &v = value(i + 1); + + if (!v.isNull()) { + ++i; + out.emplace_back(v); + } + } + } + + return out; +} + + +void xmrig::Arguments::forEach(const Callback &callback) const +{ + for (size_t i = 1; i < size(); ++i) { + const auto &v = value(i + 1); + callback(at(i), v, i); + + if (!v.isNull()) { + ++i; + } + } } void xmrig::Arguments::add(const char *arg) { - if (arg == nullptr) { + const size_t size = arg == nullptr ? 0U : strlen(arg); + + if (size < 1) { return; } - const size_t size = strlen(arg); - if (size > 4 && arg[0] == '-' && arg[1] == '-') { - const char *p = strchr(arg, '='); + if (*arg != '-') { + return add(arg, size); + } - if (p) { - const auto keySize = static_cast(p - arg); + if (size > 1 && arg[1] != '-') { + static char tmp[3] = { 0x2d, 0x00, 0x00 }; - m_data.emplace_back(arg, keySize); - m_data.emplace_back(arg + keySize + 1); + for (size_t i = 1; i < size; i++) { + tmp[1] = arg[i]; + + add(tmp, 2); + } + + return; + } + + if (size > 3) { + const char *p = nullptr; + + if (size > 5 && (p = strchr(arg, '='))) { + const auto ks = static_cast(p - arg); + + add(arg, ks); + + if (size - ks > 1) { + add(arg + ks + 1, size - ks - 1); + } return; } - } - m_data.emplace_back(arg); + add(arg, size); + } } diff --git a/src/base/tools/Arguments.h b/src/base/tools/Arguments.h index a65c44598..3e8e1b425 100644 --- a/src/base/tools/Arguments.h +++ b/src/base/tools/Arguments.h @@ -1,6 +1,6 @@ /* XMRig - * Copyright (c) 2018-2020 SChernykh - * Copyright (c) 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -20,7 +20,8 @@ #define XMRIG_ARGUMENTS_H -#include +#include +#include #include "base/tools/String.h" @@ -32,20 +33,63 @@ namespace xmrig { class Arguments { public: + using Callback = std::function; + Arguments(int argc, char **argv); - bool hasArg(const char *name) const; - const char *value(const char *key1, const char *key2 = nullptr) const; + template + bool contains(Args... args) const { + static_assert(sizeof...(args) >= 2, "Expected at least 2 arguments"); - inline char **argv() const { return m_argv; } - inline const std::vector &data() const { return m_data; } - inline int argc() const { return m_argc; } + for (const char *key : { args... }) { + if (contains(key)) { + return true; + } + } + + return false; + } + + template + const String &value(Args... args) const { + static_assert(sizeof...(args) >= 2, "Expected at least 2 arguments"); + + for (const char *key : { args... }) { + const auto &v = value(key); + if (v) { + return v; + } + } + + return m_empty; + } + + const String &value(const char *key) const; + const String &value(size_t i) const; + size_t pos(const char *key) const; + std::vector values(const char *key) const; + void forEach(const Callback &callback) const; + + inline bool contains(const char *key) const { return size() > 1 && std::find(m_data.begin() + 1, m_data.end(), key) != m_data.end(); } + inline char **argv() const { return m_argv; } + inline const std::vector &data() const { return m_data; } + inline const String &at(size_t i) const { return i < size() ? m_data[i] : m_empty; } + inline int argc() const { return m_argc; } + inline size_t count(const char *key) const { return size() > 1 ? std::count(m_data.begin() + 1, m_data.end(), key) : 0U; } + inline size_t size() const { return m_data.size(); } + + inline const String &operator[](size_t i) const { return at(i); } private: + static const String m_empty; + + inline void add(const char *arg, size_t size) { m_data.emplace_back(arg, size); } + + void add(const char *arg); char **m_argv; - int m_argc; + const int m_argc; std::vector m_data; };