-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add scannable concepts * Compile fixes * Enable scannable types for use with program options * Type fix * Access the scan result value, not the expected
- Loading branch information
Showing
14 changed files
with
204 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,5 @@ target_sources(MorpheusApplication | |
FILE_SET HEADERS | ||
FILES | ||
enums.hpp | ||
scannable.hpp | ||
) |
30 changes: 30 additions & 0 deletions
30
libraries/application/src/morpheus/application/po/adapters/scannable.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/conformance/scan.hpp" | ||
#include "morpheus/core/meta/concepts/scannable.hpp" | ||
|
||
#include <boost/any.hpp> | ||
#include <boost/program_options.hpp> | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
namespace boost | ||
{ | ||
|
||
template <class CharType, typename S> | ||
requires morpheus::meta::concepts::Scannable<S, CharType> | ||
void validate(boost::any& v, std::vector<std::basic_string<CharType>> const& values, S*, int) | ||
{ | ||
namespace po = boost::program_options; | ||
po::validators::check_first_occurrence(v); | ||
auto const& s = po::validators::get_single_string(values); | ||
|
||
auto const result = morpheus::scan_ns::scan<S>(s, "{}"); | ||
if (result) | ||
v = result.value().value(); | ||
else | ||
throw po::validation_error(po::validation_error::invalid_option_value); | ||
} | ||
|
||
} // namespace boost |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ add_subdirectory(std) | |
target_sources(MorpheusApplicationTests | ||
PRIVATE | ||
enum.tests.cpp | ||
scannable.tests.cpp | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
libraries/application/tests/po/adapters/scannable.tests.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include "morpheus/application/application.hpp" | ||
#include "morpheus/application/po/adapters/scannable.hpp" | ||
#include "morpheus/logging.hpp" | ||
|
||
#include <catch2/catch_test_macros.hpp> | ||
|
||
#include <array> | ||
#include <compare> | ||
#include <cstdint> | ||
#include <string_view> | ||
#include <tuple> | ||
|
||
struct Coordinates | ||
{ | ||
double x = 0.0; | ||
double y = 0.0; | ||
|
||
auto operator<=>(Coordinates const&) const = default; | ||
}; | ||
|
||
template <> | ||
struct morpheus::scan_ns::scanner<Coordinates> : morpheus::scan_ns::scanner<std::string> | ||
{ | ||
template <typename Context> | ||
auto scan(Coordinates& val, Context& ctx) const -> morpheus::scan_ns::scan_expected<typename Context::iterator> | ||
{ | ||
return morpheus::scan_ns::scan<int, double>(ctx.range(), "[{}, {}]") | ||
.transform( | ||
[&val](auto const& result) | ||
{ | ||
std::tie(val.x, val.y) = result.values(); | ||
return result.begin(); | ||
}); | ||
} | ||
}; | ||
|
||
namespace morpheus::application::po | ||
{ | ||
|
||
struct Location | ||
{ | ||
Coordinates coordinates; | ||
|
||
void addOptions(boost::program_options::options_description& options) | ||
{ | ||
namespace po = boost::program_options; | ||
// clang-format off | ||
options.add_options() | ||
("coordinates", po::value(&coordinates), "The 2-dimensional coordinates of the location."); | ||
// clang-format on | ||
} | ||
}; | ||
|
||
TEST_CASE_METHOD(LoggingFixture, "Test parsing of scannable as options", "[morpheus.application.po.adapters.scannable]") | ||
{ | ||
SECTION("Ensure valid value parse correctly") | ||
{ | ||
auto getCoordinates = [](std::string_view param) | ||
{ | ||
Location location{}; | ||
std::array cliOptions = {"dummyProgram.exe", "--coordinates", param.data()}; | ||
auto const result = parseProgramOptions(static_cast<int>(cliOptions.size()), cliOptions.data(), HelpDocumentation{}, location); | ||
REQUIRE(!result); | ||
return location.coordinates; | ||
}; | ||
|
||
REQUIRE(getCoordinates("[1, 97]") == Coordinates {1.0, 97.0}); | ||
} | ||
SECTION("Ensure invalid value parse correctly") | ||
{ | ||
std::array cliOptions = {"dummyProgram.exe", "--coordinates", "invalid"}; | ||
Location location{}; | ||
auto const result = parseProgramOptions(static_cast<int>(cliOptions.size()), cliOptions.data(), HelpDocumentation{}, location); | ||
REQUIRE(result); | ||
} | ||
} | ||
|
||
} // namespace morpheus::application::po |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ target_sources(MorpheusCore | |
enum.hpp | ||
hashable.hpp | ||
satisfies.hpp | ||
scannable.hpp | ||
string.hpp | ||
trait.hpp | ||
) |
16 changes: 16 additions & 0 deletions
16
libraries/core/src/morpheus/core/meta/concepts/scannable.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/conformance/scan.hpp" | ||
#include "morpheus/core/meta/detail/scannable.hpp" | ||
|
||
#include <type_traits> | ||
|
||
namespace morpheus::meta::concepts | ||
{ | ||
|
||
/// \concept Scannable | ||
/// Verifies a given T is a scannable type. | ||
template <class T, class CharT> | ||
concept Scannable = detail::ScannableWith<std::remove_reference_t<T>, scan_ns::basic_scan_context<CharT>>; | ||
|
||
} // namespace morpheus::meta::concepts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ target_sources(MorpheusCore | |
FILES | ||
aggregate.hpp | ||
any.hpp | ||
scannable.hpp | ||
) |
19 changes: 19 additions & 0 deletions
19
libraries/core/src/morpheus/core/meta/detail/scannable.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/conformance/scan.hpp" | ||
|
||
#include <concepts> | ||
#include <type_traits> | ||
|
||
namespace morpheus::meta::concepts::detail | ||
{ | ||
|
||
template <class T, class Context, class Scanner = typename Context::template scanner_type<std::remove_const_t<T>>> | ||
concept ScannableWith = | ||
std::semiregular<Scanner> && | ||
requires(Scanner& s, const Scanner& cs, T& t, Context& ctx, scan_ns::basic_scan_parse_context<typename Context::char_type> pctx) { | ||
{ s.parse(pctx) } -> std::same_as<scan_ns::scan_expected<typename decltype(pctx)::iterator>>; | ||
{ cs.scan(t, ctx) } -> std::same_as<scan_ns::scan_expected<typename Context::iterator>>; | ||
}; | ||
|
||
} // namespace morpheus::meta::concepts::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,5 @@ target_sources(MorpheusCoreTests | |
satisfies.tests.cpp | ||
trait.tests.cpp | ||
) | ||
|
||
add_subdirectory(concepts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
target_sources(MorpheusCoreTests | ||
PUBLIC | ||
scannable.tests.cpp | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include "morpheus/core/conformance/scan.hpp" | ||
#include "morpheus/core/meta/concepts/scannable.hpp" | ||
|
||
#include <catch2/catch_all.hpp> | ||
|
||
#include <tuple> | ||
|
||
struct ScannableType | ||
{ | ||
int first = 0; | ||
double second = 0.0; | ||
}; | ||
|
||
template <> | ||
struct morpheus::scan_ns::scanner<ScannableType> : morpheus::scan_ns::scanner<std::string> | ||
{ | ||
template <typename Context> | ||
auto scan(ScannableType& val, Context& ctx) const -> morpheus::scan_ns::scan_expected<typename Context::iterator> | ||
{ | ||
return morpheus::scan_ns::scan<int, double>(ctx.range(), "[{}, {}]") | ||
.transform( | ||
[&val](auto const& result) | ||
{ | ||
std::tie(val.first, val.second) = result.values(); | ||
return result.begin(); | ||
}); | ||
} | ||
}; | ||
|
||
|
||
namespace morpheus::meta::concepts | ||
{ | ||
|
||
class UnscannableType; | ||
|
||
TEST_CASE("Meta concept scannable_with verifies a given type customises scan_ns::scanner", "[morpheus.meta.concepts.scannable_with]") | ||
{ | ||
STATIC_REQUIRE(!detail::ScannableWith<UnscannableType, scan_ns::basic_scan_context<char>>); | ||
STATIC_REQUIRE(detail::ScannableWith<ScannableType, scan_ns::basic_scan_context<char>>); | ||
} | ||
|
||
TEST_CASE("Meta concept scannable_with verifies a given type customises scan_ns::scanner", "[morpheus.meta.concepts.scannable]") | ||
{ | ||
STATIC_REQUIRE(!Scannable<UnscannableType, char>); | ||
STATIC_REQUIRE(Scannable<ScannableType, char>); | ||
} | ||
|
||
} // namespace morpheus::meta::concepts |