1# libbase components 2 3## pandargs 4 5### Description: 6 7pandargs is header-only utility tool that helps to parse command line arguments. It supports several argument types: 8- integer 9- double 10- boolean 11- string 12- uint32_t 13- uint64_t 14- list 15- compound 16 17The more detail description of each type is in "Usage" section below. 18 19Source code of pandargs contains in `utils/pandargs.h` file. 20 21### Usage: 22 23pandargs API consists of two major entities: template class `PandArg`, which represents an argument and `PandArgParser` class, which represents a parser. 24 25Instead of `PandArg`, `PandArgCompound` can be used, which serves for creation of the compound arguments. 26It inherits `PandArg<bool>`. 27 28#### Arguments 29 30To create an argument, it's template constructor should be called. Here is an instance: 31 32```c++ 33 // argument name | default value | argument description 34 panda::PandArg<bool> pab("bool", false, "Sample boolean argument"); 35 // argument name | argument description | sub-arguments 36 PandArgCompound arg("compound", "Sample boolean argument", {&sub_bool_arg, &sub_int_arg, &sub_double_arg, &sub_string_arg}); 37``` 38 39Constructor can accept: 40- 3 parameters: argument name, default value, description. 41- 4 parameters for single list: argument name, default value, description, delimiter. 42- 5 parameters for integer args: argument name, default value, description, min value, max value 43- PandArgCompound accepts three parameters: argument name, description and list of sub-arguments 44 45There is description for them: 46- Argument name, is a name, which will appear in a command line. 47- Default value is a value argument will have regardless was it parsed or not. 48- Argument description will be used to form a help message. 49- Delimiter is a character or string that separates the different value if the single argument list 50- Min value is the number that the integer argument cannot be less than 51- Max value is the number that the integer argument cannot be greater than 52- List of sub-arguments has type `std::initializer_list<PandArgBase *>`, and it accepts any non-compound arguments. 53 Sub-arguments should not be added to the parser via `PandArgParser::Add`. 54 55Template parameter is an argument type. Following values could be passed: 56- `int` for integer argument 57- `double` for double argument 58- `bool` for boolean argument 59- `std::string` for string argument 60- `uint64_t` for uint64_t argument 61- `uint32_t` for uint32_t argument 62- `arg_list_t` for list argument 63 64`arg_list_t` is a type, declared in `pandargs.h` under `panda` namespace, which is an alias for `std::vector<std::string>` type. 65 66`PandArg` provides following public API: 67- `PandArgType GetType()` - returns type of an argument 68- `std::string GetName()` - returns name of an argument 69- `std::string GetDesc()` - returns description of an argument 70- `T GetValue()` - returns value of an argument depending on it's type 71- `T GetDefaultValue()` - returns default value of an argument 72- `void SetValue(T val)` - set value of an argument 73- `ResetDefaultValue()` - set value back to default one 74 75#### Argument types 76There are three global argument types in pandargs: 77- regular arguments 78- tail arguments 79- remainder arguments 80 81Regular arguments are typical non-positional arguments like ```--arg=1``` 82Tail arguments are positional arguments, which should be introduced with help of parser API 83Remainder arguments are arguments that come after trailing `--`. All of them are plain std::vector of std::string 84 85Compound argument is a boolean argument, which can contains sub-arguments, followed by symbol `:`, 86e.g: `--compiler-dump:folder=ir_dump,compact`. Sub-arguments follow the same rules as the regular arguments 87and can be any type of argument. Compound arguments implicitly have default value `false` and user can't change it. 88 89To access compound arguments from `C++`, regular convention should be used, for accessing sub-arguments, method name 90contains name of the compound argument plus name of the sub-argument. 91E.g. `--compiler-dump:compact`, here, to access `compact` sub-arguments `[Is|Get]CompilerDumpCompact()` should be used. 92 93#### Parser 94 95`PandArgParser` provides following public API: 96- `bool Add(PandArgBase* arg)` - add an argument to parser. Returns `true` if argument was succsessfully added. `PandArgBase` is a base type for all template argument types 97- `bool Parse(int argc, const char* argv[])` - parse arguments. Returns `true` on success. Note: `argv` & `argc` should be passed as is, without any amendments 98- `std::string GetErrorString()` - returns error string if error occurred on argument addition or parsing 99- `void EnableTail()` - enables positional arguments 100- `void DisableTail()` - disables positional arguments 101- `bool IsTailEnabled()` - returns `true` if positional arguments enabled 102- `bool IsArgSet(PandArgBase* arg)` - returns `true` if an argument was added to a parser 103- `bool IsArgSet(const std::string& arg_name)` - returns `true` if an argument with given name was added to a parser 104- `bool PushBackTail(PandArgBase* arg)` - add tail argument to the end of tail arguments list. `false` if argument already in a tail list 105- `bool PopBackTail()` - remove last argument from tail list 106- `void EraseTail()` - remove all arguments from tail list 107- `void EnableRemainder()` - enable remainder argument 108- `void DisableRemainder()` - disable remainder argument 109- `bool IsRemainderEnabled()` - `true` if remainder argument enabled 110- `arg_list_t GetRemainder()` - returns remainder argument 111- `std::string GetHelpString()` - returns string with all arguments and their description 112- `std::string GetRegularArgs()` - returns string with all regular arguments and their values 113 114Tail argument is a sequence of positinal arguments values. Function ```PushBackTail()``` adds an argument to the end of sequence, ```PopBackTail()``` removes the last added argument. Tail arguments may be added to a parser when tail is disabled, but they will be ignored if tail is disabled while parsing 115 116Sample parser usage: 117```c++ 118 panda::PandArgParser pa_parser; 119 pa_parser.EnableTail(); 120 pa_parser.Add(&pab); 121 if (!pa_parser.Add(&pab)) { 122 std::cout << pa_parser.GetErrorString(); 123 } 124 if (!pa_parser.Parse(argc, argv)) { 125 std::cout << pa_parser.GetErrorString(); 126 } 127``` 128 129#### Command line arguments convention 130 131- Any non-positional argument should start with `--` (double dash) prefix 132- Argument and it's value may be separated either by whitespace (` `) or by equals (`=`) sign 133- If tail (positional arguments) enabled, first argument without double dash prefix concidered as a begin of positional arguments sequence 134- Positional arguments should be without names or `=` signs, separated by whitespaces 135- Boolean argument may be used without a value. This arguments always considered as `true` 136- Remainder arguments are all literals that come after trailing `--` 137- True values for boolean arguments: **true**, **on**, **1** 138- False values for boolean arguments: **false**, **off**, **0** 139- for integer arguments it's possible to define value range 140- list values must be repeated with arg name or separated by delimiter 141- string and list arguments may accept no parameters 142 143Sample command line usage: 144```bash 145$ ./app --bool # bool is true 146$ ./app --bool= # bool is true 147$ ./app --bool on --bool1=off # bool is true, bool1 is false 148$ ./app --uint32=32 # uint32 is 32 149$ ./app --uint64=64 # uint64 is 64 150$ ./app --string="a string" # string is "a string" 151$ ./app --string "a string" # string is "a string" 152$ ./app --string string # string is "string" 153$ ./app --string= --int=1 # string is an empty string, int is 1 154$ ./app --list=val1 --list=val2 --list=val3 # list argument example 155$ ./app --slist=val1:val2:val3 # list argument example 156$ ./app --int=0x40 --uint64=0x400 # int is 64, uint64 is 1024 157$ ./app --int=1 false -1 "list1 list2 list3" # tail arguments example 158$ ./app --double 3.14 --bool off -- arg1 --arg2=1 --arg3=false # remainder arguments example 159$ ./app --compound:bool,int=2,double=54.321,string=Hello # Compound argument example 160``` 161In the tail arguments example, `false` is a boolean value, `-1` is integer value and `str1` and `str2` is a string value. List may not be a tail argument. Positional values verified the same way as regular values, difference only that it's names are ignored in an input string, but position matters 162In the remainder arguments example, all literals coming after `--` will go to remainder and can be obtained by `GetRemainder()` function 163 164How to add tail arguments: 165```c++ 166 panda::PandArgParser pa_parser; 167 pa_parser.EnableTail(); 168 // now pab will be processed as a positional argument 169 if (!pa_parser.PushBackTail(&pab)) { 170 std::cout << pa_parser.GetErrorString(); 171 } 172 if (!pa_parser.Parse(argc, argv)) { 173 std::cout << pa_parser.GetErrorString(); 174 } 175``` 176