Tutorial 3: Read and write commands¶
This tutorial shows how to integrate read and write functions to the shell
interface. The general mechanism works as follows. We first define a file
type, and name it using a tag. Then we can enable read and write commands for
this tag to a store type, which result in commands read_<tag> --<flag>
and
write_<tag> --<flag>
, where <tag>
is the tag name of the file type and
<flag>
is the flag name of the store type.
Our tutorial catches up where we left in the previous tutorial and defines a single store type for strings, and adds a function to print store elements.
#include <alice/alice.hpp>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
namespace alice
{
ALICE_ADD_STORE( std::string, "str", "s", "string", "strings" )
ALICE_PRINT_STORE( std::string, os, element )
{
os << element << std::endl;
}
We now add the file type to read and write to text files using the macro
ALICE_ADD_FILE_TYPE
, which receives the tag name as first argument
and a string defining it as second argument. The second argument will be used
to generate help strings.
ALICE_ADD_FILE_TYPE( text, "Text" )
If we wish to only read from or only write to a file type, we can use the macros
ALICE_ADD_FILE_TYPE_READ_ONLY
or
ALICE_ADD_FILE_TYPE_WRITE_ONLY
, respectively. They have the same
signature.
Once the file type is declared, we can link the string store type to the file
type and add functions to read from files and to write from files. Reading from
files is enabled using the macro ALICE_READ_FILE
, which receives four
parameters. The first two parameters are store type and tag name. The third
parameter is the variable name containing the filename, and the last parameter
gives access to the command parsing interface, which we won’t use in this
tutorial.
ALICE_READ_FILE( std::string, text, filename, cmd )
{
std::ifstream in( filename.c_str(), std::ifstream::in );
std::stringstream buffer;
buffer << in.rdbuf();
return buffer.str();
}
Similarly, we enable writing from files using the macro
ALICE_WRITE_FILE
. It receives one further parameter called
element
, which is a variable accessing the current store element that should
be written to a file.
ALICE_WRITE_FILE( std::string, text, element, filename, cmd )
{
std::ofstream out( filename.c_str(), std::ofstream::out );
out << element;
}
That’s all we need to read and write from files. Finally, we add one further
command to manipulate store entries. The command upper
will allow to change
string elements into upper case.
ALICE_COMMAND(upper, "Manipulation", "changes string to upper bound")
{
auto& str = store<std::string>().current();
std::transform( str.begin(), str.end(), str.begin(), ::toupper );
}
}
ALICE_MAIN( tutorial3 )