From 5d268488b2861ce73db233d71bdb527f89001a4e Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 25 Jan 2025 12:57:24 +0100 Subject: Add PointerList class for working with, and propagating, argc/argv --- src/pointerlist.cc | 28 +++++++++++++++ src/pointerlist.h | 26 ++++++++++++++ test/ctor.cc | 17 +++++++++ test/pointerlist_test.cc | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 src/pointerlist.cc create mode 100644 src/pointerlist.h create mode 100644 test/pointerlist_test.cc diff --git a/src/pointerlist.cc b/src/pointerlist.cc new file mode 100644 index 0000000..e642075 --- /dev/null +++ b/src/pointerlist.cc @@ -0,0 +1,28 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#include "pointerlist.h" + +PointerList::PointerList(int argc, const char* argv[]) +{ + for(int i = 0; i < argc; ++i) + { + push_back(argv[i]); + } +} + +std::pair PointerList::get() +{ + argptrs.clear(); + for(const auto& arg : *this) + { + argptrs.push_back(arg.data()); + } + + if(argptrs.size() == 0) + { + return {0, nullptr}; + } + + return {argptrs.size(), argptrs.data()}; +} diff --git a/src/pointerlist.h b/src/pointerlist.h new file mode 100644 index 0000000..7c51ca6 --- /dev/null +++ b/src/pointerlist.h @@ -0,0 +1,26 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. + +#include +#include +#include +#include + +// Maintains an (owning) list of string args and converts them to argc/argv +// compatible arguments on request. +// The returned pointers are guaranteed to be valid as long as the PointerList +// object lifetime is not exceeded. +class PointerList : + public std::deque +{ +public: + PointerList() = default; + PointerList(int argc, const char* argv[]); + + //! Returns argc/argv pair from the current list of args + std::pair get(); + +private: + std::vector argptrs; +}; diff --git a/test/ctor.cc b/test/ctor.cc index d69b1cf..acb232f 100644 --- a/test/ctor.cc +++ b/test/ctor.cc @@ -9,6 +9,23 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings) { return { + { + .type = ctor::target_type::unit_test, + .system = ctor::output_system::build, + .target = "pointerlist_test", + .sources = { + "pointerlist_test.cc", + "testmain.cc", + "../src/pointerlist.cc", + }, + .flags = { + .cxxflags = { + "-std=c++20", "-O3", "-Wall", "-Werror", + "-I../src", "-Iuunit", + "-DOUTPUT=\"pointerlist\"", + }, + }, + }, { .type = ctor::target_type::unit_test, .system = ctor::output_system::build, diff --git a/test/pointerlist_test.cc b/test/pointerlist_test.cc new file mode 100644 index 0000000..329e319 --- /dev/null +++ b/test/pointerlist_test.cc @@ -0,0 +1,90 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#include + +#include "pointerlist.h" + +class PointerListTest + : public uUnit +{ +public: + PointerListTest() + { + uTEST(PointerListTest::test_zom_push); + uTEST(PointerListTest::test_zom_from_args); + } + + void test_zom_push() + { + using namespace std::string_literals; + + { // Zero + PointerList args; + uASSERT_EQUAL(0u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(0, argc); + uASSERT_EQUAL(nullptr, argv); + } + + { // One + PointerList args; + args.push_back("hello"); + uASSERT_EQUAL(1u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(1, argc); + uASSERT_EQUAL("hello"s, std::string(argv[0])); + } + + { // Many + PointerList args; + args.push_back("hello"); + args.push_back("dear"); + args.push_back("world"); + uASSERT_EQUAL(3u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(3, argc); + uASSERT_EQUAL("hello"s, std::string(argv[0])); + uASSERT_EQUAL("dear"s, std::string(argv[1])); + uASSERT_EQUAL("world"s, std::string(argv[2])); + } + } + + void test_zom_from_args() + { + using namespace std::string_literals; + + { // Zero + PointerList args(0, nullptr); + uASSERT_EQUAL(0u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(0, argc); + uASSERT_EQUAL(nullptr, argv); + } + + { // One + int _argc{1}; + const char* _argv[] = { "hello" }; + PointerList args(_argc, _argv); + uASSERT_EQUAL(1u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(1, argc); + uASSERT_EQUAL("hello"s, std::string(argv[0])); + } + + { // Many + int _argc{3}; + const char* _argv[] = { "hello", "dear", "world" }; + PointerList args(_argc, _argv); + uASSERT_EQUAL(3u, args.size()); + auto [argc, argv] = args.get(); + uASSERT_EQUAL(3, argc); + uASSERT_EQUAL("hello"s, std::string(argv[0])); + uASSERT_EQUAL("dear"s, std::string(argv[1])); + uASSERT_EQUAL("world"s, std::string(argv[2])); + } + } +}; + +// Registers the fixture into the 'registry' +static PointerListTest test; -- cgit v1.2.3