doc: update documentation
This commit is contained in:
parent
656495f22e
commit
598aae69ae
|
@ -48,7 +48,7 @@ if (test.m_StringArgument.IsCaptured())
|
||||||
auto val = test.m_StringArgument.Get();
|
auto val = test.m_StringArgument.Get();
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
These code can resolve following command line
|
These code can resolve following command line:
|
||||||
|
|
||||||
\code{.sh}
|
\code{.sh}
|
||||||
exec -i 114514 -f 2.0 --string fuck -b --clamped-float 0.5
|
exec -i 114514 -f 2.0 --string fuck -b --clamped-float 0.5
|
||||||
|
@ -62,38 +62,82 @@ For convenience, we define following terms used in this article.
|
||||||
|
|
||||||
\section arg_parser__argument Argument
|
\section arg_parser__argument Argument
|
||||||
|
|
||||||
|
Argument is the leaf of argument parser.
|
||||||
|
It has the same position as setting in universal config manager.
|
||||||
|
|
||||||
\subsection arg_parser__argument__presets Argument Presets
|
\subsection arg_parser__argument__presets Argument Presets
|
||||||
|
|
||||||
\subsubsection arg_parser__argument__presets__number Number Argument
|
Like setting in universal config manager,
|
||||||
|
we also provide various common used argument presets.
|
||||||
|
Current'y we support following argument presets:
|
||||||
|
|
||||||
\subsubsection arg_parser__argument__presets__string String Argument
|
\li NumberArgument: The argument storing arithmetic type (except \c bool) inside. Such as <TT>-i 114514</TT> in example.
|
||||||
|
\li StringArgument: The argument storing string inside. Such as <TT>--string fuck</TT> in example.
|
||||||
|
\li SwitchArgument: The argument storing nothing. It is just a simple switch. Such as <TT>-b</TT> in example.
|
||||||
|
|
||||||
\subsubsection arg_parser__argument__presets__switch Switch Argument
|
When constructing these argument,
|
||||||
|
you need provide one from long name or short name, or both of them.
|
||||||
|
Short name is the argument starting with dash and long name starts with double dash.
|
||||||
|
You don't need add dash or double dash prefix when providing these names.
|
||||||
|
Please note only ASCII characters, which can be displayed on screen, can be used in these names.
|
||||||
|
|
||||||
Switch argument must be optional argument.
|
Optionally, you can provide description when constructing,
|
||||||
|
which will tell user how this switch does and more infomation about this switch.
|
||||||
|
And, you can add an example to tell user which value is valid.
|
||||||
|
|
||||||
|
Next, you can specify an argument to be optional.
|
||||||
|
Optional argument can be absent in command line.
|
||||||
|
Oppositely, non-optional argument must be presented in command line,
|
||||||
|
otherwise parser will return false to indicate an error.
|
||||||
|
For checking whether an optional argument is specified,
|
||||||
|
please call AbstractArgument::IsCaptured().
|
||||||
|
|
||||||
|
Last, you can optionally assign a constraint to it,
|
||||||
|
to help argument limit its value.
|
||||||
|
|
||||||
|
However SwitchArgument must be optional argument.
|
||||||
Because it is true if user specify it explicit it,
|
Because it is true if user specify it explicit it,
|
||||||
and will be false if user do not give this flag.
|
and will be false if user do not give this flag.
|
||||||
|
SwitchArgument doesn't have constraint features,
|
||||||
Switch argument also doesn't contain any value.
|
because it doesn't store any value inside.
|
||||||
Because it is just a switch.
|
Thus no need to limit this.
|
||||||
It can not hold any value.
|
|
||||||
|
|
||||||
\subsection arg_parser__argument__custom Custom Argument
|
\subsection arg_parser__argument__custom Custom Argument
|
||||||
|
|
||||||
|
In most cases, the combination use of argument presets and constraints is enough.
|
||||||
|
However, if you still are urge to create your personal argument,
|
||||||
|
please inherit AbstractArgument and implement essential class functions.
|
||||||
|
For the class functions you need to implement,
|
||||||
|
please refer to our argument presets.
|
||||||
|
|
||||||
\section arg_parser__argument_list Argument List
|
\section arg_parser__argument_list Argument List
|
||||||
|
|
||||||
|
Argument list is a struct used by parser for parsing.
|
||||||
|
It is a higher wrapper of a simple list containing argument items.
|
||||||
|
We provide 2 ways to get argument list.
|
||||||
|
|
||||||
|
\li ArgumentList::CreateFromStd: Create argument list from standard C main function parameters.
|
||||||
|
\li ArgumentList::CreateFromWin32: Create argument list from Win32 functions in Windows.
|
||||||
|
You should use this function in Windows instead of ArgumentList::CreateFromStd.
|
||||||
|
Because the command line passed in standard C main function has encoding issue in Windows.
|
||||||
|
Use this function you will fetch correct argument list especially command including non-ASCII characters.
|
||||||
|
|
||||||
|
Please note the first argument in given command line will be stripped.
|
||||||
|
Because in most cases it point to the executable self,
|
||||||
|
and should not be seen as the part of argument list.
|
||||||
|
|
||||||
\section arg_parser__option_context Option Context
|
\section arg_parser__option_context Option Context
|
||||||
|
|
||||||
Please note any unknow argument will let the parser return false.
|
Please note any unknow argument will let the parser return false.
|
||||||
This is different with other argument parsers.
|
This is different with other argument parsers.
|
||||||
In other common argument parsers,
|
In other common argument parsers,
|
||||||
they will collect all unknow argument ad positional argument,
|
they will collect all unknow argument as positional argument,
|
||||||
or just simply ignore them.
|
or just simply ignore them.
|
||||||
|
|
||||||
OptionContext also will not add \c -h or \c --help switch automatically.
|
OptionContext also will not add \c -h or \c --help switch automatically.
|
||||||
This is also differnent with other parsers.
|
This is also differnent with other parsers.
|
||||||
You should manually add it.
|
You should manually add it.
|
||||||
However, OptionContext provide a universal help print function.
|
However, OptionContext provide a universal help print function, OptionContext::Help.
|
||||||
You can directly call it to output help text if you needed (fail to parse or user order help).
|
You can directly call it to output help text if you needed (fail to parse or user order help).
|
||||||
|
|
||||||
\section arg_parser__limitation Limitation
|
\section arg_parser__limitation Limitation
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace YYCC::ArgParser {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArgumentList::IsParameter(yycc_u8string* val) const {
|
bool ArgumentList::IsValue(yycc_u8string* val) const {
|
||||||
bool is_value = !IsSwitch();
|
bool is_value = !IsSwitch();
|
||||||
if (is_value && val != nullptr)
|
if (is_value && val != nullptr)
|
||||||
*val = *m_ArgumentsIterator;
|
*val = *m_ArgumentsIterator;
|
||||||
|
|
|
@ -9,35 +9,144 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Universal argument parser.
|
||||||
|
* @details
|
||||||
|
* For how to use this namespace, please see \ref arg_parser.
|
||||||
|
*/
|
||||||
namespace YYCC::ArgParser {
|
namespace YYCC::ArgParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The advanced wrapper of the list containing command line arguments.
|
||||||
|
* @details
|
||||||
|
* This class is used by OptionContext and argument class internally for convenience.
|
||||||
|
* It should not be constrcuted directly.
|
||||||
|
* Programmer should choose proper static creation function to create instance of this class.
|
||||||
|
*/
|
||||||
class ArgumentList {
|
class ArgumentList {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create argument list from the parameters of standard C main function.
|
||||||
|
* @param[in] argc The argument count passed to standard C main function.
|
||||||
|
* @param[in] argv The argument value passed to standard C main function.
|
||||||
|
* @return Extracted argument list instance.
|
||||||
|
* @remarks
|
||||||
|
* First item in command line will be stripped,
|
||||||
|
* because in most cases it points to executable self
|
||||||
|
* and should not be seen as a part of arguments.
|
||||||
|
*/
|
||||||
static ArgumentList CreateFromStd(int argc, char* argv[]);
|
static ArgumentList CreateFromStd(int argc, char* argv[]);
|
||||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||||
|
/**
|
||||||
|
* @brief Create argument list from Win32 function.
|
||||||
|
* @details
|
||||||
|
* @return Extracted argument list instance.
|
||||||
|
* @remarks
|
||||||
|
* First item in command line will be stripped,
|
||||||
|
* because in most cases it points to executable self
|
||||||
|
* and should not be seen as a part of arguments.
|
||||||
|
* \par
|
||||||
|
* Programmer should use this function instead of CreateFromStd(),
|
||||||
|
* because that function involve encoding issue on Windows, especially command line including non-ASCII chars.
|
||||||
|
* Only this function guaranteen that return correct argument list on Windows.
|
||||||
|
*/
|
||||||
static ArgumentList CreateFromWin32();
|
static ArgumentList CreateFromWin32();
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Constructor of ArgumentList used internally.
|
||||||
|
* @param[in] arguments
|
||||||
|
* Underlying argument list.
|
||||||
|
* This argument list should remove first executable name before passing it to there.
|
||||||
|
*/
|
||||||
ArgumentList(std::vector<yycc_u8string>&& arguments);
|
ArgumentList(std::vector<yycc_u8string>&& arguments);
|
||||||
public:
|
public:
|
||||||
|
/// @brief Default copy constructor
|
||||||
ArgumentList(const ArgumentList&) = default;
|
ArgumentList(const ArgumentList&) = default;
|
||||||
|
/// @brief Default copy assigner
|
||||||
ArgumentList& operator=(const ArgumentList&) = default;
|
ArgumentList& operator=(const ArgumentList&) = default;
|
||||||
|
/// @brief Default move constructor
|
||||||
ArgumentList(ArgumentList&&) = default;
|
ArgumentList(ArgumentList&&) = default;
|
||||||
|
/// @brief Default move assigner
|
||||||
ArgumentList& operator=(ArgumentList&&) = default;
|
ArgumentList& operator=(ArgumentList&&) = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Move to previous argument.
|
||||||
|
* @exception std::runtime_error Try moving at the head of argument list.
|
||||||
|
*/
|
||||||
void Prev();
|
void Prev();
|
||||||
|
/**
|
||||||
|
* @brief Move to next argument.
|
||||||
|
* @exception std::runtime_error Try moving at the tail of argument list.
|
||||||
|
*/
|
||||||
void Next();
|
void Next();
|
||||||
|
/**
|
||||||
|
* @brief Get the string of current argument.
|
||||||
|
* @exception std::runtime_error Try fetching data at the tail of argument list.
|
||||||
|
* @return The constant reference to the string of current argument.
|
||||||
|
*/
|
||||||
const yycc_u8string& Argument() const;
|
const yycc_u8string& Argument() const;
|
||||||
|
/**
|
||||||
|
* @brief Check whether current argument is a option / switch.
|
||||||
|
* @param[out] is_long_name
|
||||||
|
* It will be set true if this argument is long name, otherwise short name.
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @param[out] long_name
|
||||||
|
* The container holding matched long name if it is (double dash stripped).
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @param[out] short_name
|
||||||
|
* The variable holding matched short name if it is (dash stripped).
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @exception std::runtime_error Try fetching data at the tail of argument list.
|
||||||
|
* @return
|
||||||
|
* True if it is, otherwise false.
|
||||||
|
* If this function return false, all given parameters are in undefined status.
|
||||||
|
*/
|
||||||
bool IsSwitch(
|
bool IsSwitch(
|
||||||
bool* is_long_name = nullptr,
|
bool* is_long_name = nullptr,
|
||||||
yycc_u8string* long_name = nullptr,
|
yycc_u8string* long_name = nullptr,
|
||||||
yycc_char8_t* short_name = nullptr) const;
|
yycc_char8_t* short_name = nullptr) const;
|
||||||
bool IsParameter(yycc_u8string* val = nullptr) const;
|
/**
|
||||||
|
* @brief Check whether current argument is a value.
|
||||||
|
* @param[out] val
|
||||||
|
* The variable holding value if it is.
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @exception std::runtime_error Try fetching data at the tail of argument list.
|
||||||
|
* @return True if it is, otherwise false.
|
||||||
|
*/
|
||||||
|
bool IsValue(yycc_u8string* val = nullptr) const;
|
||||||
|
/**
|
||||||
|
* @brief Check whether we are at the tail of argument list.
|
||||||
|
* @details
|
||||||
|
* Please note EOF is a special state that you can not fetch data from it.
|
||||||
|
* EOF is the next element of the last element of argument list.
|
||||||
|
* It more like \c end() in most C++ container.
|
||||||
|
* @return True if it is, otherwise false.
|
||||||
|
*/
|
||||||
bool IsEOF() const;
|
bool IsEOF() const;
|
||||||
|
/**
|
||||||
|
* @brief Reset cursor to the head of argument list for reuse.
|
||||||
|
*/
|
||||||
void Reset();
|
void Reset();
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Check whether current argument is long name option / switch.
|
||||||
|
* @details This function is used by IsSwitch() internally.
|
||||||
|
* @param[out] name_part
|
||||||
|
* The container holding matched long name if it is (double dash stripped).
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @return True if it is, otherwise false.
|
||||||
|
*/
|
||||||
bool IsLongNameSwitch(yycc_u8string* name_part = nullptr) const;
|
bool IsLongNameSwitch(yycc_u8string* name_part = nullptr) const;
|
||||||
|
/**
|
||||||
|
* @brief Check whether current argument is short name option / switch.
|
||||||
|
* @details This function is used by IsSwitch() internally.
|
||||||
|
* @param[out] name_part
|
||||||
|
* The variable holding matched short name if it is (dash stripped).
|
||||||
|
* nullptr if you don't want to receive this infomation.
|
||||||
|
* @return True if it is, otherwise false.
|
||||||
|
*/
|
||||||
bool IsShortNameSwitch(yycc_char8_t* name_part = nullptr) const;
|
bool IsShortNameSwitch(yycc_char8_t* name_part = nullptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -45,40 +154,112 @@ namespace YYCC::ArgParser {
|
||||||
std::vector<yycc_u8string>::const_iterator m_ArgumentsIterator;
|
std::vector<yycc_u8string>::const_iterator m_ArgumentsIterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The base class of every argument.
|
||||||
|
* @details Programmer can inherit this class and implement essential functions to create custom argument.
|
||||||
|
*/
|
||||||
class AbstractArgument {
|
class AbstractArgument {
|
||||||
friend class OptionContext;
|
friend class OptionContext;
|
||||||
|
|
||||||
// Long name and short name constants and checker.
|
// Long name and short name constants and checker.
|
||||||
public:
|
public:
|
||||||
static const yycc_u8string DOUBLE_DASH;
|
static const yycc_u8string DOUBLE_DASH; ///< The constant value representing double dash (\c --)
|
||||||
static const yycc_char8_t DASH;
|
static const yycc_char8_t DASH; ///< The constant value representing dash (\c -)
|
||||||
static const yycc_char8_t NO_SHORT_NAME;
|
static const yycc_char8_t NO_SHORT_NAME; ///< The constant value representing that there is not short value.
|
||||||
static const yycc_char8_t MIN_SHORT_NAME;
|
static const yycc_char8_t MIN_SHORT_NAME; ///< The constant value representing the minimum value of valid ASCII chars in short and long name.
|
||||||
static const yycc_char8_t MAX_SHORT_NAME;
|
static const yycc_char8_t MAX_SHORT_NAME; ///< The constant value representing the maximum value of valid ASCII chars in short and long name.
|
||||||
|
/**
|
||||||
|
* @brief Check whether given short name is valid.
|
||||||
|
* @details
|
||||||
|
* An ASCII code of valid short name
|
||||||
|
* should not lower than #MIN_SHORT_NAME or higher than #MAX_SHORT_NAME.
|
||||||
|
* It also can not be #DASH.
|
||||||
|
* @param[in] short_name Short name for checking.
|
||||||
|
* @return True if it is valid, otherwise false.
|
||||||
|
*/
|
||||||
static bool IsLegalShortName(yycc_char8_t short_name);
|
static bool IsLegalShortName(yycc_char8_t short_name);
|
||||||
|
/**
|
||||||
|
* @brief Check whether given long name is valid.
|
||||||
|
* @details
|
||||||
|
* An ASCII code of every item in valid long name
|
||||||
|
* should not lower than #MIN_SHORT_NAME or higher than #MAX_SHORT_NAME.
|
||||||
|
* However it can be #DASH. This is different with short name.
|
||||||
|
* @param[in] long_name Long name for checking.
|
||||||
|
* @return True if it is valid, otherwise false.
|
||||||
|
*/
|
||||||
static bool IsLegalLongName(const yycc_u8string_view& long_name);
|
static bool IsLegalLongName(const yycc_u8string_view& long_name);
|
||||||
|
|
||||||
// Constructor & destructor
|
// Constructor & destructor
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor an argument
|
||||||
|
* @param[in] long_name The long name of this argument. nullptr if no long name.
|
||||||
|
* @param[in] short_name The short name of this argument. #NO_SHORT_NAME if no short name.
|
||||||
|
* @param[in] description The description of this argument to indroduce what this argument does. nullptr if no description.
|
||||||
|
* @param[in] argument_example The example string of this argument's value. nullptr if no example.
|
||||||
|
* @param[in] is_optional
|
||||||
|
* True if this argument is optional argument.
|
||||||
|
* Optional argument can be absent in argument list.
|
||||||
|
* Non-optional argument must be presented in argument list,
|
||||||
|
* otherwise parser will fail.
|
||||||
|
* @exception std::invalid_argument Given short name or long name are invalid.
|
||||||
|
*/
|
||||||
AbstractArgument(
|
AbstractArgument(
|
||||||
const yycc_char8_t* long_name, yycc_char8_t short_name = AbstractArgument::NO_SHORT_NAME,
|
const yycc_char8_t* long_name, yycc_char8_t short_name = AbstractArgument::NO_SHORT_NAME,
|
||||||
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
||||||
bool is_optional = false);
|
bool is_optional = false);
|
||||||
virtual ~AbstractArgument();
|
virtual ~AbstractArgument();
|
||||||
|
|
||||||
|
// ===== User Implementation =====
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief User implemented custom parse function
|
||||||
|
* @param[in] al The argument list for parsing.
|
||||||
|
* @return True if parse is success, otherwise false.
|
||||||
|
* @remarks
|
||||||
|
* When enter this function, argument list points to switch self.
|
||||||
|
* After success parsing, you should point it to the argument this function last accepted.
|
||||||
|
* For exmaple, for command line "-i 114514",
|
||||||
|
* when enter this function, this argument list point to "-i",
|
||||||
|
* and you should set it to "114514" when exiting this function.
|
||||||
|
*/
|
||||||
virtual bool Parse(ArgumentList& al) = 0;
|
virtual bool Parse(ArgumentList& al) = 0;
|
||||||
|
/**
|
||||||
|
* @brief User implemented custom reset function
|
||||||
|
* @remarks
|
||||||
|
* In this function, user should claer its stored value if is has.
|
||||||
|
* You don't need clar capture state. That is done by library self.
|
||||||
|
*/
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
|
|
||||||
|
// ===== Basic Infos =====
|
||||||
public:
|
public:
|
||||||
|
/// @brief Check whether this argument specify long name.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool HasLongName() const;
|
bool HasLongName() const;
|
||||||
|
/// @brief Get specified long name.
|
||||||
|
/// @return Specified long name.
|
||||||
const yycc_u8string& GetLongName() const;
|
const yycc_u8string& GetLongName() const;
|
||||||
|
/// @brief Check whether this argument specify short name.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool HasShortName() const;
|
bool HasShortName() const;
|
||||||
|
/// @brief Get specified short name.
|
||||||
|
/// @return Specified short name.
|
||||||
yycc_char8_t GetShortName() const;
|
yycc_char8_t GetShortName() const;
|
||||||
|
/// @brief Check whether this argument specify description.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool HasDescription() const;
|
bool HasDescription() const;
|
||||||
|
/// @brief Get specified description.
|
||||||
|
/// @return Specified description.
|
||||||
const yycc_u8string& GetDescription() const;
|
const yycc_u8string& GetDescription() const;
|
||||||
|
/// @brief Check whether this argument specify example.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool HasArgumentExample() const;
|
bool HasArgumentExample() const;
|
||||||
|
/// @brief Get specified example.
|
||||||
|
/// @return Specified example.
|
||||||
const yycc_u8string& GetArgumentExample() const;
|
const yycc_u8string& GetArgumentExample() const;
|
||||||
|
/// @brief Check whether this argument is optional.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool IsOptional() const;
|
bool IsOptional() const;
|
||||||
private:
|
private:
|
||||||
yycc_u8string m_LongName;
|
yycc_u8string m_LongName;
|
||||||
|
@ -86,24 +267,52 @@ namespace YYCC::ArgParser {
|
||||||
yycc_u8string m_Description;
|
yycc_u8string m_Description;
|
||||||
yycc_u8string m_ArgumentExample;
|
yycc_u8string m_ArgumentExample;
|
||||||
bool m_IsOptional;
|
bool m_IsOptional;
|
||||||
|
|
||||||
|
// ===== Capture State =====
|
||||||
public:
|
public:
|
||||||
|
/// @brief Check whether this argument has been captured.
|
||||||
|
/// @return True if it is, otherwise false.
|
||||||
bool IsCaptured() const;
|
bool IsCaptured() const;
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Set capture state of this argument.
|
||||||
|
* @details This function is used internally by OptionContext.
|
||||||
|
* @param[in] is_captured New states of captured.
|
||||||
|
*/
|
||||||
void SetCaptured(bool is_captured);
|
void SetCaptured(bool is_captured);
|
||||||
bool m_IsCaptured;
|
bool m_IsCaptured;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief The core of argument parser, also manage all arguments.
|
||||||
class OptionContext {
|
class OptionContext {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Construct option context.
|
||||||
|
* @param[in] summary The summary of this application which will be printed in help text.
|
||||||
|
* @param[in] description The description of this application which will be printed in help text.
|
||||||
|
* @param[in] arguments The initializer list including pointers to all arguments.
|
||||||
|
*/
|
||||||
OptionContext(
|
OptionContext(
|
||||||
const yycc_char8_t* summary, const yycc_char8_t* description,
|
const yycc_char8_t* summary, const yycc_char8_t* description,
|
||||||
std::initializer_list<AbstractArgument*> arguments);
|
std::initializer_list<AbstractArgument*> arguments);
|
||||||
~OptionContext();
|
~OptionContext();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Start a parse.
|
||||||
|
* @param[in] al The reference to ArgumentList for parsing.
|
||||||
|
* @return
|
||||||
|
* True if success, otherwise false.
|
||||||
|
* If this function return false, you should not visit any arguments it managed.
|
||||||
|
*/
|
||||||
bool Parse(ArgumentList& al);
|
bool Parse(ArgumentList& al);
|
||||||
|
/**
|
||||||
|
* @brief Reset all managed argument to default state thus you can start another parsing.
|
||||||
|
*/
|
||||||
void Reset();
|
void Reset();
|
||||||
|
/**
|
||||||
|
* @brief Print help text in \c stdout.
|
||||||
|
*/
|
||||||
void Help() const;
|
void Help() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -116,10 +325,24 @@ namespace YYCC::ArgParser {
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma region Argument Presets
|
#pragma region Argument Presets
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Arithmetic (integral, floating point. except bool) type argument
|
||||||
|
* @tparam _Ty The internal stored type belongs to arithmetic type.
|
||||||
|
*/
|
||||||
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
|
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
|
||||||
class NumberArgument : public AbstractArgument {
|
class NumberArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor an arithmetic argument
|
||||||
|
* @param[in] long_name The long name of this argument. nullptr if no long name.
|
||||||
|
* @param[in] short_name The short name of this argument. #NO_SHORT_NAME if no short name.
|
||||||
|
* @param[in] description The description of this argument to indroduce what this argument does. nullptr if no description.
|
||||||
|
* @param[in] argument_example The example string of this argument's value. nullptr if no example.
|
||||||
|
* @param[in] is_optional True if this argument is optional argument.
|
||||||
|
* @param[in] constraint The constraint applied to this argument.
|
||||||
|
* @exception std::invalid_argument Given short name or long name are invalid.
|
||||||
|
*/
|
||||||
NumberArgument(
|
NumberArgument(
|
||||||
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
||||||
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
||||||
|
@ -129,6 +352,7 @@ namespace YYCC::ArgParser {
|
||||||
virtual ~NumberArgument() {}
|
virtual ~NumberArgument() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// @brief Get stored data in argument.
|
||||||
_Ty Get() const {
|
_Ty Get() const {
|
||||||
if (!IsCaptured()) throw std::runtime_error("try fetching data from a not captured argument.");
|
if (!IsCaptured()) throw std::runtime_error("try fetching data from a not captured argument.");
|
||||||
return m_Data;
|
return m_Data;
|
||||||
|
@ -139,7 +363,7 @@ namespace YYCC::ArgParser {
|
||||||
// try get corresponding value
|
// try get corresponding value
|
||||||
yycc_u8string strval;
|
yycc_u8string strval;
|
||||||
al.Next();
|
al.Next();
|
||||||
if (al.IsEOF() || !al.IsParameter(&strval)) {
|
if (al.IsEOF() || !al.IsValue(&strval)) {
|
||||||
al.Prev();
|
al.Prev();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -160,32 +384,44 @@ namespace YYCC::ArgParser {
|
||||||
Constraints::Constraint<_Ty> m_Constraint;
|
Constraints::Constraint<_Ty> m_Constraint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A simple switch type argument which do not store any value.
|
||||||
|
*/
|
||||||
class SwitchArgument : public AbstractArgument {
|
class SwitchArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor an switch argument
|
||||||
|
* @param[in] long_name The long name of this argument. nullptr if no long name.
|
||||||
|
* @param[in] short_name The short name of this argument. #NO_SHORT_NAME if no short name.
|
||||||
|
* @param[in] description The description of this argument to indroduce what this argument does. nullptr if no description.
|
||||||
|
* @exception std::invalid_argument Given short name or long name are invalid.
|
||||||
|
*/
|
||||||
SwitchArgument(
|
SwitchArgument(
|
||||||
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
||||||
const yycc_char8_t* description = nullptr) :
|
const yycc_char8_t* description = nullptr) :
|
||||||
// bool switch must be optional, because it is false if no given switch.
|
// bool switch must be optional, because it is false if no given switch.
|
||||||
// bool switch doesn't have argument, so it doesn't have example property.
|
// bool switch doesn't have argument, so it doesn't have example property.
|
||||||
AbstractArgument(long_name, short_name, description, nullptr, true), m_Data(false) {}
|
AbstractArgument(long_name, short_name, description, nullptr, true) {}
|
||||||
virtual ~SwitchArgument() {}
|
virtual ~SwitchArgument() {}
|
||||||
|
|
||||||
public:
|
|
||||||
bool Get() const { return m_Data; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool Parse(ArgumentList& al) override {
|
virtual bool Parse(ArgumentList& al) override { return true; } // simply return true because no value to store.
|
||||||
m_Data = true;
|
virtual void Reset() override {} // nothing need to be reset.
|
||||||
return true;
|
|
||||||
}
|
|
||||||
virtual void Reset() override { m_Data = false; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool m_Data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief String type argument
|
||||||
class StringArgument : public AbstractArgument {
|
class StringArgument : public AbstractArgument {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor a string argument
|
||||||
|
* @param[in] long_name The long name of this argument. nullptr if no long name.
|
||||||
|
* @param[in] short_name The short name of this argument. #NO_SHORT_NAME if no short name.
|
||||||
|
* @param[in] description The description of this argument to indroduce what this argument does. nullptr if no description.
|
||||||
|
* @param[in] argument_example The example string of this argument's value. nullptr if no example.
|
||||||
|
* @param[in] is_optional True if this argument is optional argument.
|
||||||
|
* @param[in] constraint The constraint applied to this argument.
|
||||||
|
* @exception std::invalid_argument Given short name or long name are invalid.
|
||||||
|
*/
|
||||||
StringArgument(
|
StringArgument(
|
||||||
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
const yycc_char8_t* long_name, yycc_char8_t short_name,
|
||||||
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
||||||
|
@ -195,6 +431,7 @@ namespace YYCC::ArgParser {
|
||||||
virtual ~StringArgument() {}
|
virtual ~StringArgument() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// @brief Get stored data in argument.
|
||||||
const yycc_u8string& Get() const {
|
const yycc_u8string& Get() const {
|
||||||
if (!IsCaptured()) throw std::runtime_error("try fetching data from a not captured argument.");
|
if (!IsCaptured()) throw std::runtime_error("try fetching data from a not captured argument.");
|
||||||
return m_Data;
|
return m_Data;
|
||||||
|
@ -204,7 +441,7 @@ namespace YYCC::ArgParser {
|
||||||
virtual bool Parse(ArgumentList& al) override {
|
virtual bool Parse(ArgumentList& al) override {
|
||||||
// try get corresponding value
|
// try get corresponding value
|
||||||
al.Next();
|
al.Next();
|
||||||
if (al.IsEOF() || !al.IsParameter(&m_Data)) {
|
if (al.IsEOF() || !al.IsValue(&m_Data)) {
|
||||||
al.Prev();
|
al.Prev();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
namespace YYCC::ConfigManager {
|
namespace YYCC::ConfigManager {
|
||||||
|
|
||||||
/// @brief The base class of every setting.
|
/// @brief The base class of every setting.
|
||||||
/// @details Programmer can inherit this class and implement essential to create custom setting.
|
/// @details Programmer can inherit this class and implement essential functions to create custom setting.
|
||||||
class AbstractSetting {
|
class AbstractSetting {
|
||||||
friend class CoreManager;
|
friend class CoreManager;
|
||||||
public:
|
public:
|
||||||
|
@ -42,19 +42,19 @@ namespace YYCC::ConfigManager {
|
||||||
|
|
||||||
// User Implementations
|
// User Implementations
|
||||||
protected:
|
protected:
|
||||||
/// @brief User implemented custom load functions
|
/// @brief User implemented custom load function
|
||||||
/// @remarks
|
/// @remarks
|
||||||
/// In this function, programmer should read data from internal buffer
|
/// In this function, programmer should read data from internal buffer
|
||||||
/// and store it to its own another internal variables.
|
/// and store it to its own another internal variables.
|
||||||
/// @return True if success, otherwise false.
|
/// @return True if success, otherwise false.
|
||||||
virtual bool UserLoad() = 0;
|
virtual bool UserLoad() = 0;
|
||||||
/// @brief User implemented custom save functions
|
/// @brief User implemented custom save function
|
||||||
/// @remarks
|
/// @remarks
|
||||||
/// In this function, programmer should write data,
|
/// In this function, programmer should write data,
|
||||||
/// which is stored in another variavle by it own, to internal buffer.
|
/// which is stored in another variavle by it own, to internal buffer.
|
||||||
/// @return True if success, otherwise false.
|
/// @return True if success, otherwise false.
|
||||||
virtual bool UserSave() = 0;
|
virtual bool UserSave() = 0;
|
||||||
/// @brief User implemented custom reset functions
|
/// @brief User implemented custom reset function
|
||||||
/// @remarks In this function, programmer should reset its internal variable to default value.
|
/// @remarks In this function, programmer should reset its internal variable to default value.
|
||||||
virtual void UserReset() = 0;
|
virtual void UserReset() = 0;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace YYCC::ExceptionHelper {
|
||||||
* (for convenient debugging of developer when reporting bugs.)
|
* (for convenient debugging of developer when reporting bugs.)
|
||||||
*
|
*
|
||||||
* This function usually is called at the start of program.
|
* This function usually is called at the start of program.
|
||||||
|
* @param[in] callback User defined callback called when unhandled exception happened. nullptr if no callback.
|
||||||
*/
|
*/
|
||||||
void Register(ExceptionCallback callback = nullptr);
|
void Register(ExceptionCallback callback = nullptr);
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -544,7 +544,11 @@ auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(sizeof(test_argv) / sizeo
|
||||||
PREPARE_DATA("exec", "-i", "114514");
|
PREPARE_DATA("exec", "-i", "114514");
|
||||||
Assert(test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(!test.m_BoolArgument.Get(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(!test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
|
Assert(!test.m_FloatArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
|
Assert(!test.m_StringArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
|
Assert(!test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
|
Assert(!test.m_ClampedFloatArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
test.m_OptionContext.Reset();
|
test.m_OptionContext.Reset();
|
||||||
}
|
}
|
||||||
// no argument
|
// no argument
|
||||||
|
@ -565,6 +569,12 @@ auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(sizeof(test_argv) / sizeo
|
||||||
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
test.m_OptionContext.Reset();
|
test.m_OptionContext.Reset();
|
||||||
}
|
}
|
||||||
|
// dplicated assign
|
||||||
|
{
|
||||||
|
PREPARE_DATA("exec", "-i", "114514" "--int", "114514");
|
||||||
|
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
|
test.m_OptionContext.Reset();
|
||||||
|
}
|
||||||
// extra useless argument
|
// extra useless argument
|
||||||
{
|
{
|
||||||
PREPARE_DATA("exec", "-i", "114514" "1919810");
|
PREPARE_DATA("exec", "-i", "114514" "1919810");
|
||||||
|
@ -584,7 +594,7 @@ auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(sizeof(test_argv) / sizeo
|
||||||
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(test.m_FloatArgument.IsCaptured() && test.m_FloatArgument.Get() == 2.0f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_FloatArgument.IsCaptured() && test.m_FloatArgument.Get() == 2.0f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(test.m_StringArgument.IsCaptured() && test.m_StringArgument.Get() == YYCC_U8("fuck"), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_StringArgument.IsCaptured() && test.m_StringArgument.Get() == YYCC_U8("fuck"), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(test.m_BoolArgument.IsCaptured() && test.m_BoolArgument.Get(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
Assert(test.m_ClampedFloatArgument.IsCaptured() && test.m_ClampedFloatArgument.Get() == 0.5f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
Assert(test.m_ClampedFloatArgument.IsCaptured() && test.m_ClampedFloatArgument.Get() == 0.5f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
|
||||||
test.m_OptionContext.Reset();
|
test.m_OptionContext.Reset();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user