Difference between revisions of "The libshore C++ Library"

From SHORE wiki
Jump to: navigation, search
(Adding command line options)
(Further documentation to be written.)
 
(3 intermediate revisions by the same user not shown)
Line 4: Line 4:
 
[http://shore.sourceforge.net/libshore-api/files.html Doxygen-generated API documentation] is available.
 
[http://shore.sourceforge.net/libshore-api/files.html Doxygen-generated API documentation] is available.
  
== The ''program'' class ==
+
= The ''program'' class =
  
The ''' ''program'' ''' class is a command line interface base class providing command line option parsing and documentation as well as application-level exception handling and reporting.
+
The [http://shore.sourceforge.net/libshore-api/classshore_1_1program.html ''' ''program'' ''' class is a command line interface base class providing command line option parsing and documentation as well as application-level exception handling and reporting.
  
=== Hello world ===
+
== Hello world ==
  
 
  // file hello_program.cpp
 
  // file hello_program.cpp
Line 57: Line 57:
 
  Hello, world!
 
  Hello, world!
  
=== Adding command line options ===
+
== Adding command line options ==
  
 
Command line options and further usage instructions may be defined in the class's constructor.
 
Command line options and further usage instructions may be defined in the class's constructor.
Line 83: Line 83:
 
  virtual void sanity_check()
 
  virtual void sanity_check()
 
  {
 
  {
  if(m_conf.name=="Joe")
+
  if(m_conf.name == "Joe")
 
  throw usage_error("Joe is not around");
 
  throw usage_error("Joe is not around");
 
  }
 
  }
Line 100: Line 100:
 
  }
 
  }
 
  };
 
  };
 
int main(int ac, char **av)
 
{
 
hello_program p;
 
p(ac, av);
 
return p.status();
 
}
 
  
 +
(the global ''main()'' function is omitted from now on)
  
 
When called without command line options, the output is now
 
When called without command line options, the output is now
Line 216: Line 210:
 
  error: need `--names' (mandatory)
 
  error: need `--names' (mandatory)
  
== Further documentation to be written. ==
+
= Further documentation to be written. =

Latest revision as of 19:59, 20 June 2013

Basic functionality used by SHORE is provided as a C++ programming library residing below the directory src/CoreLib of the SHORE source package. The make install command will by default install the libshore library and headers below /usr/local/lib and /usr/local/include, respectively; see the file INSTALL distributed with the SHORE sources for details.

Doxygen-generated API documentation is available.

The program class

The program class is a command line interface base class providing command line option parsing and documentation as well as application-level exception handling and reporting.

Hello world

// file hello_program.cpp

#include <iostream> 
#include "shore/program/program.hpp"

class hello_program
:public shore::program
{
 protected:

        virtual int main()
        {
                std::cout << "\nHello, world!\n" << std::endl;
        }
};

int main(int ac, char **av)
{
        hello_program p;
        p(ac, av);
        return p.status();
}

Given libshore is installed system-wide, this program may be compiled using the command

$ g++ -lshore -o hello hello_program.cpp

The default behavior of the program base class is to display usage instructions when no command line arguments are provided:

$ ./hello

./hello

Usage: ./hello 

However, the main() method is invoked if the command's input is a pipe:

$ true | ./hello

Hello, world!

This default behavior is sensible for many applications. It may however be altered by overriding the protected base class method basic_sanity_check():

        virtual void basic_sanity_check() {}

As a result, the default is no longer to display the help page:

$ ./hello

Hello, world!

Adding command line options

Command line options and further usage instructions may be defined in the class's constructor.

For clarity, command line option variables are grouped in a struct config in our example.

For validation of provided user input, the protected base class method sanity_check() may be implemented.

Invalid user input is indicated by throwing an exception of class usage_error defined by the program class:

class hello_program
:public shore::program
{
 private:
        
	struct config
	{
		std::string name;
	};
 
	config m_conf;

 protected:

	virtual void sanity_check()
	{
		if(m_conf.name == "Joe")
			throw usage_error("Joe is not around");
	}

	virtual int main()
	{
		std::cout << "\nHello, " << m_conf.name << "!\n" <<std::endl;
	}

 public:

	hello_program()
	{
		set_description("Greeter program");
		add_option("name,n", &m_conf.name, "The person to greet (but not Joe)");
	}
};

(the global main() function is omitted from now on)

When called without command line options, the output is now

$ ./hello

./hello --- Greeter program

Usage: ./hello [OPTIONS]

Allowed options:
  -n, --name=STRING (not set) The person to greet (but not Joe)

Command line options are automatically verified through sanity_check():

$ ./hello -n Jim

Hello, Jim!

$ ./hello -n Joe

./hello --- Greeter program

Usage: ./hello [OPTIONS]

Allowed options:
  -n, --name=STRING (=Joe) The person to greet (but not Joe)

error: Joe is not around

Command line option variables are not restricted to the std::string class, but may be of any class for which an operator>> for std::istream objects is defined. Furthermore, certain classes such as std::vector<T> are handled explicitly by the command line option parser:

#include <iostream>
#include <string>
#include <vector>
#include "shore/program/program.hpp"
#include "shore/base/stringops.hpp" // for shore::join() and shore::to_string()

class hello_program
:public shore::program
{
 private:
        
	struct config
	{
		std::vector<std::string> names;
		int times;
	};
 
	config m_conf;

 protected:

	virtual void sanity_check()
	{
		if(m_conf.times < 1)
			throw usage_error("invalid value " + shore::to_string(m_conf.times) + " for --times");
	}

	virtual int main()
	{
		for(int i = 0; i < m_conf.times; ++i)
			std::cout << "Hello, " << shore::join(m_conf.names, ", ") << '!' <<std::endl;
	}

 public:

	hello_program()
	{
		m_conf.times=1;

		set_description("Greeter program");
		add_option("names,n", &m_conf.names, "The people to greet", shore::OPT_MANDATORY);
		add_option("times,t", &m_conf.times, "Greet multiple times");
	}
};

When correctly invoked, the example's output is

$ ./hello -t 2 -n Jim -n Joe
Hello, Jim, Joe!
Hello, Jim, Joe!

In this example, the sanity_check() method was changed to ensure correct specification of the --times option. Furthermore, the default value for times was set to 1 in the constructor, which is displayed accordingly in the middle column of the new help page:

$ ./hello

./hello --- Greeter program

Usage: ./hello OPTIONS

Allowed options:
  -n, --names=STRING[,...] (mandatory) The people to greet
  -t, --times=INT          (=1)        Greet multiple times

For options that do not have a default value, output of the default may be suppressed by specifying shore::OPT_NOTSET as an additional parameter to the add_option() method.

Furthermore, as shown in the example's constructor, shore::OPT_MANDATORY may be specified to instruct the command line option parser to automatically verify that an option was specified by the user:

$ ./hello -t 2

./hello --- Greeter program

Usage: ./hello OPTIONS

Allowed options:
  -n, --names=STRING[,...] (mandatory) The people to greet
  -t, --times=INT          (=2)        Greet multiple times

error: need `--names' (mandatory)

Further documentation to be written.