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)