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;
};