Attention une mise à jour du service Gitlab va être effectuée le mardi 18 janvier (et non lundi 17 comme annoncé précédemment) entre 18h00 et 18h30. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes.

Commit 59c07d20 authored by ESTERIE Pierre's avatar ESTERIE Pierre
Browse files

First tools version

parent 26465db2
#ifndef CPP_TOOLS_CL_PARSER_EXCEPTIONS_HPP
#define CPP_TOOLS_CL_PARSER_EXCEPTIONS_HPP
#include <stdexcept>
namespace cpptools::cl_parser
{
struct parameter_conflict : std::logic_error
{
using std::logic_error::logic_error;
};
struct invalid_parameter : std::logic_error
{
using std::logic_error::logic_error;
};
struct unknown_parameter : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct missing_required_parameter : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct partial_parse : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct exclusive_parameters : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct parse_error : std::runtime_error
{
using std::runtime_error::runtime_error;
bool missing_required = false;
bool unknown_parameter = false;
};
} // namespace cpptools::cl_parser
#endif
This diff is collapsed.
#ifndef CPP_TOOLS_CL_PARSER_TCLI_SFINAE_HPP
#define CPP_TOOLS_CL_PARSER_TCLI_SFINAE_HPP
#include <istream>
#include <string>
#include <type_traits>
#include <vector>
namespace cpptools::cl_parser::meta
{
/**
* \brief Useful type alias for metaprogramming
*/
template<class...>
using void_t = void;
/**
* \brief Checks that all boolean values are true
*/
template<bool B, bool... Bs>
struct all_true
{
/** \internal */
template<bool... Cs>
struct list
{
};
enum
{
value = std::is_same<list<B, Bs...>, list<Bs..., B>>::value
};
};
/**
* \brief Alias to ease use of std::enable_if
*
* \tparam T Trait to check, value is extracted
* \tparam U Type given to std::enable_if
*/
template<class T, class U = char>
using use_if = typename std::enable_if<T::value, U>::type;
/**
* \copydoc use_if
*/
template<class T, class U = char>
using not_use_if = typename std::enable_if<!T::value, U>::type;
/**
* \brief Checks for the compile time static value T::stackable
*
* \tparam T Type to inspect
*/
template<class T>
struct is_stackable
{
template<class U, int = U::stackable>
static constexpr bool check(U*)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
/**
* \brief Checks for the compile time static value T::tcli_parser
*
* \tparam T Type to inspect
*/
template<class T>
struct is_parser
{
template<class U, int = U::tcli_parser>
static constexpr bool check(U*)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
/**
* \brief Checks for the compile time static value T::flagged
*
* \tparam T Type to inspect
*/
template<class T>
struct is_flagged
{
template<class U, int = U::flagged>
static constexpr bool check(U*)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
/**
* \brief Checks for the compile time static value T::required
*
* \tparam T Type to inspect
*/
template<class T>
struct is_required
{
template<class U, int = U::required>
static constexpr bool check(U*)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
namespace details
{
/**
* \copydoc is_istream_settable
*/
template<class T>
struct has_formated_input_impl
{
template<class U>
constexpr static auto check(U* u, std::istream* is = nullptr) -> decltype((*is >> *u), void(), true)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
} // namespace details
/**
* \brief Checks whether T has a formatted input operator
*
* \tparam T Type to inspect
*/
template<class T>
struct is_istream_settable : std::integral_constant<bool, details::has_formated_input_impl<T>::value>
{
};
/**
* \brief Checks whether T has a `type` type alias
*
* \tparam T Type to inspect
*/
template<class T>
struct has_type
{
template<typename U>
static constexpr bool check(U*, typename U::type* = nullptr)
{
return true;
}
static constexpr bool check(...) { return false; }
enum
{
value = check((T*)0)
};
};
/**
* \brief Checks whether T has a `parse` static method
*
* \tparam T Type to inspect
* \tparam Func Function signature
*
* Example:
*
* ~~~{.cpp}
* struct S {
* static int parse(int, char**);
* };
*
* std::cout << has_parse<S, int(int, char**)>::value; // true
* ~~~
*/
template<class T, class Func>
struct has_parse;
/**
* \copydoc inria::tcli::meta::has_parse
*/
template<class T, class Ret, class... Args>
struct has_parse<T, Ret(Args...)>
{
template<class, class = void>
struct check : std::false_type
{
};
template<class U>
struct check<U, void_t<decltype(U::parse(std::declval<Args>()...))>> : std::true_type
{
};
enum
{
value = check<T>::value
};
};
/**
* \brief Checks whether T has a `visit` static method
*
* \tparam T Type to inspect
* \tparam Func Function signature
*
* Example:
*
* ~~~{.cpp}
* struct S {
* static int visit(int, char**);
* };
*
* std::cout << has_visit<S, int(int, char**)>::value; // true
* ~~~
*/
template<class T, class Func>
struct has_visit;
/**
* \copydoc has_visit
*/
template<class T, class Ret, class... Args>
struct has_visit<T, Ret(Args...)>
{
template<class, class = void>
struct check : std::false_type
{
};
template<class U>
struct check<U, void_t<decltype(std::declval<U>().visit(std::declval<Args>()...))>> : std::true_type
{
};
enum
{
value = check<T>::value
};
};
/**
* \brief Checks attribute `T::def` existence
*
* \tparam T Type to inspect
*/
template<class T>
struct has_default
{
template<class U, decltype(std::declval<U>().def)* = nullptr>
static constexpr std::true_type check(U*)
{
return {};
}
static constexpr std::false_type check(...) { return {}; }
enum
{
value = decltype(check((T*)nullptr))::value
};
};
/**
* \brief Metaprogramming type list
*
* \tparam Elts Elements pack
*/
template<class... Elts>
struct list
{
/// List element count
static constexpr int size = sizeof...(Elts);
/**
* \brief Find first occurence of an element in the list
*
* \tparam U Element to find
* \tparam Vs Remaining elements in the list
*/
template<class U, class... Vs>
struct find
{
/// Index of the element, default value is past the list end
static constexpr int value = size + 1;
};
/**
* \brief Find element in the list, success specialisation
*
* \copydetails find
*/
template<class U, class... Vs>
struct find<U, U, Vs...>
{
static constexpr int value = size - sizeof...(Vs) - 1;
};
/**
* \brief Find element in the list, recursion specialisation
*
* \copydetails find
* \tparam V First element, different from `U`
*/
template<class U, class V, class... Vs>
struct find<U, V, Vs...>
{
static constexpr int value = find<U, Vs...>::value;
};
/**
* \brief Get element index in the list
*
* \tparam T Element to find
*/
template<class T>
struct index
{
/// Index of element, `list<Elts>::size+1` if the element does not exist
static constexpr int value = find<T, Elts...>::value;
};
/**
* \brief Check for type in list
*
* \tparam T Type to look for in the list
*/
template<class T>
struct exists
{
// Intel compiler requires the parentheses
static constexpr int value = (find<T, Elts...>::value) < size;
};
};
} // namespace cpptools::cl_parser::meta
#endif /* TCLI_SFINAE_HPP */
#ifndef CPP_TOOLS_CL_PARSER_PARAMETER_MODEL_HPP
#define CPP_TOOLS_CL_PARSER_PARAMETER_MODEL_HPP
#include <string>
#include <vector>
namespace cpptools::cl_parser
{
/**
* \brief Parameter descriptor model
*
* A parameter descriptor is a class that exposes the following public
* interface.
*/
struct parameter_descriptor_model
{
/// argument type
using type = int;
/// flags
std::vector<std::string> flags = {"t"};
/// optional, argument description
const char* description;
/// optional, argument default value
type def;
enum
{
stackable, ///< optional, the argument may be specified several time
///< and the value are stacked
required, ///< optional, the argument must be specified once
hidden, ///< optional, the argument must be hidden in help message
};
/// optional, called after parameter parsing
template<class Parser>
void visit(Parser& p, std::vector<std::string>& args, typename std::vector<std::string>::iterator& current_arg);
/// optional, customize parameter parsing
bool parse(std::vector<std::string>& args, typename std::vector<std::string>::iterator& current_arg,
type& data);
};
/**
* \brief Basic parameter descriptor
*
* \tparam T Parameter underlying type.
* \tparam Tag Optional tag class use to differenciate two parameters with
* the same type.
*/
template<class T, class Tag = void>
struct parameter_descriptor
{
using type = T;
std::vector<std::string> flags;
parameter_descriptor() = default;
parameter_descriptor(const parameter_descriptor&) = default;
parameter_descriptor(parameter_descriptor&&) = default;
parameter_descriptor& operator=(const parameter_descriptor&) = default;
parameter_descriptor& operator=(parameter_descriptor&&) = default;
parameter_descriptor(const std::vector<std::string>& new_flags)
: flags(new_flags)
{
}
};
/**
* \brief Basic flag structure, inherit from it to quickly create a flag
*
* Structure meant to be inherited from to create a flag parameter. Flags do
* not consume the following argument on the CLI.
*
* Creates a `bool` typed parameter which value defaults to `false`.
*/
struct flag_descriptor
{
using type = bool;
enum
{
flagged
};
};
} // namespace cpptools::cl_parser
#endif /* TCLI_PARAMETER_MODEL_HPP */
#ifndef CPP_TOOLS_CL_PARSER_UTILS_HPP
#define CPP_TOOLS_CL_PARSER_UTILS_HPP
#include <tuple>
#include <utility>
namespace cpptools::cl_parser::utils
{
/**
* \brief Collective operation result
*
* Collective operations on a tuple are made by calling a functor with a
* state over all elements. If the functor defines a `collective_result()`
* method, get its returned value.
*
* \tparam F functor type, argument-deduced
*
* \param functor Callable object to get a result from
*
* \return `functor.collective_result()`
*/
template<class F>
auto get_collective_result(F&& functor) -> decltype(functor.collective_result())
{
return functor.collective_result();
}
/**
* \brief Collective operation result fallback
*
* If not `collective_result()` method is defined by the arguments, this
* overload is called. This is a no-op.
*/
inline void get_collective_result(...) {}
/**
* \brief for_each_in_tuple implementation
*/
template<class Tuple, class F, class... Args, std::size_t... Is>
auto for_each_in_tuple_impl(std::index_sequence<Is...>, Tuple&& t, F&& func, Args&&... args)
-> decltype(get_collective_result(func))
{
auto l = {0, (std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(t)), std::forward<Args>(args)...), 0)...};
(void)l;
return get_collective_result(func);
}
/**
* \brief Calls a functor over the elements of a tuple
*
* \tparam Tuple Tuple type
* \tparam F Functor type
* \tparam Args Additional arguments to pass to the functor
*
* \param t Tuple to iterate over
* \param func Functor to call
* \param args Additional arguments
*
* \return `f.collective_result()` if it exists, `void` otherwise.
*
* Example (C++14):
* ```{cpp}
* std::tuple<int, double, char> t(1, 3.14, 'c');
* // The following
* for_each_in_tuple(t, [](auto a, char delim){std::cout << a << delim;}, ':')
* // is equivalent to
* std::cout << std::get<0>(t) << ':';
* std::cout << std::get<1>(t) << ':';
* std::cout << std::get<2>(t) << ':';
* ```
*
* Output:
* ```
* 1:3.14:c
* ```
*/
template<class Tuple, class F, class... Args>
auto for_each_in_tuple(Tuple&& t, F&& func, Args&&... args)
#ifndef __INTEL_COMPILER
-> decltype(
for_each_in_tuple_impl(std::make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>(),
std::forward<Tuple>(t), std::forward<F>(func), std::forward<Args>(args)...))
#endif
{
return for_each_in_tuple_impl(
std::make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>(), std::forward<Tuple>(t),
std::forward<F>(func), std::forward<Args>(args)...);
}
} // namespace cpptools::cl_parser::utils
#endif /* TCLI_UTILS_HPP */
This diff is collapsed.
set(MODULE_NAME cl-parser)