Contribute a failing to compile part of a CLI support implementation.

This commit is contained in:
p620
2021-03-31 14:02:38 +03:00
parent 53d6f8a83d
commit 6a3b85b9b1
7 changed files with 316 additions and 4 deletions

View File

@@ -244,7 +244,7 @@ COLLECT_FILES(false imguipiemenu_sources src/external/imguipiemenu ".c;.cpp;")
set ( util_sources
src/util/exception_to_string.cpp
)
COLLECT_FILES(false noggit_root_headers src/noggit ".h;.hpp")
COLLECT_FILES(false noggit_root_headers src/noggit ".h;.hpp;.inl")
COLLECT_FILES(true noggit_ui_headers src/noggit/ui ".h;.hpp")
COLLECT_FILES(false math_headers src/math ".h;.hpp")
COLLECT_FILES(false opengl_headers src/opengl ".h;.hpp")

View File

@@ -33,7 +33,7 @@ file (READ "${_noggit_revision_template_file}" _template_blob)
file (READ "${CMAKE_CURRENT_LIST_FILE}" _self_blob)
string (SHA256 _state_hash "${_dirty_marker}${_revision}${_template_blob}${_self_blob}")
if (EXISTS ${_noggit_revision_output_file})
if (EXISTS ${_noggit_revision_state_file})
file (READ "${_noggit_revision_state_file}" _old_state_hash)
if (_state_hash STREQUAL _old_state_hash)
return()

157
src/noggit/Cli.cpp Normal file
View File

@@ -0,0 +1,157 @@
#include <iostream>
#include <optional>
#include "Cli.inl"
using namespace noggit;
template < typename Ty >
concept CharOrCStr = std::is_same_v<Ty, char>
|| std::is_same_v<Ty, char const*>;
template < CharOrCStr Str >
struct ControllerException
{
explicit constexpr
ControllerException ( Str arg )
: arg{arg}
{ }
Str arg;
};
Cli::Cli
(
std::size_t argC,
char const* const* argV
)
: _args(_countArgs(argC, argV))
{
try
{
std::size_t counter{};
auto const findHandlerOrThrow{
[ this ]
< CharOrCStr Str >
( Str str )
-> ControllerHandler
{
auto const result{CliAssister::_findControllerInfo(str, _argMapping)};
return result ? throw ControllerException{str} : result->second;
}};
for(std::size_t i{}; i < argC; ++i)
{
if(argV[i][0] == '-')
{
if(argV[i][1] == '\0')
throw "-";
if(argV[i][1] == '-')
{
if(argV[i][2] == '\0')
throw "--";
else
{
_args[i] = findHandlerOrThrow(&argV[i][2]);
++counter;
continue;
}
for(std::size_t j{1}; argV[i][j]; ++j, ++counter)
_args[counter] = findHandlerOrThrow(argV[i][j]);
}
}
_args[counter] = (argV[i]);
++counter;
}
}
catch ( ControllerException<char> e )
{
std::cerr << "\nE: Unknown control flag: '" << e.arg << '\'';
throw;
}
catch ( ControllerException<char const*> e )
{
std::cerr << "\nE: Unknown control statement: '" << e.arg << '\'';
throw;
}
catch ( char const* str )
{
std::cerr << "\nE: Unknown parameter: '" << str << '\'';
throw;
}
catch ( ... )
{
std::exit(EXIT_FAILURE);
}
}
struct ControllerNotSatisfied
{
std::string_view name;
};
auto Cli::exec ( )
-> void
{
StateMachine state{};
try
{
for(auto arg{_args.cbegin()}; arg != _args.cend(); )
{
if(ControllerHandler const* handler{std::get_if<ControllerHandler>(&*arg)}
; handler)
{
if(state.curHandler)
throw ControllerNotSatisfied{*CliAssister::_findControllerInfo
(state.curHandler, _nameMapping)};
(*handler)({}) || (state.curHandler = *handler);
++arg;
continue;
}
}
}
catch ( ControllerNotSatisfied e )
{
std::cerr << "\nE: Controller '" << e.name << "' expected an argument.";
throw;
}
catch ( ... )
{
std::exit(EXIT_FAILURE);
}
}
Cli::StateMachine::StateMachine ( )
: curHandler{}, flags{Flags::doContinueExecution}
{ }
constexpr
auto Cli::_countArgs
(
std::size_t argC,
char const* const* argV
)
-> std::size_t
{
std::size_t result{};
for(std::size_t i{}; i < argC; ++i)
{
if(argV[i][0] == '-' && argV[i][1] != '-' && argV[i][1] != '\0')
{
for(std::size_t j{1}; argV[i][j]; ++j, ++result);
continue;
}
++result;
}
return result;
}

