damaris-backends/core/xml_states.h
2014-06-26 11:10:51 +00:00

163 lines
5.5 KiB
C++

/* **************************************************************************
Author: Achim Gaedke
Created: June 2004
****************************************************************************/
#ifndef XML_STATES_H
#define XML_STATES_H
#include "states.h"
#include "constants.h"
#include <expat.h>
#include <cstdio>
#include <xercesc/dom/DOMElement.hpp>
/**
\defgroup xmlstateinterface XML support for all state classes
\ingroup states
The state sequences consist of states and again sequences. A state is defined by a number of state_atom objects.
This definition results in a file with nested sections, that is parsed into a tree formed by the state objects.
The leaves of the tree are normaly state_atom objects. These state_atom objects define the state of a device.
An example for a sequence definition is:
\verbatim<?xml version="1.0" encoding="ISO-8859-1"?>
<sequent repeat="3">
<state time="3e-3">
<ttlout value="4"/>
<ttlout channel="2" state="0"/>
<analogout channel="1" f="1e6" p="0"/>
<analogout channel="2" f="1e6" p="90"/>
</state>
<sequent repeat="15">
<state time="3e-3">
<ttlout value="7"/>
<analogout channel="1" f="1e6" p="0"/>
<analogout channel="2" f="1e6" p="90"/>
</state>
<state time="1e-3">
<analogin f="5e6" s="4096"/>
<state/>
</sequent>
</sequent>\endverbatim
The first line of this code is a statement of xml conformity. (More about xml can be read at:
http://www.w3.org/TR/REC-xml .)
\n
The second line defines a new subsequence of states by using the tag \<sequent repeat="3"\>.
The "repeat" value 3 is the loop count. This line effects an instatiation of a state_sequent object.
All information will be collected in this branch, it is closed on the last line by \</sequent\>.
In this example the third line provides a %state tag corresponding to a state object.
So this also line specifies the duration of this state in seconds.
This section is closed with the eigth line containing \</state\>.
A xml document can contain only one top-level-element, that is called root or document element.
Applying the xml_state_reader it is not necessary to begin with a sequent element.
\n
A xml section (representing a state or sequence in our case) is opend by a tag with a name in angle braces like
\<sequent\> and is closed with an extra slash before the name \</sequent\>. Attributes can follow in the form name="value",
attributes must be quoted (single or double quotes). If such a section has no contents there is a short form with a slash
before the closing angle, e.g. \<ttlout value="7"/\>.
\n
Of course outside these tags, text can be supplied. By now, xml_state_reader ignores this text.
Inside a %state section the definition of the state is collected. Implemented are ttlout, analogout and
analogin. One element can occurr several times. How these states are merged is machine dependent.
So a state sequence is defined by <b>one sequent</b> section, containing again serval <b>state</b> or <b>sequent</b>
sections. The <b>state</b> sections must not contain other <b>state</b> sections or <b>sequent</b> sections.
*/
//@{
/**
\brief gains state sequence from an xml event stream
*/
class xml_state_reader {
state_atom* root;
std::list<state_atom*> pending_elements;
XML_Parser parser;
public:
/**
instantiates an expat xml parser object
*/
xml_state_reader();
/**
frees the parser object
*/
~xml_state_reader();
/**
\brief parses xml file containing sequences of states
the name of the file is the only parameter
\return returns tree of states or NULL if an parse error occured
*/
state_atom* read_from_file(const std::string& filename);
state_atom* read_from_dom(const XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* e) {
// to do work, work and work
return NULL;
}
/**
\brief parses a string containing sequences of states
\return returns tree of states or NULL if an parse error occured
*/
state_atom* read_from_string(const std::string& data);
/** \brief finds an attribute in the attributes array
\return returns the pointer to the attributes value or NULL if not in the array
*/
const XML_Char* search_attribute(const XML_Char** atts, const XML_Char* attr) const;
/**
\brief looks for an attribute with different names
the first alternative, that could be found is taken
\return returns a pointer to the attributes value or NULL if nothing approprate is found
*/
const XML_Char* search_attributes(const XML_Char** atts, ...) const;
/**
create new states from xml tags and their attributes
*/
state_atom* state_factory(const XML_Char* name, const XML_Char** atts) const;
/**
start tag callback for expat parser
*/
void start_element(const XML_Char* name,const XML_Char** atts);
/**
end tag callback for expat parser
*/
void end_element(const XML_Char* name);
};
/**
\ingroup states
the writer outputs states to xml files
takes care of formating
*/
class xml_state_writer {
public:
/// have a stack
std::list<state_atom*> pending_elements;
/// allow nice formating druing recursive operation
size_t indent_offset;
/// allow nice formating druing recursive operation
size_t indent_increase;
/// simple initialisation
xml_state_writer(){
indent_offset=0;
indent_increase=2;
};
/**
write states to a given output
if add_header is !=0 a full xml document is given
*/
int write_states(FILE* output, const state_atom& states_to_write, int add_header=0, int indent_size=0);
};
//@}
#endif