Add function for parsing command-line arguments into argument list
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include "CommandLine.h"
|
#include "CommandLine.h"
|
||||||
#include "Engine/Core/Collections/Array.h"
|
#include "Engine/Core/Collections/Array.h"
|
||||||
#include "Engine/Core/Utilities.h"
|
#include "Engine/Core/Utilities.h"
|
||||||
|
#include "Engine/Core/Types/StringView.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
CommandLine::OptionsData CommandLine::Options;
|
CommandLine::OptionsData CommandLine::Options;
|
||||||
@@ -170,3 +171,63 @@ bool CommandLine::Parse(const Char* cmdLine)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandLine::ParseArguments(const StringView& cmdLine, Array<StringAnsi>& arguments)
|
||||||
|
{
|
||||||
|
int32 start = 0;
|
||||||
|
int32 quotesStart = -1;
|
||||||
|
int32 length = cmdLine.Length();
|
||||||
|
for (int32 i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (cmdLine[i] == ' ' && quotesStart == -1)
|
||||||
|
{
|
||||||
|
int32 count = i - start;
|
||||||
|
if (count > 0)
|
||||||
|
arguments.Add(StringAnsi(cmdLine.Substring(start, count)));
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
else if (cmdLine[i] == '\"')
|
||||||
|
{
|
||||||
|
if (quotesStart >= 0)
|
||||||
|
{
|
||||||
|
if (i + 1 < length && cmdLine[i + 1] != ' ')
|
||||||
|
{
|
||||||
|
// End quotes are in the middle of the current word,
|
||||||
|
// continue until the end of the current word.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int32 offset = 1;
|
||||||
|
if (quotesStart == start && cmdLine[start] == '\"')
|
||||||
|
{
|
||||||
|
// Word starts and ends with quotes, only include the quoted content.
|
||||||
|
quotesStart++;
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
|
else if (quotesStart != start)
|
||||||
|
{
|
||||||
|
// Start quotes in the middle of the word, include the whole word.
|
||||||
|
quotesStart = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 count = i - quotesStart + offset;
|
||||||
|
if (count > 0)
|
||||||
|
arguments.Add(StringAnsi(cmdLine.Substring(quotesStart, count)));
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
quotesStart = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
quotesStart = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int32 count = length - start;
|
||||||
|
if (count > 0)
|
||||||
|
arguments.Add(StringAnsi(cmdLine.Substring(start, count)));
|
||||||
|
if (quotesStart >= 0)
|
||||||
|
return true; // Missing last closing quote
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Engine/Core/Types/String.h"
|
#include "Engine/Core/Types/String.h"
|
||||||
#include "Engine/Core/Types/Nullable.h"
|
#include "Engine/Core/Types/Nullable.h"
|
||||||
|
#include "Engine/Core/Collections/Array.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command line options helper.
|
/// Command line options helper.
|
||||||
@@ -219,4 +220,12 @@ public:
|
|||||||
/// <param name="cmdLine">The command line.</param>
|
/// <param name="cmdLine">The command line.</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
static bool Parse(const Char* cmdLine);
|
static bool Parse(const Char* cmdLine);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the command line arguments string into string list of arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cmdLine">The command line.</param>
|
||||||
|
/// <param name="arguments">The parsed arguments</param>
|
||||||
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
|
static bool ParseArguments(const StringView& cmdLine, Array<StringAnsi>& arguments);
|
||||||
};
|
};
|
||||||
|
|||||||
82
Source/Engine/Tests/TestCommandLine.cpp
Normal file
82
Source/Engine/Tests/TestCommandLine.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#include "Engine/Engine/CommandLine.h"
|
||||||
|
#include "Engine/Core/Types/StringView.h"
|
||||||
|
#include "Engine/Core/Collections/Array.h"
|
||||||
|
#include <ThirdParty/catch2/catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("CommandLine")
|
||||||
|
{
|
||||||
|
SECTION("Test Argument Parser")
|
||||||
|
{
|
||||||
|
SECTION("Single quoted word")
|
||||||
|
{
|
||||||
|
String input("\"word\"");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 1);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("word")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Quotes at the beginning of the word")
|
||||||
|
{
|
||||||
|
String input("start\"word\"");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 1);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("start\"word\"")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Quotes in the middle of the word")
|
||||||
|
{
|
||||||
|
String input("start\"word\"end");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 1);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("start\"word\"end")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Quotes at the end of the word")
|
||||||
|
{
|
||||||
|
String input("\"word\"end");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 1);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("\"word\"end")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Multiple words")
|
||||||
|
{
|
||||||
|
String input("The quick brown fox");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 4);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("The")) == 0);
|
||||||
|
CHECK(arguments[1].Compare(StringAnsi("quick")) == 0);
|
||||||
|
CHECK(arguments[2].Compare(StringAnsi("brown")) == 0);
|
||||||
|
CHECK(arguments[3].Compare(StringAnsi("fox")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Multiple words with quotes")
|
||||||
|
{
|
||||||
|
String input("The \"quick brown fox\" jumps over the \"lazy\" dog");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 7);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("The")) == 0);
|
||||||
|
CHECK(arguments[1].Compare(StringAnsi("quick brown fox")) == 0);
|
||||||
|
CHECK(arguments[2].Compare(StringAnsi("jumps")) == 0);
|
||||||
|
CHECK(arguments[3].Compare(StringAnsi("over")) == 0);
|
||||||
|
CHECK(arguments[4].Compare(StringAnsi("the")) == 0);
|
||||||
|
CHECK(arguments[5].Compare(StringAnsi("lazy")) == 0);
|
||||||
|
CHECK(arguments[6].Compare(StringAnsi("dog")) == 0);
|
||||||
|
}
|
||||||
|
SECTION("Flax.Build sample parameters")
|
||||||
|
{
|
||||||
|
String input("-log -mutex -workspace=\"C:\\path with spaces/to/FlaxEngine/\" -configuration=Debug -hotreload=\".HotReload.1\"");
|
||||||
|
Array<StringAnsi> arguments;
|
||||||
|
CHECK(!CommandLine::ParseArguments(input, arguments));
|
||||||
|
CHECK(arguments.Count() == 5);
|
||||||
|
CHECK(arguments[0].Compare(StringAnsi("-log")) == 0);
|
||||||
|
CHECK(arguments[1].Compare(StringAnsi("-mutex")) == 0);
|
||||||
|
CHECK(arguments[2].Compare(StringAnsi("-workspace=\"C:\\path with spaces/to/FlaxEngine/\"")) == 0);
|
||||||
|
CHECK(arguments[3].Compare(StringAnsi("-configuration=Debug")) == 0);
|
||||||
|
CHECK(arguments[4].Compare(StringAnsi("-hotreload=\".HotReload.1\"")) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user