111
src/noggit/Cli.hpp Normal file
View File

@@ -0,0 +1,111 @@
#ifndef NOGGIT_SRC_NOGGIT_CLI_HPP
#define NOGGIT_SRC_NOGGIT_CLI_HPP
#include <array>
#include <initializer_list>
#include <optional>
#include <string_view>
#include <type_traits>
#include <variant>
#include <vector>
namespace noggit
{
using namespace std::literals;
class Cli
{
public:
explicit
Cli
(
std::size_t argC,
char const* const* argV
);
auto exec ( )
-> void;
private:
static constexpr
auto _countArgs
(
std::size_t argC,
char const* const* argV
)
-> std::size_t;
typedef std::vector<std::variant<std::size_t, std::string>> ArgContainer;
struct ParamInfo
{
typedef auto(HandlerSignature)
(
ArgContainer::const_iterator begin,
ArgContainer::const_iterator end
)
-> bool;
explicit constexpr
ParamInfo
(
std::initializer_list<std::string_view> aliases,
std::string_view name,
HandlerSignature* handler
);
std::vector<std::string_view> aliases;
std::string_view name;
HandlerSignature* handler;
};
struct StateMachine
{
struct Flags
{
enum : std::size_t
{
IsControllerSatisfied = 0x1,
doContinueExecution = 0x2
};
};
StateMachine ( );
std::size_t curParamIdx;
std::size_t flags;
};
static constexpr
std::array paramInfos
{
ParamInfo{{"r", "recovery"}, "Recovery", nullptr}
};
ArgContainer _args;
};
template < typename Ty >
concept ControllerInfo = std::is_same_v<Ty, std::string_view>
|| std::is_same_v<Ty, Cli::ControllerHandler>;
class CliAssister
{
private:
friend class Cli;
template
<
ControllerInfo Key,
ControllerInfo Value,
std::size_t n
>
requires ( !std::is_same_v<Key, Value> )
static constexpr
auto _findControllerInfo
(
Key key,
std::array<std::pair<Key, Value>, n> const& info
)
-> std::optional<Value>;
};
}
#endif //NOGGIT_SRC_NOGGIT_CLI_HPP

37
src/noggit/Cli.inl Normal file
View File

@@ -0,0 +1,37 @@
#ifndef NOGGIT_SRC_NOGGIT_CLI_INL
#define NOGGIT_SRC_NOGGIT_CLI_INL
#include <algorithm>
#include "Cli.hpp"
namespace noggit
{
template
<
ControllerInfo Key,
ControllerInfo Value,
std::size_t n
>
requires ( !std::is_same_v<Key, Value> )
constexpr
auto CliAssister::_findControllerInfo
(
Key key,
std::array<std::pair<Key, Value>, n> const& info
)
-> std::optional<Value>
{
auto const result{std::find_if(info.cbegin(), info.cend(),
[ key ]
( std::pair<Key, Value> const& pair )
-> bool
{
return pair.first == key;
})};
return result == info.cend() ? std::nullopt
: std::optional{result->second};
}
}
#endif //NOGGIT_SRC_NOGGIT_CLI_INL

View File

@@ -1,4 +1,4 @@
#include "MapHeaders.h"
/*#include "MapHeaders.h"
#include "MPQ.h"
#include "MakeshiftMt.hpp"
@@ -145,3 +145,4 @@ MakeshiftMt::~MakeshiftMt( void )
{
}
*/

View File

@@ -41,7 +41,7 @@
#include <QStyleFactory>
#include "revision.h"
#include "Cli.hpp"
class Noggit
{
@@ -341,6 +341,12 @@ namespace
int main(int argc, char *argv[])
{
/* command-line mode */
if(argc > 1)
{
noggit::Cli{static_cast<std::size_t>(argc), argv}.exec();
}
noggit::RegisterErrorHandlers();
std::set_terminate (noggit_terminate_handler);