fsfc.hh File Reference
libfsfc (Fill Structure From Configuration) main header file. More...
|
Namespaces |
namespace | fsfc |
Functions |
template<class T> |
void | fsfc::parse (T &s, std::istream &is) |
| Fill a structure from an input stream.
|
template<class T> |
void | fsfc::parseFile (T &s, const std::string &fileName) |
| Conveniance function similar to parse() taking a file name as input.
|
template<class T> |
void | fsfc::output (T &s, std::ostream &os) |
| Write the structure contente into an output stream.
|
template<class T> |
void | fsfc::outputFile (T &s, const std::string &fileName) |
| Conveniance function similar to output() taking a file name as input.
|
Detailed Description
libfsfc (Fill Structure From Configuration) main header file.
libfsf, generating code to fill structures from configuration files.
Copyright (C) 2007 Matthieu Nottale.
This file is part of libfsfc.
libfsfc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3,
as published by the Free Software Foundation.
libfsfc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libfsfc. If not, see <http://www.gnu.org/licenses/>.
libfsfc is a library and a set of tools that takes C++ classes as input, and outputs C++ code to fill those structures from configuration files. The parser accepts a lot of different syntax, and can be configured for each class using keywords in the Doxygen documentation.
Suppose you have a file called "point.hh", containing a class Point: class Point {
public:
int x;
int y;
};
To generate the code to parse such a structure, type fsfcgen -o fsfc_point.hh -c point point.hh. This will generate the file fsfc_point.hh containing the code. Include the file (after including point.hh). Then, to parse a Point from an input stream, just type: Point p;
parse(p, myStream);
This code will successfuly fill p, if myStream contains a representation of a Point, such as "x 1 y 2", "1 2", "x:1 y:2" ...
Your structure can have fields of any type that operator >>(std::istream&is, const YourType&) can handle, and of types for which you ran fsfcgen. std::list and std::vector are also handled.
By default, the parser is very leniant: it accepts either a list of all the class fields in the correct order, or pairs of the form fieldname <separator> value, separator being empty, ':' or '='. It accepts all the fields on the same line, or one per line with the same indent. Substructures can be wrapped using a bracket block {}, or just indented differently.
The parser can be configured using keywords in the Doxygen commentary of your class. Either in the class description, or in the field descriptions. There are two types of options: boolean, or tri-stated. Booleans can be either true or false. Boolean option <opt> can be set to true by the keyword <opt>, enable<opt> or allow<opt>; it can be set to false by no<opt>, not<opt>, disable<opt>, or deny<opt>. Tri-stated options can have a value of ALLOW, REQUIRE or DENY.
- ALLOW means the parser will accept content both with and without the option.
- DENY means content with the option set will result in a parse exception.
- REQUIRE means content without the option will result in a parse exception.
They can be set by <opt> <val> (or <opt>:<val>). A specific value can also be set by using allow<opt>, require<opt>, or deny<opt>
The supported options are:
- optional : boolean, the field is optional, do not throw a parse exception if field is not set when the end of the structure is encountered.
- multipleWrite: boolean, allow multiple writes to the same field. This is set for list types to allow filling the list by multiple "key value" pairs.
- fieldName: tristated, controls wether the parser expects "key value" pairs or just the list of field values.
- terminator: tristated, controls wether the structure must be delimited by braces '{}', or xml tags.
- singleLine: tristated, controls wether the structure must be on a single line or spread one line per field.
- colonAfterFieldName: tristated, controls wether the field and value must be separated by a ':'.
- equalAfterFieldName: tristated, controls wether the field and value must be separated by a '='.
- xmlFieldName: tristated, controls wether field name must be a xml tag (which implies that a closing tag must be present)
- dashInList: tristated, all entries in a list are prefixed with a '-' followed by a space or a newline.
- ignoreIndent: boolean, completely ignore indentation while parsing struct. This is reserved for special cases, do not set this unless you know what you are doing.
The options are also used to control the output format: the output will use the format dictated by the options with a REQUIRE value.
Multiple examples are present in the samples and tests subdirectories of the libfsfc source release. To build the samples, type make samples -C tests as they are not built by default.
Here is a simple hypothetical experiment control structure:
///A point,parse options: singleLine fieldName:deny as this struct is simple
class Point
{
public:
float x;
float y;
};
///Class describing an algorithm
class Algorithm
{
public:
std::string name;
bool needsReloading; ///< Reload the module after each run?
std::string extraParameters; ///< extra parameters to pass, optional
};
class Experiment
{
public:
///name of the experiment
std::string name;
/// starting point
Point startingPoint;
/// algorithm to use
Algorithm algorithm;
///optional: frame numbers for which to log
std::list<int> logFrame;
};
The following texts will be correctly parsed by libfsfc
#comments start with '#' and spawn until end of line.
name="experiment 12" # strings can be quoted
startingPoint = 0 0
logFrame = 10 20 30
algorithm = # order does not matter if field name are given
name = "von schtroumpf"
needsReloading = 0
#notice the missing optional field
name: "experiment \"12\"" #escaping is supported
startingPoint: 0 0
algorithm: {
name "bucher"
needsReloading 1
extraParameters "hiiiiiiiiiiiii"
}
logFrame:
10
20
30
name experiment_12
startingPoint { 0 0}
algorithm { name:Voight-Kampf needsReloading:0}
logFrame 10 #std::list support multipleWrite by default.
logFrame 20
logFrame 30
Be careful, by default the parser is extremely leniant. Particularily, if the first encountered word is not the name of a field, the parser will try to parse the content as the list of field values in the declaration order. It is recommanded that you set stricter parsing options for all your classes (at least fieldName:require).
- Implement options to specify output format (right now output uses options in REQUIRE state).
- Dynamic options. Ie not per-structure, but per-parse-per-structure.
- Option to allow a value terminator.
- Better error reporting.
fsfcgen invokes Doxygen, in XML output mode. This XML is paresd by a perl script to produce a file of the form:
CLASS_BEGIN(classname)
FIELD(classname, field1name, field1type)
FIELD(classname, field2name, field2type)
CLASS_END(classname)
fsfc_internal.hh defines macros for each of those token, to declare a MetaClass containing the description of the class. This metaclass is capable of listing the class fields, their options, and to create instances of a metaclass for them. The parser in fsfc.cc uses the metaclass interface (called StructDesc) to guide itself during the parsing process.
Generated on Sat Dec 29 03:14:02 2007 for libfsfc by
1.5.4