Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions choc/containers/choc_ArgumentList.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct ArgumentList
{
ArgumentList() = default;
ArgumentList (int argc, const char* const* argv);
ArgumentList (std::vector<std::string> tokens);

/// Returns the number of tokens in the list
size_t size() const;
Expand Down Expand Up @@ -181,6 +182,10 @@ inline ArgumentList::ArgumentList (int argc, const char* const* argv)
#endif
}

inline ArgumentList::ArgumentList (std::vector<std::string> tokens_) : tokens (tokens_)
{
}

inline size_t ArgumentList::size() const
{
return tokens.size();
Expand Down Expand Up @@ -218,6 +223,15 @@ inline bool ArgumentList::removeIfFound (std::string_view arg)
inline int ArgumentList::indexOf (std::string_view arg) const
{
CHOC_ASSERT (! choc::text::trim (arg).empty());

if (! isOption (arg))
{
if (auto singleIndex = indexOf ("-" + std::string (arg)); singleIndex != -1)
return singleIndex;

return indexOf ("--" + std::string (arg));
}

bool isDoubleDash = isDoubleDashOption (arg);

for (size_t i = 0; i < tokens.size(); ++i)
Expand All @@ -241,11 +255,17 @@ inline void ArgumentList::throwIfNotFound (std::string_view arg) const

inline std::optional<std::string> ArgumentList::getValueFor (std::string_view argToFind, bool remove)
{
if (! isOption (argToFind))
{
if (auto v = getValueFor ("-" + std::string (argToFind), remove); v.has_value())
return v;

return getValueFor ("--" + std::string (argToFind), remove);
}

bool isDoubleDash = isDoubleDashOption (argToFind);
bool isSingleDash = isSingleDashOption (argToFind);

CHOC_ASSERT (isDoubleDash || isSingleDash); // the arg you pass in needs to be a "--option" or "-option"

if (auto i = indexOf (argToFind); i >= 0)
{
auto index = static_cast<size_t> (i);
Expand Down
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16)

project(choc_tests)

add_executable(choc_tests choc_tests.cpp)
add_executable(choc_tests choc_tests.cpp choc_tests.h)

# To test V8, there needs to be a suitable folder somewhere with a build
# set(V8_LOCATION "/path_to_your_v8_folder/v8")
Expand Down
183 changes: 183 additions & 0 deletions tests/choc_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
#include "../choc/javascript/choc_javascript.h"
#include "../choc/javascript/choc_javascript_Timer.h"
#include "../choc/javascript/choc_javascript_Console.h"
#include "../choc/containers/choc_ArgumentList.h"

#if CHOC_ENABLE_HTTP_SERVER_TEST
#include "../choc/network/choc_HTTPServer.h"
Expand Down Expand Up @@ -1383,6 +1384,187 @@ inline void testMIDI (choc::test::TestProgress& progress)
}
}

//==============================================================================
inline void testArgumentList (choc::test::TestProgress& progress)
{
CHOC_CATEGORY (ArgumentList);

{
CHOC_TEST (ArgcvParsingDoubleDash)

const char* argv[] = { "executableName", "other1", "--flag1", "other2", "--param1=foo", "--flag2", "--param2=bar", "--param3=42", "other3" };

choc::ArgumentList args (9, argv);

CHOC_EXPECT_TRUE (args.contains ("--flag1"));
CHOC_EXPECT_TRUE (args.contains ("--param1"));
CHOC_EXPECT_TRUE (args.contains ("--flag2"));
CHOC_EXPECT_TRUE (args.contains ("--param2"));
CHOC_EXPECT_TRUE (args.contains ("--param3"));
CHOC_EXPECT_FALSE (args.contains ("--flag3"));

CHOC_EXPECT_EQ (args.indexOf ("--flag1"), 1);
CHOC_EXPECT_EQ (args.indexOf ("--param1"), 3);
CHOC_EXPECT_EQ (args.indexOf ("--flag2"), 4);
CHOC_EXPECT_EQ (args.indexOf ("--param2"), 5);
CHOC_EXPECT_EQ (args.indexOf ("--param3"), 6);
CHOC_EXPECT_EQ (args.indexOf ("--flag3"), -1);

CHOC_EXPECT_EQ (args.getValueFor ("--param1", false).value(), "foo");
CHOC_EXPECT_EQ (args.getValueFor ("--param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("--param3", false).value(), "42");

CHOC_EXPECT_TRUE (args.removeIfFound ("--flag1"));
CHOC_EXPECT_TRUE (args.removeIfFound ("--param1"));

CHOC_EXPECT_FALSE (args.getValueFor ("--param1", false).has_value());
CHOC_EXPECT_EQ (args.getValueFor ("--param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("--param3", false).value(), "42");

CHOC_EXPECT_EQ (args.removeValueFor ("--param2", "default"), "bar");
CHOC_EXPECT_EQ (args.removeValueFor ("--param2", "default"), "default");
CHOC_EXPECT_FALSE (args.removeValueFor ("--param2").has_value());
CHOC_EXPECT_FALSE (args.getValueFor ("--param2", false).has_value());

CHOC_EXPECT_EQ (args.removeIntValue<int> ("--param3", 101), 42);
CHOC_EXPECT_EQ (args.removeIntValue<int> ("--param3", 101), 101);

CHOC_EXPECT_EQ (args.indexOf ("--flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--flag2"), 2);
CHOC_EXPECT_EQ (args.indexOf ("--param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--flag3"), -1);

args.removeIndex (2);

CHOC_EXPECT_EQ (args.indexOf ("--flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--flag2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("--flag3"), -1);
}

{
CHOC_TEST (ArgcvParsingSingleDash)

const char* argv[] = { "executableName", "other1", "-flag1", "other2", "-param1", "foo", "-flag2", "-param2", "bar", "-param3", "42", "other3" };

choc::ArgumentList args (12, argv);

CHOC_EXPECT_TRUE (args.contains ("-flag1"));
CHOC_EXPECT_TRUE (args.contains ("-param1"));
CHOC_EXPECT_TRUE (args.contains ("-flag2"));
CHOC_EXPECT_TRUE (args.contains ("-param2"));
CHOC_EXPECT_TRUE (args.contains ("-param3"));
CHOC_EXPECT_FALSE (args.contains ("-flag3"));

CHOC_EXPECT_EQ (args.indexOf ("-flag1"), 1);
CHOC_EXPECT_EQ (args.indexOf ("-param1"), 3);
CHOC_EXPECT_EQ (args.indexOf ("-flag2"), 5);
CHOC_EXPECT_EQ (args.indexOf ("-param2"), 6);
CHOC_EXPECT_EQ (args.indexOf ("-param3"), 8);
CHOC_EXPECT_EQ (args.indexOf ("-flag3"), -1);

CHOC_EXPECT_EQ (args.getValueFor ("-param1", false).value(), "foo");
CHOC_EXPECT_EQ (args.getValueFor ("-param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("-param3", false).value(), "42");

CHOC_EXPECT_TRUE (args.removeIfFound ("-flag1"));
CHOC_EXPECT_TRUE (args.removeIfFound ("-param1"));

CHOC_EXPECT_FALSE (args.getValueFor ("-param1", false).has_value());
CHOC_EXPECT_EQ (args.getValueFor ("-param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("-param3", false).value(), "42");

CHOC_EXPECT_EQ (args.removeValueFor ("-param2", "default"), "bar");
CHOC_EXPECT_EQ (args.removeValueFor ("-param2", "default"), "default");
CHOC_EXPECT_FALSE (args.removeValueFor ("-param2").has_value());
CHOC_EXPECT_FALSE (args.getValueFor ("-param2", false).has_value());

CHOC_EXPECT_EQ (args.removeIntValue<int> ("-param3", 101), 42);
CHOC_EXPECT_EQ (args.removeIntValue<int> ("-param3", 101), 101);

CHOC_EXPECT_EQ (args.indexOf ("-flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-flag2"), 3);
CHOC_EXPECT_EQ (args.indexOf ("-param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-flag3"), -1);

args.removeIndex (3);

CHOC_EXPECT_EQ (args.indexOf ("-flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-flag2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("-flag3"), -1);
}


{
CHOC_TEST (ArgcvParsingMixed)

const char* argv[] = { "executableName", "other1", "-flag1", "other2", "-param1", "foo", "--flag2", "--param2=bar", "-param3", "42", "other3" };

choc::ArgumentList args (12, argv);

CHOC_EXPECT_TRUE (args.contains ("flag1"));
CHOC_EXPECT_TRUE (args.contains ("param1"));
CHOC_EXPECT_TRUE (args.contains ("flag2"));
CHOC_EXPECT_TRUE (args.contains ("param2"));
CHOC_EXPECT_TRUE (args.contains ("param3"));
CHOC_EXPECT_FALSE (args.contains ("flag3"));

CHOC_EXPECT_EQ (args.indexOf ("flag1"), 1);
CHOC_EXPECT_EQ (args.indexOf ("param1"), 3);
CHOC_EXPECT_EQ (args.indexOf ("flag2"), 5);
CHOC_EXPECT_EQ (args.indexOf ("param2"), 6);
CHOC_EXPECT_EQ (args.indexOf ("param3"), 7);
CHOC_EXPECT_EQ (args.indexOf ("flag3"), -1);

CHOC_EXPECT_EQ (args.getValueFor ("param1", false).value(), "foo");
CHOC_EXPECT_EQ (args.getValueFor ("param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("param3", false).value(), "42");

CHOC_EXPECT_TRUE (args.removeIfFound ("flag1"));
CHOC_EXPECT_TRUE (args.removeIfFound ("param1"));

CHOC_EXPECT_FALSE (args.getValueFor ("param1", false).has_value());
CHOC_EXPECT_EQ (args.getValueFor ("param2", false).value(), "bar");
CHOC_EXPECT_EQ (args.getValueFor ("param3", false).value(), "42");

CHOC_EXPECT_EQ (args.removeValueFor ("param2", "default"), "bar");
CHOC_EXPECT_EQ (args.removeValueFor ("param2", "default"), "default");
CHOC_EXPECT_FALSE (args.removeValueFor ("param2").has_value());
CHOC_EXPECT_FALSE (args.getValueFor ("param2", false).has_value());

CHOC_EXPECT_EQ (args.removeIntValue<int> ("param3", 101), 42);
CHOC_EXPECT_EQ (args.removeIntValue<int> ("param3", 101), 101);

CHOC_EXPECT_EQ (args.indexOf ("flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("flag2"), 3);
CHOC_EXPECT_EQ (args.indexOf ("param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("flag3"), -1);

args.removeIndex (3);

CHOC_EXPECT_EQ (args.indexOf ("flag1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("param1"), -1);
CHOC_EXPECT_EQ (args.indexOf ("flag2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("param2"), -1);
CHOC_EXPECT_EQ (args.indexOf ("flag3"), -1);
}

{
CHOC_TEST (ArgcvParsingStringArgs)

choc::ArgumentList args (choc::text::splitAtWhitespace ("-flag1 --flag2 --param1=foo other stuff"));

CHOC_EXPECT_TRUE (args.contains ("flag1"));
CHOC_EXPECT_EQ (args.removeValueFor ("param1", "default"), "foo");
}
}

//==============================================================================
inline void testAudioBuffers (choc::test::TestProgress& progress)
{
Expand Down Expand Up @@ -4135,6 +4317,7 @@ inline bool runAllTests (choc::test::TestProgress& progress, bool multithread)

std::function<void(choc::test::TestProgress&)> testFunctions[] =
{
testArgumentList,
testExecute,
testHTTPServer,
testZLIB,
Expand Down
Loading