[Original] Command Line Parameter Parsing and configuration programming process paradigm, command line parameter paradigm
When studying the open source code of Bitshares 2.0, I was amazed at the excellent process of parsing the command line parameters in the main function of witness_node. Here we will post the code for appreciation:
1 namespace bpo = boost: program_options; 2 3 ............... 4 ............... 5 int main (int argc, char ** argv) {6 app: application * node = new app: application (); 7 fc: oexception unhandled_exception; 8 9 try {10 bpo: options_description app_options ("Graphene Witness Node"); 11 bpo: options_description using _options ("Graphene Witness Node"); 12 app_options.add_options () 13 ("help, h", "Print this El P message and exit. ") 14 (" data-dir, d ", bpo: value <boost: filesystem: path> ()-> default_value (" witness_node_data_dir "), "Directory containing databases, configuration file, etc. ") 15; 16 17 bpo: variables_map options; 18 19 ............... 20 ............... 21 22 23 24 try {25 bpo: options_description cli, cfg; 26 // cli. cfg is an external parameter. Place cli and cfg in the set_program_options function, configure these two parameters and then add them to the app_options.add () function. 27 node-> set_program_options (cli, cfg); 28 app_options.add (cli); 29 // cfg_options the configuration here is not used immediately. In this scope, after configuring app_options and cmd_options, the cli and cfg parameters are released. 30 cfg_options.add (cfg); 34 // only app_options is used here. However, the content of cfg is added to the cli in the set_program_options () function. 31 bpo: store (bpo: parse_command_line (argc, argv, app_options), options); 32 33} 34 catch (const boost: program_options: error & e) 35 {36 std: cerr <"Error parsing command line:" <e. what () <"\ n"; 37 return 1; 38} 39 40 ............... 41 ............... 42} catch (const fc: exception & e) {43 // deleting the node can yield, so do this outside the exception handler44 unhandled_exception = e; 45} 46 47 if (unhandled_exception) 48 {49 elog ("Exiting with error: \ n $ {e}", ("e", unhandled_exception-> to_detail_string ())); 50 node-> shutdown (); 51 delete node; 52 return 1; 53}
Step 1: set global variables
namespace bpo = boost::program_options;
This facilitates subsequent descriptions, simplifies the code, and makes it easy to read. Before the main function, it is declared as a global variable.
Part 2: after entering the main program, define the exception variable
fc::oexception unhandled_exception;
Of course, you can also directly use related classes in the STL library or boost. Here we provide a basic paradigm. fc is a Fast-Compiling-Library (FC for short) that comes with Bitshares source code. It provides similar functions in many Boost libraries, however, specific projects are cropped. Because Bitshares is also a development framework.
Step 3: Build a try... catch... framework
try {
............ } catch( ClassType& e ) { // deleting the node can yield, so do this outside the exception handler unhandled_exception = e; }
Step 4: declare an instance of the options_description class. The parameter can be set as the main program name.
Then, use the add_options () function to add the content. Then, use a bracket to add an item, and add ";" to the end of the function. One Parameter in brackets is the setting parameter that needs to be attached to the program command line. The first item in "" is the full name, and "--" is added before execution; the second item is the short name, and "-" is added before execution.
bpo::options_description app_options("Graphene Witness Node");
app_options.add_options() ("help,h", "Print this help message and exit.") ("data-dir,d", bpo::value<boost::filesystem::path>()->default_value("witness_node_data_dir"), "Directory containing databases, configuration file, etc.");
However, in many special cases, you can use the add function to append the display content. However, you must first declare the container of the options_description class and write a function to add the content, these contents can be directly set from the command line string, or from the INI file.
bpo::options_description cli, cfg; node->set_program_options(cli, cfg); app_options.add(cli);
In this example, a set_program_options function is compiled, and node-> is used to overload it.
Step 5: declare a variables_map variable to hold the parsed data, use parse_command_line for parsing, and use the store function to save the parsed results in the variables_map container, the basic functions are completed.
bpo::variables_map options;bpo::store(bpo::parse_command_line(argc, argv, app_options), options);
Parse_command_line has three parameters. argc and argv come from the main program. app_options stores the added commands and information to be displayed.
Of course, if the added information comes from the ini configuration file, you can also use the parse_config_file function to parse app_options.
Step 6: handle exceptions
catch( const fc::exception& e ) { // deleting the node can yield, so do this outside the exception handler unhandled_exception = e; } if (unhandled_exception) { elog("Exiting with error:\n${e}", ("e", unhandled_exception->to_detail_string())); node->shutdown(); delete node; return 1; }
Here, elog is used to display exceptions and put the if processing on the outside, which makes the program more concise and clear, and you can add more try... catch... structure.
This programming process paradigm is very simple, practical, secure, and complete and can be applied in other tasks.