From 6f096e7c4be974b1c79d938e927edc5fdbfa53d3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 4 Oct 2024 12:07:10 -0700 Subject: [PATCH] FHU: Add StringArgumentParser function Split this out so we can unittest it. Adds a unittest to handle specific edge cases. --- .../FEXHeaderUtils/StringArgumentParser.h | 39 ++++++++++ unittests/APITests/ArgumentParser.cpp | 75 +++++++++++++++++++ unittests/APITests/CMakeLists.txt | 1 + 3 files changed, 115 insertions(+) create mode 100644 FEXHeaderUtils/FEXHeaderUtils/StringArgumentParser.h create mode 100644 unittests/APITests/ArgumentParser.cpp diff --git a/FEXHeaderUtils/FEXHeaderUtils/StringArgumentParser.h b/FEXHeaderUtils/FEXHeaderUtils/StringArgumentParser.h new file mode 100644 index 0000000000..2ddfc3f265 --- /dev/null +++ b/FEXHeaderUtils/FEXHeaderUtils/StringArgumentParser.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include + +#include +#include + +namespace FHU { + +/** + * @brief Parses a string of arguments, returning a vector of string_views. + * + * @param ArgumentString The string of arguments to parse + * + * @return The array of parsed arguments + */ +static inline fextl::vector ParseArgumentsFromString(const std::string_view ArgumentString) { + fextl::vector Arguments; + + auto Begin = ArgumentString.begin(); + auto ArgEnd = Begin; + const auto End = ArgumentString.end(); + while (ArgEnd != End && Begin != End) { + // The end of an argument ends with a space or the end of the interpreter line. + ArgEnd = std::find(Begin, End, ' '); + + if (Begin != ArgEnd) { + const auto View = std::string_view(Begin, ArgEnd - Begin); + if (!View.empty()) { + Arguments.emplace_back(View); + } + } + + Begin = ArgEnd + 1; + } + + return Arguments; +} +} // namespace FHU diff --git a/unittests/APITests/ArgumentParser.cpp b/unittests/APITests/ArgumentParser.cpp new file mode 100644 index 0000000000..c67932c7f5 --- /dev/null +++ b/unittests/APITests/ArgumentParser.cpp @@ -0,0 +1,75 @@ +#include + +#include + +TEST_CASE("Basic") { + const auto ArgString = "Test a b c"; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "c"); +} + +TEST_CASE("Basic - Empty") { + const auto ArgString = ""; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 0); +} + +TEST_CASE("Basic - Empty spaces") { + const auto ArgString = " "; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 0); +} + +TEST_CASE("Basic - Space at start") { + const auto ArgString = " Test a b c"; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "c"); +} + +TEST_CASE("Basic - Bonus spaces between args") { + const auto ArgString = "Test a b c"; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "c"); +} + +TEST_CASE("Basic - non printable") { + const auto ArgString = "Test a b \x01c"; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "\x01c"); +} + +TEST_CASE("Basic - Emoji") { + const auto ArgString = "Test a b 🐸"; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "🐸"); +} + +TEST_CASE("Basic - space at the end") { + const auto ArgString = "Test a b 🐸 "; + auto Args = FHU::ParseArgumentsFromString(ArgString); + REQUIRE(Args.size() == 4); + CHECK(Args.at(0) == "Test"); + CHECK(Args.at(1) == "a"); + CHECK(Args.at(2) == "b"); + CHECK(Args.at(3) == "🐸"); +} diff --git a/unittests/APITests/CMakeLists.txt b/unittests/APITests/CMakeLists.txt index 23cf1077d8..1e4abfe2c9 100644 --- a/unittests/APITests/CMakeLists.txt +++ b/unittests/APITests/CMakeLists.txt @@ -1,5 +1,6 @@ set (TESTS Allocator + ArgumentParser InterruptableConditionVariable Filesystem )