drop bayesian network representation
This commit is contained in:
parent
abb0410d07
commit
b28ee8fb3a
@ -5,8 +5,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "xmlParser/xmlParser.h"
|
||||
|
||||
#include "BayesBall.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
@ -19,9 +19,10 @@ struct ScheduleInfo
|
||||
{
|
||||
ScheduleInfo (DAGraphNode* n, bool vfp, bool vfc) :
|
||||
node(n), visitedFromParent(vfp), visitedFromChild(vfc) { }
|
||||
|
||||
DAGraphNode* node;
|
||||
bool visitedFromParent;
|
||||
bool visitedFromChild;
|
||||
bool visitedFromParent;
|
||||
bool visitedFromChild;
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "xmlParser/xmlParser.h"
|
||||
|
||||
#include "BayesNet.h"
|
||||
#include "Util.h"
|
||||
|
||||
@ -107,442 +105,3 @@ DAGraph::exportToGraphViz (const char* fileName)
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BayesNet::~BayesNet (void)
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
delete nodes_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNet::readFromBifFormat (const char* fileName)
|
||||
{
|
||||
XMLNode xMainNode = XMLNode::openFileHelper (fileName, "BIF");
|
||||
// only the first network is parsed, others are ignored
|
||||
XMLNode xNode = xMainNode.getChildNode ("NETWORK");
|
||||
unsigned nVars = xNode.nChildNode ("VARIABLE");
|
||||
for (unsigned i = 0; i < nVars; i++) {
|
||||
XMLNode var = xNode.getChildNode ("VARIABLE", i);
|
||||
if (string (var.getAttribute ("TYPE")) != "nature") {
|
||||
cerr << "error: only \"nature\" variables are supported" << endl;
|
||||
abort();
|
||||
}
|
||||
States states;
|
||||
string label = var.getChildNode("NAME").getText();
|
||||
unsigned range = var.nChildNode ("OUTCOME");
|
||||
for (unsigned j = 0; j < range; j++) {
|
||||
if (var.getChildNode("OUTCOME", j).getText() == 0) {
|
||||
stringstream ss;
|
||||
ss << j + 1;
|
||||
states.push_back (ss.str());
|
||||
} else {
|
||||
states.push_back (var.getChildNode("OUTCOME", j).getText());
|
||||
}
|
||||
}
|
||||
addNode (label, states);
|
||||
}
|
||||
|
||||
unsigned nDefs = xNode.nChildNode ("DEFINITION");
|
||||
if (nVars != nDefs) {
|
||||
cerr << "error: different number of variables and definitions" << endl;
|
||||
abort();
|
||||
}
|
||||
for (unsigned i = 0; i < nDefs; i++) {
|
||||
XMLNode def = xNode.getChildNode ("DEFINITION", i);
|
||||
string label = def.getChildNode("FOR").getText();
|
||||
BayesNode* node = getBayesNode (label);
|
||||
if (!node) {
|
||||
cerr << "error: unknow variable `" << label << "'" << endl;
|
||||
abort();
|
||||
}
|
||||
BnNodeSet parents;
|
||||
unsigned nParams = node->range();
|
||||
for (int j = 0; j < def.nChildNode ("GIVEN"); j++) {
|
||||
string parentLabel = def.getChildNode("GIVEN", j).getText();
|
||||
BayesNode* parentNode = getBayesNode (parentLabel);
|
||||
if (!parentNode) {
|
||||
cerr << "error: unknow variable `" << parentLabel << "'" << endl;
|
||||
abort();
|
||||
}
|
||||
nParams *= parentNode->range();
|
||||
parents.push_back (parentNode);
|
||||
}
|
||||
node->setParents (parents);
|
||||
unsigned count = 0;
|
||||
Params params (nParams);
|
||||
stringstream s (def.getChildNode("TABLE").getText());
|
||||
while (!s.eof() && count < nParams) {
|
||||
s >> params[count];
|
||||
count ++;
|
||||
}
|
||||
if (count != nParams) {
|
||||
cerr << "error: invalid number of parameters " ;
|
||||
cerr << "for variable `" << label << "'" << endl;
|
||||
abort();
|
||||
}
|
||||
params = reorderParameters (params, node->range());
|
||||
if (Globals::logDomain) {
|
||||
Util::toLog (params);
|
||||
}
|
||||
node->setParams (params);
|
||||
}
|
||||
setIndexes();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BayesNode*
|
||||
BayesNet::addNode (BayesNode* n)
|
||||
{
|
||||
varMap_.insert (make_pair (n->varId(), nodes_.size()));
|
||||
nodes_.push_back (n);
|
||||
return nodes_.back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BayesNode*
|
||||
BayesNet::addNode (string label, const States& states)
|
||||
{
|
||||
VarId vid = nodes_.size();
|
||||
varMap_.insert (make_pair (vid, nodes_.size()));
|
||||
GraphicalModel::addVariableInformation (vid, label, states);
|
||||
BayesNode* node = new BayesNode (VarNode (vid, states.size()));
|
||||
nodes_.push_back (node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BayesNode*
|
||||
BayesNet::getBayesNode (VarId vid) const
|
||||
{
|
||||
IndexMap::const_iterator it = varMap_.find (vid);
|
||||
if (it == varMap_.end()) {
|
||||
return 0;
|
||||
} else {
|
||||
return nodes_[it->second];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BayesNode*
|
||||
BayesNet::getBayesNode (string label) const
|
||||
{
|
||||
BayesNode* node = 0;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (nodes_[i]->label() == label) {
|
||||
node = nodes_[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VarNode*
|
||||
BayesNet::getVariableNode (VarId vid) const
|
||||
{
|
||||
BayesNode* node = getBayesNode (vid);
|
||||
assert (node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VarNodes
|
||||
BayesNet::getVariableNodes (void) const
|
||||
{
|
||||
VarNodes vars;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
vars.push_back (nodes_[i]);
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const BnNodeSet&
|
||||
BayesNet::getBayesNodes (void) const
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
BayesNet::nrNodes (void) const
|
||||
{
|
||||
return nodes_.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BnNodeSet
|
||||
BayesNet::getRootNodes (void) const
|
||||
{
|
||||
BnNodeSet roots;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (nodes_[i]->isRoot()) {
|
||||
roots.push_back (nodes_[i]);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BnNodeSet
|
||||
BayesNet::getLeafNodes (void) const
|
||||
{
|
||||
BnNodeSet leafs;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (nodes_[i]->isLeaf()) {
|
||||
leafs.push_back (nodes_[i]);
|
||||
}
|
||||
}
|
||||
return leafs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNet::isPolyTree (void) const
|
||||
{
|
||||
return !containsUndirectedCycle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNet::setIndexes (void)
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
nodes_[i]->setIndex (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNet::printGraphicalModel (void) const
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
cout << *nodes_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNet::exportToGraphViz (const char* fileName,
|
||||
bool showNeighborless,
|
||||
const VarIds& highlightVarIds) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "BayesNet::exportToDotFile()" << endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
out << "digraph {" << endl;
|
||||
out << "ranksep=1" << endl;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (showNeighborless || nodes_[i]->hasNeighbors()) {
|
||||
out << nodes_[i]->varId() ;
|
||||
if (nodes_[i]->hasEvidence()) {
|
||||
out << " [" ;
|
||||
out << "label=\"" << nodes_[i]->label() << "\"," ;
|
||||
out << "style=filled, fillcolor=yellow" ;
|
||||
out << "]" ;
|
||||
} else {
|
||||
out << " [" ;
|
||||
out << "label=\"" << nodes_[i]->label() << "\"" ;
|
||||
out << "]" ;
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < highlightVarIds.size(); i++) {
|
||||
BayesNode* node = getBayesNode (highlightVarIds[i]);
|
||||
if (node) {
|
||||
out << node->varId() ;
|
||||
out << " [shape=box3d]" << endl;
|
||||
} else {
|
||||
cout << "error: invalid variable id: " << highlightVarIds[i] << endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
const BnNodeSet& childs = nodes_[i]->getChilds();
|
||||
for (unsigned j = 0; j < childs.size(); j++) {
|
||||
out << nodes_[i]->varId() << " -> " << childs[j]->varId() << " [style=bold]" << endl ;
|
||||
}
|
||||
}
|
||||
|
||||
out << "}" << endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNet::exportToBifFormat (const char* fileName) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if(!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "BayesNet::exportToBifFile()" << endl;
|
||||
abort();
|
||||
}
|
||||
out << "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>" << endl;
|
||||
out << "<BIF VERSION=\"0.3\">" << endl;
|
||||
out << "<NETWORK>" << endl;
|
||||
out << "<NAME>" << fileName << "</NAME>" << endl << endl;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
out << "<VARIABLE TYPE=\"nature\">" << endl;
|
||||
out << "\t<NAME>" << nodes_[i]->label() << "</NAME>" << endl;
|
||||
const States& states = nodes_[i]->states();
|
||||
for (unsigned j = 0; j < states.size(); j++) {
|
||||
out << "\t<OUTCOME>" << states[j] << "</OUTCOME>" << endl;
|
||||
}
|
||||
out << "</VARIABLE>" << endl << endl;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
out << "<DEFINITION>" << endl;
|
||||
out << "\t<FOR>" << nodes_[i]->label() << "</FOR>" << endl;
|
||||
const BnNodeSet& parents = nodes_[i]->getParents();
|
||||
for (unsigned j = 0; j < parents.size(); j++) {
|
||||
out << "\t<GIVEN>" << parents[j]->label();
|
||||
out << "</GIVEN>" << endl;
|
||||
}
|
||||
Params params = revertParameterReorder (
|
||||
nodes_[i]->params(), nodes_[i]->range());
|
||||
out << "\t<TABLE>" ;
|
||||
for (unsigned j = 0; j < params.size(); j++) {
|
||||
out << " " << params[j];
|
||||
}
|
||||
out << " </TABLE>" << endl;
|
||||
out << "</DEFINITION>" << endl << endl;
|
||||
}
|
||||
out << "</NETWORK>" << endl;
|
||||
out << "</BIF>" << endl << endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNet::containsUndirectedCycle (void) const
|
||||
{
|
||||
vector<bool> visited (nodes_.size(), false);
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
int v = nodes_[i]->getIndex();
|
||||
if (!visited[v]) {
|
||||
if (containsUndirectedCycle (v, -1, visited)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNet::containsUndirectedCycle (int v, int p, vector<bool>& visited) const
|
||||
{
|
||||
visited[v] = true;
|
||||
vector<int> adjacencies = getAdjacentNodes (v);
|
||||
for (unsigned i = 0; i < adjacencies.size(); i++) {
|
||||
int w = adjacencies[i];
|
||||
if (!visited[w]) {
|
||||
if (containsUndirectedCycle (w, v, visited)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (visited[w] && w != p) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // no cycle detected in this component
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<int>
|
||||
BayesNet::getAdjacentNodes (int v) const
|
||||
{
|
||||
vector<int> adjacencies;
|
||||
const BnNodeSet& parents = nodes_[v]->getParents();
|
||||
const BnNodeSet& childs = nodes_[v]->getChilds();
|
||||
for (unsigned i = 0; i < parents.size(); i++) {
|
||||
adjacencies.push_back (parents[i]->getIndex());
|
||||
}
|
||||
for (unsigned i = 0; i < childs.size(); i++) {
|
||||
adjacencies.push_back (childs[i]->getIndex());
|
||||
}
|
||||
return adjacencies;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BayesNet::reorderParameters (const Params& params, unsigned dsize) const
|
||||
{
|
||||
// the interchange format for bayesian networks keeps the probabilities
|
||||
// in the following order:
|
||||
// p(a1|b1,c1) p(a2|b1,c1) p(a1|b1,c2) p(a2|b1,c2) p(a1|b2,c1) p(a2|b2,c1)
|
||||
// p(a1|b2,c2) p(a2|b2,c2).
|
||||
//
|
||||
// however, in clpbn we keep the probabilities in this order:
|
||||
// p(a1|b1,c1) p(a1|b1,c2) p(a1|b2,c1) p(a1|b2,c2) p(a2|b1,c1) p(a2|b1,c2)
|
||||
// p(a2|b2,c1) p(a2|b2,c2).
|
||||
unsigned count = 0;
|
||||
unsigned rowSize = params.size() / dsize;
|
||||
Params reordered;
|
||||
while (reordered.size() < params.size()) {
|
||||
unsigned idx = count;
|
||||
for (unsigned i = 0; i < rowSize; i++) {
|
||||
reordered.push_back (params[idx]);
|
||||
idx += dsize ;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return reordered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BayesNet::revertParameterReorder (const Params& params, unsigned dsize) const
|
||||
{
|
||||
unsigned count = 0;
|
||||
unsigned rowSize = params.size() / dsize;
|
||||
Params reordered;
|
||||
while (reordered.size() < params.size()) {
|
||||
unsigned idx = count;
|
||||
for (unsigned i = 0; i < dsize; i++) {
|
||||
reordered.push_back (params[idx]);
|
||||
idx += rowSize;
|
||||
}
|
||||
count ++;
|
||||
}
|
||||
return reordered;
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@
|
||||
#include <map>
|
||||
|
||||
#include "GraphicalModel.h"
|
||||
#include "BayesNode.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
class VarNode;
|
||||
|
||||
class DAGraphNode : public VarNode
|
||||
@ -87,64 +85,4 @@ class DAGraph
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BayesNet : public GraphicalModel
|
||||
{
|
||||
public:
|
||||
BayesNet (void) { };
|
||||
|
||||
~BayesNet (void);
|
||||
|
||||
void readFromBifFormat (const char*);
|
||||
|
||||
BayesNode* addNode (BayesNode*);
|
||||
|
||||
BayesNode* addNode (string, const States&);
|
||||
|
||||
BayesNode* getBayesNode (VarId) const;
|
||||
|
||||
BayesNode* getBayesNode (string) const;
|
||||
|
||||
VarNode* getVariableNode (VarId) const;
|
||||
|
||||
VarNodes getVariableNodes (void) const;
|
||||
|
||||
const BnNodeSet& getBayesNodes (void) const;
|
||||
|
||||
unsigned nrNodes (void) const;
|
||||
|
||||
BnNodeSet getRootNodes (void) const;
|
||||
|
||||
BnNodeSet getLeafNodes (void) const;
|
||||
|
||||
bool isPolyTree (void) const;
|
||||
|
||||
void setIndexes (void);
|
||||
|
||||
void printGraphicalModel (void) const;
|
||||
|
||||
void exportToGraphViz (const char*, bool = true,
|
||||
const VarIds& = VarIds()) const;
|
||||
|
||||
void exportToBifFormat (const char*) const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (BayesNet);
|
||||
|
||||
bool containsUndirectedCycle (void) const;
|
||||
|
||||
bool containsUndirectedCycle (int, int, vector<bool>&)const;
|
||||
|
||||
vector<int> getAdjacentNodes (int) const;
|
||||
|
||||
Params reorderParameters (const Params&, unsigned) const;
|
||||
|
||||
Params revertParameterReorder (const Params&, unsigned) const;
|
||||
|
||||
BnNodeSet nodes_;
|
||||
|
||||
typedef unordered_map<unsigned, unsigned> IndexMap;
|
||||
IndexMap varMap_;
|
||||
};
|
||||
|
||||
#endif // HORUS_BAYESNET_H
|
||||
|
@ -1,247 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "BayesNode.h"
|
||||
|
||||
|
||||
void
|
||||
BayesNode::setParams (const Params& params)
|
||||
{
|
||||
params_ = params;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNode::setParents (const BnNodeSet& parents)
|
||||
{
|
||||
parents_ = parents;
|
||||
for (unsigned int i = 0; i < parents.size(); i++) {
|
||||
parents[i]->addChild (this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesNode::addChild (BayesNode* node)
|
||||
{
|
||||
childs_.push_back (node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BayesNode::getRow (int rowIndex) const
|
||||
{
|
||||
int rowSize = getRowSize();
|
||||
int offset = rowSize * rowIndex;
|
||||
Params row (rowSize);
|
||||
for (int i = 0; i < rowSize; i++) {
|
||||
row[i] = params_[offset + i] ;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNode::isRoot (void)
|
||||
{
|
||||
return getParents().empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNode::isLeaf (void)
|
||||
{
|
||||
return getChilds().empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BayesNode::hasNeighbors (void) const
|
||||
{
|
||||
return childs_.size() != 0 || parents_.size() != 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BayesNode::getCptSize (void)
|
||||
{
|
||||
return params_.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BayesNode::indexOfParent (const BayesNode* parent) const
|
||||
{
|
||||
for (unsigned int i = 0; i < parents_.size(); i++) {
|
||||
if (parents_[i] == parent) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
BayesNode::cptEntryToString (
|
||||
int row,
|
||||
const vector<unsigned>& stateConf) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "p(" ;
|
||||
ss << states()[row];
|
||||
if (parents_.size() > 0) {
|
||||
ss << "|" ;
|
||||
for (unsigned int i = 0; i < stateConf.size(); i++) {
|
||||
if (i != 0) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << parents_[i]->states()[stateConf[i]];
|
||||
}
|
||||
}
|
||||
ss << ")" ;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<string>
|
||||
BayesNode::getDomainHeaders (void) const
|
||||
{
|
||||
unsigned nParents = parents_.size();
|
||||
unsigned rowSize = getRowSize();
|
||||
unsigned nReps = 1;
|
||||
vector<string> headers (rowSize);
|
||||
for (int i = nParents - 1; i >= 0; i--) {
|
||||
States states = parents_[i]->states();
|
||||
unsigned index = 0;
|
||||
while (index < rowSize) {
|
||||
for (unsigned j = 0; j < parents_[i]->range(); j++) {
|
||||
for (unsigned r = 0; r < nReps; r++) {
|
||||
if (headers[index] != "") {
|
||||
headers[index] = states[j] + "," + headers[index];
|
||||
} else {
|
||||
headers[index] = states[j];
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
nReps *= parents_[i]->range();
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ostream&
|
||||
operator << (ostream& o, const BayesNode& node)
|
||||
{
|
||||
o << "variable " << node.getIndex() << endl;
|
||||
o << "Var Id: " << node.varId() << endl;
|
||||
o << "Label: " << node.label() << endl;
|
||||
|
||||
o << "Evidence: " ;
|
||||
if (node.hasEvidence()) {
|
||||
o << node.getEvidence();
|
||||
}
|
||||
else {
|
||||
o << "no" ;
|
||||
}
|
||||
o << endl;
|
||||
|
||||
o << "Parents: " ;
|
||||
const BnNodeSet& parents = node.getParents();
|
||||
if (parents.size() != 0) {
|
||||
for (unsigned int i = 0; i < parents.size() - 1; i++) {
|
||||
o << parents[i]->label() << ", " ;
|
||||
}
|
||||
o << parents[parents.size() - 1]->label();
|
||||
}
|
||||
o << endl;
|
||||
|
||||
o << "Childs: " ;
|
||||
const BnNodeSet& childs = node.getChilds();
|
||||
if (childs.size() != 0) {
|
||||
for (unsigned int i = 0; i < childs.size() - 1; i++) {
|
||||
o << childs[i]->label() << ", " ;
|
||||
}
|
||||
o << childs[childs.size() - 1]->label();
|
||||
}
|
||||
o << endl;
|
||||
|
||||
o << "Domain: " ;
|
||||
States states = node.states();
|
||||
for (unsigned int i = 0; i < states.size() - 1; i++) {
|
||||
o << states[i] << ", " ;
|
||||
}
|
||||
if (states.size() != 0) {
|
||||
o << states[states.size() - 1];
|
||||
}
|
||||
o << endl;
|
||||
|
||||
// min width of first column
|
||||
const unsigned int MIN_DOMAIN_WIDTH = 4;
|
||||
// min width of following columns
|
||||
const unsigned int MIN_COMBO_WIDTH = 12;
|
||||
|
||||
unsigned int domainWidth = states[0].length();
|
||||
for (unsigned int i = 1; i < states.size(); i++) {
|
||||
if (states[i].length() > domainWidth) {
|
||||
domainWidth = states[i].length();
|
||||
}
|
||||
}
|
||||
domainWidth = (domainWidth < MIN_DOMAIN_WIDTH)
|
||||
? MIN_DOMAIN_WIDTH
|
||||
: domainWidth;
|
||||
|
||||
o << left << setw (domainWidth) << "cpt" << right;
|
||||
|
||||
vector<int> widths;
|
||||
int lineWidth = domainWidth;
|
||||
vector<string> headers = node.getDomainHeaders();
|
||||
|
||||
if (!headers.empty()) {
|
||||
for (unsigned int i = 0; i < headers.size(); i++) {
|
||||
unsigned int len = headers[i].length();
|
||||
int w = (len < MIN_COMBO_WIDTH) ? MIN_COMBO_WIDTH : len;
|
||||
widths.push_back (w);
|
||||
o << setw (w) << headers[i];
|
||||
lineWidth += w;
|
||||
}
|
||||
o << endl;
|
||||
} else {
|
||||
cout << endl;
|
||||
widths.push_back (domainWidth);
|
||||
lineWidth += MIN_COMBO_WIDTH;
|
||||
}
|
||||
|
||||
for (int i = 0; i < lineWidth; i++) {
|
||||
o << "-" ;
|
||||
}
|
||||
o << endl;
|
||||
|
||||
for (unsigned int i = 0; i < states.size(); i++) {
|
||||
Params row = node.getRow (i);
|
||||
o << left << setw (domainWidth) << states[i] << right;
|
||||
for (unsigned j = 0; j < node.getRowSize(); j++) {
|
||||
o << setw (widths[j]) << row[j];
|
||||
}
|
||||
o << endl;
|
||||
}
|
||||
o << endl;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
#ifndef HORUS_BAYESNODE_H
|
||||
#define HORUS_BAYESNODE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "VarNode.h"
|
||||
#include "Horus.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class BayesNode : public VarNode
|
||||
{
|
||||
public:
|
||||
|
||||
BayesNode (const VarNode& v) : VarNode (v) { }
|
||||
|
||||
BayesNode (const BayesNode* n) :
|
||||
VarNode (n->varId(), n->range(), n->getEvidence()),
|
||||
params_(n->params()), distId_(n->distId()) { }
|
||||
|
||||
BayesNode (VarId vid, unsigned range, int ev,
|
||||
const Params& ps, unsigned id)
|
||||
: VarNode (vid, range, ev) , params_(ps), distId_(id) { }
|
||||
|
||||
const BnNodeSet& getParents (void) const { return parents_; }
|
||||
|
||||
const BnNodeSet& getChilds (void) const { return childs_; }
|
||||
|
||||
const Params& params (void) const { return params_; }
|
||||
|
||||
unsigned distId (void) const { return distId_; }
|
||||
|
||||
unsigned getRowSize (void) const
|
||||
{
|
||||
return params_.size() / range();
|
||||
}
|
||||
|
||||
double getProbability (int row, unsigned col)
|
||||
{
|
||||
int idx = (row * getRowSize()) + col;
|
||||
return params_[idx];
|
||||
}
|
||||
|
||||
void setParams (const Params& params);
|
||||
|
||||
void setParents (const BnNodeSet&);
|
||||
|
||||
void addChild (BayesNode*);
|
||||
|
||||
const Params& getParameters (void);
|
||||
|
||||
Params getRow (int) const;
|
||||
|
||||
bool isRoot (void);
|
||||
|
||||
bool isLeaf (void);
|
||||
|
||||
bool hasNeighbors (void) const;
|
||||
|
||||
int getCptSize (void);
|
||||
|
||||
int indexOfParent (const BayesNode*) const;
|
||||
|
||||
string cptEntryToString (int, const vector<unsigned>&) const;
|
||||
|
||||
friend ostream& operator << (ostream&, const BayesNode&);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (BayesNode);
|
||||
|
||||
States getDomainHeaders (void) const;
|
||||
|
||||
BnNodeSet parents_;
|
||||
BnNodeSet childs_;
|
||||
Params params_;
|
||||
unsigned distId_;
|
||||
};
|
||||
|
||||
#endif // HORUS_BAYESNODE_H
|
||||
|
@ -37,39 +37,6 @@ FactorGraph::FactorGraph (const FactorGraph& fg)
|
||||
|
||||
|
||||
|
||||
FactorGraph::FactorGraph (const BayesNet& bn)
|
||||
{
|
||||
const BnNodeSet& nodes = bn.getBayesNodes();
|
||||
for (unsigned i = 0; i < nodes.size(); i++) {
|
||||
FgVarNode* varNode = new FgVarNode (nodes[i]);
|
||||
addVariable (varNode);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < nodes.size(); i++) {
|
||||
const BnNodeSet& parents = nodes[i]->getParents();
|
||||
if (!(nodes[i]->hasEvidence() && parents.size() == 0)) {
|
||||
VarNodes neighs;
|
||||
neighs.push_back (varNodes_[nodes[i]->getIndex()]);
|
||||
for (unsigned j = 0; j < parents.size(); j++) {
|
||||
neighs.push_back (varNodes_[parents[j]->getIndex()]);
|
||||
}
|
||||
FgFacNode* fn = new FgFacNode (
|
||||
new Factor (neighs, nodes[i]->params(), nodes[i]->distId()));
|
||||
if (orderFactorVariables) {
|
||||
sort (neighs.begin(), neighs.end(), CompVarId());
|
||||
fn->factor()->reorderAccordingVarIds();
|
||||
}
|
||||
addFactor (fn);
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
addEdge (fn, static_cast<FgVarNode*> (neighs[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
setIndexes();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::readFromUaiFormat (const char* fileName)
|
||||
{
|
||||
|
@ -97,8 +97,6 @@ class FactorGraph : public GraphicalModel
|
||||
|
||||
FactorGraph (const FactorGraph&);
|
||||
|
||||
FactorGraph (const BayesNet&);
|
||||
|
||||
~FactorGraph (void);
|
||||
|
||||
const FgVarSet& getVarNodes (void) const { return varNodes_; }
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <YapInterface.h>
|
||||
|
||||
#include "ParfactorList.h"
|
||||
#include "BayesNet.h"
|
||||
#include "FactorGraph.h"
|
||||
#include "FoveSolver.h"
|
||||
#include "VarElimSolver.h"
|
||||
@ -469,6 +468,8 @@ setParfactorsParams (void)
|
||||
int
|
||||
setBayesNetParams (void)
|
||||
{
|
||||
// TODO FIXME
|
||||
/*
|
||||
BayesNet* bn = (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
|
||||
YAP_Term distList = YAP_ARG2;
|
||||
unordered_map<unsigned, Params> paramsMap;
|
||||
@ -484,6 +485,7 @@ setBayesNetParams (void)
|
||||
assert (Util::contains (paramsMap, nodes[i]->distId()));
|
||||
nodes[i]->setParams (paramsMap[nodes[i]->distId()]);
|
||||
}
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -601,7 +603,7 @@ setHorusFlag (void)
|
||||
int
|
||||
freeGroundNetwork (void)
|
||||
{
|
||||
delete (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
|
||||
delete (FactorGraph*) YAP_IntOfTerm (YAP_ARG1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,6 @@ HEADERS = \
|
||||
$(srcdir)/GraphicalModel.h \
|
||||
$(srcdir)/BayesNet.h \
|
||||
$(srcdir)/BayesBall.h \
|
||||
$(srcdir)/BayesNode.h \
|
||||
$(srcdir)/ElimGraph.h \
|
||||
$(srcdir)/FactorGraph.h \
|
||||
$(srcdir)/Factor.h \
|
||||
@ -68,13 +67,11 @@ HEADERS = \
|
||||
$(srcdir)/LiftedUtils.h \
|
||||
$(srcdir)/TinySet.h \
|
||||
$(srcdir)/Util.h \
|
||||
$(srcdir)/Horus.h \
|
||||
$(srcdir)/xmlParser/xmlParser.h
|
||||
$(srcdir)/Horus.h
|
||||
|
||||
CPP_SOURCES = \
|
||||
$(srcdir)/BayesNet.cpp \
|
||||
$(srcdir)/BayesBall.cpp \
|
||||
$(srcdir)/BayesNode.cpp \
|
||||
$(srcdir)/ElimGraph.cpp \
|
||||
$(srcdir)/FactorGraph.cpp \
|
||||
$(srcdir)/Factor.cpp \
|
||||
@ -93,13 +90,11 @@ CPP_SOURCES = \
|
||||
$(srcdir)/LiftedUtils.cpp \
|
||||
$(srcdir)/Util.cpp \
|
||||
$(srcdir)/HorusYap.cpp \
|
||||
$(srcdir)/HorusCli.cpp \
|
||||
$(srcdir)/xmlParser/xmlParser.cpp
|
||||
$(srcdir)/HorusCli.cpp
|
||||
|
||||
OBJS = \
|
||||
BayesNet.o \
|
||||
BayesBall.o \
|
||||
BayesNode.o \
|
||||
ElimGraph.o \
|
||||
FactorGraph.o \
|
||||
Factor.o \
|
||||
@ -122,7 +117,6 @@ OBJS = \
|
||||
HCLI_OBJS = \
|
||||
BayesNet.o \
|
||||
BayesBall.o \
|
||||
BayesNode.o \
|
||||
ElimGraph.o \
|
||||
FactorGraph.o \
|
||||
Factor.o \
|
||||
@ -140,7 +134,6 @@ HCLI_OBJS = \
|
||||
ParfactorList.o \
|
||||
LiftedUtils.o \
|
||||
Util.o \
|
||||
xmlParser/xmlParser.o \
|
||||
HorusCli.o
|
||||
|
||||
SOBJS=horus.@SO@
|
||||
@ -153,10 +146,6 @@ all: $(SOBJS) hcli
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
|
||||
xmlParser/xmlParser.o : $(srcdir)/xmlParser/xmlParser.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
|
||||
@DO_SECOND_LD@horus.@SO@: $(OBJS)
|
||||
@DO_SECOND_LD@ @SHLIB_CXX_LD@ -o horus.@SO@ $(OBJS) @EXTRA_LIBS_FOR_SWIDLLS@
|
||||
|
||||
@ -170,7 +159,7 @@ install: all
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK hcli xmlParser/*.o
|
||||
rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK hcli
|
||||
|
||||
|
||||
erase_dots:
|
||||
|
@ -1,241 +0,0 @@
|
||||
Aladdin Free Public License
|
||||
(Version 8, November 18, 1999)
|
||||
|
||||
Copyright (C) 1994, 1995, 1997, 1998, 1999 Aladdin Enterprises,
|
||||
Menlo Park, California, U.S.A. All rights reserved.
|
||||
|
||||
*NOTE:* This License is not the same as any of the GNU Licenses
|
||||
<http://www.gnu.org/copyleft/gpl.html> published by the Free
|
||||
Software Foundation <http://www.gnu.org/>. Its terms are
|
||||
substantially different from those of the GNU Licenses. If you are
|
||||
familiar with the GNU Licenses, please read this license with extra
|
||||
care.
|
||||
|
||||
Aladdin Enterprises hereby grants to anyone the permission to apply this
|
||||
License to their own work, as long as the entire License (including the
|
||||
above notices and this paragraph) is copied with no changes, additions,
|
||||
or deletions except for changing the first paragraph of Section 0 to
|
||||
include a suitable description of the work to which the license is being
|
||||
applied and of the person or entity that holds the copyright in the
|
||||
work, and, if the License is being applied to a work created in a
|
||||
country other than the United States, replacing the first paragraph of
|
||||
Section 6 with an appropriate reference to the laws of the appropriate
|
||||
country.
|
||||
|
||||
|
||||
0. Subject Matter
|
||||
|
||||
This License applies to the computer program known as "XMLParser library".
|
||||
The "Program", below, refers to such program. The Program
|
||||
is a copyrighted work whose copyright is held by Frank Vanden Berghen
|
||||
(the "Licensor").
|
||||
|
||||
A "work based on the Program" means either the Program or any derivative
|
||||
work of the Program, as defined in the United States Copyright Act of
|
||||
1976, such as a translation or a modification.
|
||||
|
||||
* BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY WORK BASED ON THE
|
||||
PROGRAM), YOU INDICATE YOUR ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL
|
||||
ITS TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR MODIFYING THE
|
||||
PROGRAM OR WORKS BASED ON IT. NOTHING OTHER THAN THIS LICENSE GRANTS YOU
|
||||
PERMISSION TO MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE WORKS.
|
||||
THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU DO NOT ACCEPT THESE TERMS
|
||||
AND CONDITIONS, DO NOT MODIFY OR DISTRIBUTE THE PROGRAM. *
|
||||
|
||||
|
||||
1. Licenses.
|
||||
|
||||
Licensor hereby grants you the following rights, provided that you
|
||||
comply with all of the restrictions set forth in this License and
|
||||
provided, further, that you distribute an unmodified copy of this
|
||||
License with the Program:
|
||||
|
||||
(a)
|
||||
You may copy and distribute literal (i.e., verbatim) copies of the
|
||||
Program's source code as you receive it throughout the world, in any
|
||||
medium.
|
||||
(b)
|
||||
You may modify the Program, create works based on the Program and
|
||||
distribute copies of such throughout the world, in any medium.
|
||||
|
||||
|
||||
2. Restrictions.
|
||||
|
||||
This license is subject to the following restrictions:
|
||||
|
||||
(a)
|
||||
Distribution of the Program or any work based on the Program by a
|
||||
commercial organization to any third party is prohibited if any
|
||||
payment is made in connection with such distribution, whether
|
||||
directly (as in payment for a copy of the Program) or indirectly (as
|
||||
in payment for some service related to the Program, or payment for
|
||||
some product or service that includes a copy of the Program "without
|
||||
charge"; these are only examples, and not an exhaustive enumeration
|
||||
of prohibited activities). The following methods of distribution
|
||||
involving payment shall not in and of themselves be a violation of
|
||||
this restriction:
|
||||
|
||||
(i)
|
||||
Posting the Program on a public access information storage and
|
||||
retrieval service for which a fee is received for retrieving
|
||||
information (such as an on-line service), provided that the fee
|
||||
is not content-dependent (i.e., the fee would be the same for
|
||||
retrieving the same volume of information consisting of random
|
||||
data) and that access to the service and to the Program is
|
||||
available independent of any other product or service. An
|
||||
example of a service that does not fall under this section is an
|
||||
on-line service that is operated by a company and that is only
|
||||
available to customers of that company. (This is not an
|
||||
exhaustive enumeration.)
|
||||
(ii)
|
||||
Distributing the Program on removable computer-readable media,
|
||||
provided that the files containing the Program are reproduced
|
||||
entirely and verbatim on such media, that all information on
|
||||
such media be redistributable for non-commercial purposes
|
||||
without charge, and that such media are distributed by
|
||||
themselves (except for accompanying documentation) independent
|
||||
of any other product or service. Examples of such media include
|
||||
CD-ROM, magnetic tape, and optical storage media. (This is not
|
||||
intended to be an exhaustive list.) An example of a distribution
|
||||
that does not fall under this section is a CD-ROM included in a
|
||||
book or magazine. (This is not an exhaustive enumeration.)
|
||||
|
||||
(b)
|
||||
Activities other than copying, distribution and modification of the
|
||||
Program are not subject to this License and they are outside its
|
||||
scope. Functional use (running) of the Program is not restricted,
|
||||
and any output produced through the use of the Program is subject to
|
||||
this license only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
(c)
|
||||
You must meet all of the following conditions with respect to any
|
||||
work that you distribute or publish that in whole or in part
|
||||
contains or is derived from the Program or any part thereof ("the
|
||||
Work"):
|
||||
|
||||
(i)
|
||||
If you have modified the Program, you must cause the Work to
|
||||
carry prominent notices stating that you have modified the
|
||||
Program's files and the date of any change. In each source file
|
||||
that you have modified, you must include a prominent notice that
|
||||
you have modified the file, including your name, your e-mail
|
||||
address (if any), and the date and purpose of the change;
|
||||
(ii)
|
||||
You must cause the Work to be licensed as a whole and at no
|
||||
charge to all third parties under the terms of this License;
|
||||
(iii)
|
||||
If the Work normally reads commands interactively when run, you
|
||||
must cause it, at each time the Work commences operation, to
|
||||
print or display an announcement including an appropriate
|
||||
copyright notice and a notice that there is no warranty (or
|
||||
else, saying that you provide a warranty). Such notice must also
|
||||
state that users may redistribute the Work only under the
|
||||
conditions of this License and tell the user how to view the
|
||||
copy of this License included with the Work. (Exceptions: if the
|
||||
Program is interactive but normally prints or displays such an
|
||||
announcement only at the request of a user, such as in an "About
|
||||
box", the Work is required to print or display the notice only
|
||||
under the same circumstances; if the Program itself is
|
||||
interactive but does not normally print such an announcement,
|
||||
the Work is not required to print an announcement.);
|
||||
(iv)
|
||||
You must accompany the Work with the complete corresponding
|
||||
machine-readable source code, delivered on a medium customarily
|
||||
used for software interchange. The source code for a work means
|
||||
the preferred form of the work for making modifications to it.
|
||||
For an executable work, complete source code means all the
|
||||
source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control
|
||||
compilation and installation of the executable code. If you
|
||||
distribute with the Work any component that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system
|
||||
on which the executable runs, you must also distribute the
|
||||
source code of that component if you have it and are allowed to
|
||||
do so;
|
||||
(v)
|
||||
If you distribute any written or printed material at all with
|
||||
the Work, such material must include either a written copy of
|
||||
this License, or a prominent written indication that the Work is
|
||||
covered by this License and written instructions for printing
|
||||
and/or displaying the copy of the License on the distribution
|
||||
medium;
|
||||
(vi)
|
||||
You may not impose any further restrictions on the recipient's
|
||||
exercise of the rights granted herein.
|
||||
|
||||
If distribution of executable or object code is made by offering the
|
||||
equivalent ability to copy from a designated place, then offering
|
||||
equivalent ability to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source code along with the object code.
|
||||
|
||||
|
||||
3. Reservation of Rights.
|
||||
|
||||
No rights are granted to the Program except as expressly set forth
|
||||
herein. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt otherwise
|
||||
to copy, modify, sublicense or distribute the Program is void, and will
|
||||
automatically terminate your rights under this License. However, parties
|
||||
who have received copies, or rights, from you under this License will
|
||||
not have their licenses terminated so long as such parties remain in
|
||||
full compliance.
|
||||
|
||||
|
||||
4. Other Restrictions.
|
||||
|
||||
If the distribution and/or use of the Program is restricted in certain
|
||||
countries for any reason, Licensor may add an explicit geographical
|
||||
distribution limitation excluding those countries, so that distribution
|
||||
is permitted only in or among countries not thus excluded. In such case,
|
||||
this License incorporates the limitation as if written in the body of
|
||||
this License.
|
||||
|
||||
|
||||
5. Limitations.
|
||||
|
||||
* THE PROGRAM IS PROVIDED TO YOU "AS IS," WITHOUT WARRANTY. THERE IS NO
|
||||
WARRANTY FOR THE PROGRAM, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
|
||||
YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION. *
|
||||
|
||||
* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL LICENSOR, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
|
||||
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS
|
||||
OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
|
||||
THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES. *
|
||||
|
||||
|
||||
6. General.
|
||||
|
||||
This License is governed by the laws of Belgium., excluding choice of
|
||||
law rules.
|
||||
|
||||
If any part of this License is found to be in conflict with the law,
|
||||
that part shall be interpreted in its broadest meaning consistent with
|
||||
the law, and no other parts of the License shall be affected.
|
||||
|
||||
For United States Government users, the Program is provided with
|
||||
*RESTRICTED RIGHTS*. If you are a unit or agency of the United States
|
||||
Government or are acquiring the Program for any such unit or agency, the
|
||||
following apply:
|
||||
|
||||
If the unit or agency is the Department of Defense ("DOD"), the
|
||||
Program and its documentation are classified as "commercial computer
|
||||
software" and "commercial computer software documentation"
|
||||
respectively and, pursuant to DFAR Section 227.7202, the Government
|
||||
is acquiring the Program and its documentation in accordance with
|
||||
the terms of this License. If the unit or agency is other than DOD,
|
||||
the Program and its documentation are classified as "commercial
|
||||
computer software" and "commercial computer software documentation"
|
||||
respectively and, pursuant to FAR Section 12.212, the Government is
|
||||
acquiring the Program and its documentation in accordance with the
|
||||
terms of this License.
|
File diff suppressed because it is too large
Load Diff
@ -1,734 +0,0 @@
|
||||
|
||||
/****************************************************************************/
|
||||
/*! \mainpage XMLParser library
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This is a basic XML parser written in ANSI C++ for portability.
|
||||
* It works by using recursion and a node tree for breaking
|
||||
* down the elements of an XML document.
|
||||
*
|
||||
* @version V2.42
|
||||
* @author Frank Vanden Berghen
|
||||
*
|
||||
* Copyright (c) 2002, Business-Insight
|
||||
* <a href="http://www.Business-Insight.com">Business-Insight</a>
|
||||
* All rights reserved.
|
||||
* See the file <a href="../../AFPL-license.txt">AFPL-license.txt</a> about the licensing terms
|
||||
*
|
||||
* \section tutorial First Tutorial
|
||||
* You can follow a simple <a href="../../xmlParser.html">Tutorial</a> to know the basics...
|
||||
*
|
||||
* \section usage General usage: How to include the XMLParser library inside your project.
|
||||
*
|
||||
* The library is composed of two files: <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
|
||||
* <a href="../../xmlParser.h">xmlParser.h</a>. These are the ONLY 2 files that you need when
|
||||
* using the library inside your own projects.
|
||||
*
|
||||
* All the functions of the library are documented inside the comments of the file
|
||||
* <a href="../../xmlParser.h">xmlParser.h</a>. These comments can be transformed in
|
||||
* full-fledged HTML documentation using the DOXYGEN software: simply type: "doxygen doxy.cfg"
|
||||
*
|
||||
* By default, the XMLParser library uses (char*) for string representation.To use the (wchar_t*)
|
||||
* version of the library, you need to define the "_UNICODE" preprocessor definition variable
|
||||
* (this is usually done inside your project definition file) (This is done automatically for you
|
||||
* when using Visual Studio).
|
||||
*
|
||||
* \section example Advanced Tutorial and Many Examples of usage.
|
||||
*
|
||||
* Some very small introductory examples are described inside the Tutorial file
|
||||
* <a href="../../xmlParser.html">xmlParser.html</a>
|
||||
*
|
||||
* Some additional small examples are also inside the file <a href="../../xmlTest.cpp">xmlTest.cpp</a>
|
||||
* (for the "char*" version of the library) and inside the file
|
||||
* <a href="../../xmlTestUnicode.cpp">xmlTestUnicode.cpp</a> (for the "wchar_t*"
|
||||
* version of the library). If you have a question, please review these additionnal examples
|
||||
* before sending an e-mail to the author.
|
||||
*
|
||||
* To build the examples:
|
||||
* - linux/unix: type "make"
|
||||
* - solaris: type "make -f makefile.solaris"
|
||||
* - windows: Visual Studio: double-click on xmlParser.dsw
|
||||
* (under Visual Studio .NET, the .dsp and .dsw files will be automatically converted to .vcproj and .sln files)
|
||||
*
|
||||
* In order to build the examples you need some additional files:
|
||||
* - linux/unix: makefile
|
||||
* - solaris: makefile.solaris
|
||||
* - windows: Visual Studio: *.dsp, xmlParser.dsw and also xmlParser.lib and xmlParser.dll
|
||||
*
|
||||
* \section debugging Debugging with the XMLParser library
|
||||
*
|
||||
* \subsection debugwin Debugging under WINDOWS
|
||||
*
|
||||
* Inside Visual C++, the "debug versions" of the memory allocation functions are
|
||||
* very slow: Do not forget to compile in "release mode" to get maximum speed.
|
||||
* When I had to debug a software that was using the XMLParser Library, it was usually
|
||||
* a nightmare because the library was sooOOOoooo slow in debug mode (because of the
|
||||
* slow memory allocations in Debug mode). To solve this
|
||||
* problem, during all the debugging session, I am now using a very fast DLL version of the
|
||||
* XMLParser Library (the DLL is compiled in release mode). Using the DLL version of
|
||||
* the XMLParser Library allows me to have lightening XML parsing speed even in debug!
|
||||
* Other than that, the DLL version is useless: In the release version of my tool,
|
||||
* I always use the normal, ".cpp"-based, XMLParser Library (I simply include the
|
||||
* <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
|
||||
* <a href="../../xmlParser.h">xmlParser.h</a> files into the project).
|
||||
*
|
||||
* The file <a href="../../XMLNodeAutoexp.txt">XMLNodeAutoexp.txt</a> contains some
|
||||
* "tweaks" that improve substancially the display of the content of the XMLNode objects
|
||||
* inside the Visual Studio Debugger. Believe me, once you have seen inside the debugger
|
||||
* the "smooth" display of the XMLNode objects, you cannot live without it anymore!
|
||||
*
|
||||
* \subsection debuglinux Debugging under LINUX/UNIX
|
||||
*
|
||||
* The speed of the debug version of the XMLParser library is tolerable so no extra
|
||||
* work.has been done.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_XML_NODE__
|
||||
#define __INCLUDE_XML_NODE__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _UNICODE
|
||||
// If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
|
||||
// This is useful when you get error messages like:
|
||||
// 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
|
||||
// The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
|
||||
// must be defined) or utf8-mode(the pre-processor variable must be undefined).
|
||||
#define _XMLWIDECHAR
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(UNDER_CE) || defined(_WIN32) || defined(WIN64) || defined(__BORLANDC__)
|
||||
// comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET) or Borland
|
||||
#define _XMLWINDOWS
|
||||
#endif
|
||||
|
||||
#ifdef XMLDLLENTRY
|
||||
#undef XMLDLLENTRY
|
||||
#endif
|
||||
#ifdef _USE_XMLPARSER_DLL
|
||||
#ifdef _DLL_EXPORTS_
|
||||
#define XMLDLLENTRY __declspec(dllexport)
|
||||
#else
|
||||
#define XMLDLLENTRY __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define XMLDLLENTRY
|
||||
#endif
|
||||
|
||||
// uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
|
||||
//#define XML_NO_WIDE_CHAR
|
||||
|
||||
#ifdef XML_NO_WIDE_CHAR
|
||||
#undef _XMLWINDOWS
|
||||
#undef _XMLWIDECHAR
|
||||
#endif
|
||||
|
||||
#ifdef _XMLWINDOWS
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#define XMLDLLENTRY
|
||||
#ifndef XML_NO_WIDE_CHAR
|
||||
#include <wchar.h> // to have 'wcsrtombs' for ANSI version
|
||||
// to have 'mbsrtowcs' for WIDECHAR version
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Some common types for char set portable code
|
||||
#ifdef _XMLWIDECHAR
|
||||
#define _CXML(c) L ## c
|
||||
#define XMLCSTR const wchar_t *
|
||||
#define XMLSTR wchar_t *
|
||||
#define XMLCHAR wchar_t
|
||||
#else
|
||||
#define _CXML(c) c
|
||||
#define XMLCSTR const char *
|
||||
#define XMLSTR char *
|
||||
#define XMLCHAR char
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* FALSE */
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* TRUE */
|
||||
|
||||
|
||||
/// Enumeration for XML parse errors.
|
||||
typedef enum XMLError
|
||||
{
|
||||
eXMLErrorNone = 0,
|
||||
eXMLErrorMissingEndTag,
|
||||
eXMLErrorNoXMLTagFound,
|
||||
eXMLErrorEmpty,
|
||||
eXMLErrorMissingTagName,
|
||||
eXMLErrorMissingEndTagName,
|
||||
eXMLErrorUnmatchedEndTag,
|
||||
eXMLErrorUnmatchedEndClearTag,
|
||||
eXMLErrorUnexpectedToken,
|
||||
eXMLErrorNoElements,
|
||||
eXMLErrorFileNotFound,
|
||||
eXMLErrorFirstTagNotFound,
|
||||
eXMLErrorUnknownCharacterEntity,
|
||||
eXMLErrorCharacterCodeAbove255,
|
||||
eXMLErrorCharConversionError,
|
||||
eXMLErrorCannotOpenWriteFile,
|
||||
eXMLErrorCannotWriteFile,
|
||||
|
||||
eXMLErrorBase64DataSizeIsNotMultipleOf4,
|
||||
eXMLErrorBase64DecodeIllegalCharacter,
|
||||
eXMLErrorBase64DecodeTruncatedData,
|
||||
eXMLErrorBase64DecodeBufferTooSmall
|
||||
} XMLError;
|
||||
|
||||
|
||||
/// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
|
||||
typedef enum XMLElementType
|
||||
{
|
||||
eNodeChild=0,
|
||||
eNodeAttribute=1,
|
||||
eNodeText=2,
|
||||
eNodeClear=3,
|
||||
eNodeNULL=4
|
||||
} XMLElementType;
|
||||
|
||||
/// Structure used to obtain error details if the parse fails.
|
||||
typedef struct XMLResults
|
||||
{
|
||||
enum XMLError error;
|
||||
int nLine,nColumn;
|
||||
} XMLResults;
|
||||
|
||||
/// Structure for XML clear (unformatted) node (usually comments)
|
||||
typedef struct XMLClear {
|
||||
XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
|
||||
} XMLClear;
|
||||
|
||||
/// Structure for XML attribute.
|
||||
typedef struct XMLAttribute {
|
||||
XMLCSTR lpszName; XMLCSTR lpszValue;
|
||||
} XMLAttribute;
|
||||
|
||||
/// XMLElementPosition are not interchangeable with simple indexes
|
||||
typedef int XMLElementPosition;
|
||||
|
||||
struct XMLNodeContents;
|
||||
|
||||
/** @defgroup XMLParserGeneral The XML parser */
|
||||
|
||||
/// Main Class representing a XML node
|
||||
/**
|
||||
* All operations are performed using this class.
|
||||
* \note The constructors of the XMLNode class are protected, so use instead one of these four methods to get your first instance of XMLNode:
|
||||
* <ul>
|
||||
* <li> XMLNode::parseString </li>
|
||||
* <li> XMLNode::parseFile </li>
|
||||
* <li> XMLNode::openFileHelper </li>
|
||||
* <li> XMLNode::createXMLTopNode (or XMLNode::createXMLTopNode_WOSD)</li>
|
||||
* </ul> */
|
||||
typedef struct XMLDLLENTRY XMLNode
|
||||
{
|
||||
private:
|
||||
|
||||
struct XMLNodeDataTag;
|
||||
|
||||
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
|
||||
XMLNode(struct XMLNodeDataTag *pParent, XMLSTR lpszName, char isDeclaration);
|
||||
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
|
||||
XMLNode(struct XMLNodeDataTag *p);
|
||||
|
||||
public:
|
||||
static XMLCSTR getVersion();///< Return the XMLParser library version number
|
||||
|
||||
/** @defgroup conversions Parsing XML files/strings to an XMLNode structure and Rendering XMLNode's to files/string.
|
||||
* @ingroup XMLParserGeneral
|
||||
* @{ */
|
||||
|
||||
/// Parse an XML string and return the root of a XMLNode tree representing the string.
|
||||
static XMLNode parseString (XMLCSTR lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
|
||||
/**< The "parseString" function parse an XML string and return the root of a XMLNode tree. The "opposite" of this function is
|
||||
* the function "createXMLString" that re-creates an XML string from an XMLNode tree. If the XML document is corrupted, the
|
||||
* "parseString" method will initialize the "pResults" variable with some information that can be used to trace the error.
|
||||
* If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
|
||||
* beginning of the "xmlParser.cpp" file.
|
||||
*
|
||||
* @param lpXMLString the XML string to parse
|
||||
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
|
||||
* @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
|
||||
*/
|
||||
|
||||
/// Parse an XML file and return the root of a XMLNode tree representing the file.
|
||||
static XMLNode parseFile (XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
|
||||
/**< The "parseFile" function parse an XML file and return the root of a XMLNode tree. The "opposite" of this function is
|
||||
* the function "writeToFile" that re-creates an XML file from an XMLNode tree. If the XML document is corrupted, the
|
||||
* "parseFile" method will initialize the "pResults" variable with some information that can be used to trace the error.
|
||||
* If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
|
||||
* beginning of the "xmlParser.cpp" file.
|
||||
*
|
||||
* @param filename the path to the XML file to parse
|
||||
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
|
||||
* @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
|
||||
*/
|
||||
|
||||
/// Parse an XML file and return the root of a XMLNode tree representing the file. A very crude error checking is made. An attempt to guess the Char Encoding used in the file is made.
|
||||
static XMLNode openFileHelper(XMLCSTR filename, XMLCSTR tag=NULL);
|
||||
/**< The "openFileHelper" function reports to the screen all the warnings and errors that occurred during parsing of the XML file.
|
||||
* This function also tries to guess char Encoding (UTF-8, ASCII or SHIT-JIS) based on the first 200 bytes of the file. Since each
|
||||
* application has its own way to report and deal with errors, you should rather use the "parseFile" function to parse XML files
|
||||
* and program yourself thereafter an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
|
||||
* mechanism included inside the "openFileHelper" function).
|
||||
*
|
||||
* If the XML document is corrupted, the "openFileHelper" method will:
|
||||
* - display an error message on the console (or inside a messageBox for windows).
|
||||
* - stop execution (exit).
|
||||
*
|
||||
* I strongly suggest that you write your own "openFileHelper" method tailored to your needs. If you still want to parse
|
||||
* the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the beginning of the "xmlParser.cpp" file.
|
||||
*
|
||||
* @param filename the path of the XML file to parse.
|
||||
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
|
||||
*/
|
||||
|
||||
static XMLCSTR getError(XMLError error); ///< this gives you a user-friendly explanation of the parsing error
|
||||
|
||||
/// Create an XML string starting from the current XMLNode.
|
||||
XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const;
|
||||
/**< The returned string should be free'd using the "freeXMLString" function.
|
||||
*
|
||||
* If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element
|
||||
* with appropriate white spaces and carriage returns. if pnSize is given it returns the size in character of the string. */
|
||||
|
||||
/// Save the content of an xmlNode inside a file
|
||||
XMLError writeToFile(XMLCSTR filename,
|
||||
const char *encoding=NULL,
|
||||
char nFormat=1) const;
|
||||
/**< If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element with appropriate white spaces and carriage returns.
|
||||
* If the global parameter "characterEncoding==encoding_UTF8", then the "encoding" parameter is ignored and always set to "utf-8".
|
||||
* If the global parameter "characterEncoding==encoding_ShiftJIS", then the "encoding" parameter is ignored and always set to "SHIFT-JIS".
|
||||
* If "_XMLWIDECHAR=1", then the "encoding" parameter is ignored and always set to "utf-16".
|
||||
* If no "encoding" parameter is given the "ISO-8859-1" encoding is used. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup navigate Navigate the XMLNode structure
|
||||
* @ingroup XMLParserGeneral
|
||||
* @{ */
|
||||
XMLCSTR getName() const; ///< name of the node
|
||||
XMLCSTR getText(int i=0) const; ///< return ith text field
|
||||
int nText() const; ///< nbr of text field
|
||||
XMLNode getParentNode() const; ///< return the parent node
|
||||
XMLNode getChildNode(int i=0) const; ///< return ith child node
|
||||
XMLNode getChildNode(XMLCSTR name, int i) const; ///< return ith child node with specific name (return an empty node if failing). If i==-1, this returns the last XMLNode with the given name.
|
||||
XMLNode getChildNode(XMLCSTR name, int *i=NULL) const; ///< return next child node with specific name (return an empty node if failing)
|
||||
XMLNode getChildNodeWithAttribute(XMLCSTR tagName,
|
||||
XMLCSTR attributeName,
|
||||
XMLCSTR attributeValue=NULL,
|
||||
int *i=NULL) const; ///< return child node with specific name/attribute (return an empty node if failing)
|
||||
XMLNode getChildNodeByPath(XMLCSTR path, char createNodeIfMissing=0, XMLCHAR sep='/');
|
||||
///< return the first child node with specific path
|
||||
XMLNode getChildNodeByPathNonConst(XMLSTR path, char createNodeIfMissing=0, XMLCHAR sep='/');
|
||||
///< return the first child node with specific path.
|
||||
|
||||
int nChildNode(XMLCSTR name) const; ///< return the number of child node with specific name
|
||||
int nChildNode() const; ///< nbr of child node
|
||||
XMLAttribute getAttribute(int i=0) const; ///< return ith attribute
|
||||
XMLCSTR getAttributeName(int i=0) const; ///< return ith attribute name
|
||||
XMLCSTR getAttributeValue(int i=0) const; ///< return ith attribute value
|
||||
char isAttributeSet(XMLCSTR name) const; ///< test if an attribute with a specific name is given
|
||||
XMLCSTR getAttribute(XMLCSTR name, int i) const; ///< return ith attribute content with specific name (return a NULL if failing)
|
||||
XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const; ///< return next attribute content with specific name (return a NULL if failing)
|
||||
int nAttribute() const; ///< nbr of attribute
|
||||
XMLClear getClear(int i=0) const; ///< return ith clear field (comments)
|
||||
int nClear() const; ///< nbr of clear field
|
||||
XMLNodeContents enumContents(XMLElementPosition i) const; ///< enumerate all the different contents (attribute,child,text, clear) of the current XMLNode. The order is reflecting the order of the original file/string. NOTE: 0 <= i < nElement();
|
||||
int nElement() const; ///< nbr of different contents for current node
|
||||
char isEmpty() const; ///< is this node Empty?
|
||||
char isDeclaration() const; ///< is this node a declaration <? .... ?>
|
||||
XMLNode deepCopy() const; ///< deep copy (duplicate/clone) a XMLNode
|
||||
static XMLNode emptyNode(); ///< return XMLNode::emptyXMLNode;
|
||||
/** @} */
|
||||
|
||||
~XMLNode();
|
||||
XMLNode(const XMLNode &A); ///< to allow shallow/fast copy:
|
||||
XMLNode& operator=( const XMLNode& A ); ///< to allow shallow/fast copy:
|
||||
|
||||
XMLNode(): d(NULL){};
|
||||
static XMLNode emptyXMLNode;
|
||||
static XMLClear emptyXMLClear;
|
||||
static XMLAttribute emptyXMLAttribute;
|
||||
|
||||
/** @defgroup xmlModify Create or Update the XMLNode structure
|
||||
* @ingroup XMLParserGeneral
|
||||
* The functions in this group allows you to create from scratch (or update) a XMLNode structure. Start by creating your top
|
||||
* node with the "createXMLTopNode" function and then add new nodes with the "addChild" function. The parameter 'pos' gives
|
||||
* the position where the childNode, the text or the XMLClearTag will be inserted. The default value (pos=-1) inserts at the
|
||||
* end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end). <br>
|
||||
*
|
||||
* REMARK: 0 <= pos < nChild()+nText()+nClear() <br>
|
||||
*/
|
||||
|
||||
/** @defgroup creation Creating from scratch a XMLNode structure
|
||||
* @ingroup xmlModify
|
||||
* @{ */
|
||||
static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE); ///< Create the top node of an XMLNode structure
|
||||
XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); ///< Add a new child node
|
||||
XMLNode addChild(XMLNode nodeToAdd, XMLElementPosition pos=-1); ///< If the "nodeToAdd" has some parents, it will be detached from it's parents before being attached to the current XMLNode
|
||||
XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev); ///< Add a new attribute
|
||||
XMLCSTR addText(XMLCSTR lpszValue, XMLElementPosition pos=-1); ///< Add a new text content
|
||||
XMLClear *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1);
|
||||
/**< Add a new clear tag
|
||||
* @param lpszOpen default value "<![CDATA["
|
||||
* @param lpszClose default value "]]>"
|
||||
*/
|
||||
/** @} */
|
||||
|
||||
/** @defgroup xmlUpdate Updating Nodes
|
||||
* @ingroup xmlModify
|
||||
* Some update functions:
|
||||
* @{
|
||||
*/
|
||||
XMLCSTR updateName(XMLCSTR lpszName); ///< change node's name
|
||||
XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); ///< if the attribute to update is missing, a new one will be added
|
||||
XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0); ///< if the attribute to update is missing, a new one will be added
|
||||
XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
|
||||
XMLCSTR updateText(XMLCSTR lpszNewValue, int i=0); ///< if the text to update is missing, a new one will be added
|
||||
XMLCSTR updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the text to update is missing, a new one will be added
|
||||
XMLClear *updateClear(XMLCSTR lpszNewContent, int i=0); ///< if the clearTag to update is missing, a new one will be added
|
||||
XMLClear *updateClear(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added
|
||||
XMLClear *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the clearTag to update is missing, a new one will be added
|
||||
/** @} */
|
||||
|
||||
/** @defgroup xmlDelete Deleting Nodes or Attributes
|
||||
* @ingroup xmlModify
|
||||
* Some deletion functions:
|
||||
* @{
|
||||
*/
|
||||
/// The "deleteNodeContent" function forces the deletion of the content of this XMLNode and the subtree.
|
||||
void deleteNodeContent();
|
||||
/**< \note The XMLNode instances that are referring to the part of the subtree that has been deleted CANNOT be used anymore!!. Unexpected results will occur if you continue using them. */
|
||||
void deleteAttribute(int i=0); ///< Delete the ith attribute of the current XMLNode
|
||||
void deleteAttribute(XMLCSTR lpszName); ///< Delete the attribute with the given name (the "strcmp" function is used to find the right attribute)
|
||||
void deleteAttribute(XMLAttribute *anAttribute); ///< Delete the attribute with the name "anAttribute->lpszName" (the "strcmp" function is used to find the right attribute)
|
||||
void deleteText(int i=0); ///< Delete the Ith text content of the current XMLNode
|
||||
void deleteText(XMLCSTR lpszValue); ///< Delete the text content "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the right text)
|
||||
void deleteClear(int i=0); ///< Delete the Ith clear tag inside the current XMLNode
|
||||
void deleteClear(XMLCSTR lpszValue); ///< Delete the clear tag "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the clear tag)
|
||||
void deleteClear(XMLClear *p); ///< Delete the clear tag "p" inside the current XMLNode (direct "pointer-to-pointer" comparison on the lpszName of the clear tag is used to find the clear tag)
|
||||
/** @} */
|
||||
|
||||
/** @defgroup xmlWOSD ???_WOSD functions.
|
||||
* @ingroup xmlModify
|
||||
* The strings given as parameters for the "add" and "update" methods that have a name with
|
||||
* the postfix "_WOSD" (that means "WithOut String Duplication")(for example "addText_WOSD")
|
||||
* will be free'd by the XMLNode class. For example, it means that this is incorrect:
|
||||
* \code
|
||||
* xNode.addText_WOSD("foo");
|
||||
* xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
|
||||
* \endcode
|
||||
* In opposition, this is correct:
|
||||
* \code
|
||||
* xNode.addText("foo");
|
||||
* xNode.addText_WOSD(stringDup("foo"));
|
||||
* xNode.updateAttribute("#newcolor" ,NULL,"color");
|
||||
* xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
|
||||
* \endcode
|
||||
* Typically, you will never do:
|
||||
* \code
|
||||
* char *b=(char*)malloc(...);
|
||||
* xNode.addText(b);
|
||||
* free(b);
|
||||
* \endcode
|
||||
* ... but rather:
|
||||
* \code
|
||||
* char *b=(char*)malloc(...);
|
||||
* xNode.addText_WOSD(b);
|
||||
* \endcode
|
||||
* ('free(b)' is performed by the XMLNode class)
|
||||
* @{ */
|
||||
static XMLNode createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration=FALSE); ///< Create the top node of an XMLNode structure
|
||||
XMLNode addChild_WOSD(XMLSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); ///< Add a new child node
|
||||
XMLAttribute *addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValue); ///< Add a new attribute
|
||||
XMLCSTR addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos=-1); ///< Add a new text content
|
||||
XMLClear *addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1); ///< Add a new clear Tag
|
||||
|
||||
XMLCSTR updateName_WOSD(XMLSTR lpszName); ///< change node's name
|
||||
XMLAttribute *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); ///< if the attribute to update is missing, a new one will be added
|
||||
XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName=NULL,int i=0); ///< if the attribute to update is missing, a new one will be added
|
||||
XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName); ///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
|
||||
XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, int i=0); ///< if the text to update is missing, a new one will be added
|
||||
XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the text to update is missing, a new one will be added
|
||||
XMLClear *updateClear_WOSD(XMLSTR lpszNewContent, int i=0); ///< if the clearTag to update is missing, a new one will be added
|
||||
XMLClear *updateClear_WOSD(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added
|
||||
XMLClear *updateClear_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the clearTag to update is missing, a new one will be added
|
||||
/** @} */
|
||||
|
||||
/** @defgroup xmlPosition Position helper functions (use in conjunction with the update&add functions
|
||||
* @ingroup xmlModify
|
||||
* These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
|
||||
* middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
|
||||
* methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
|
||||
* @{ */
|
||||
XMLElementPosition positionOfText(int i=0) const;
|
||||
XMLElementPosition positionOfText(XMLCSTR lpszValue) const;
|
||||
XMLElementPosition positionOfClear(int i=0) const;
|
||||
XMLElementPosition positionOfClear(XMLCSTR lpszValue) const;
|
||||
XMLElementPosition positionOfClear(XMLClear *a) const;
|
||||
XMLElementPosition positionOfChildNode(int i=0) const;
|
||||
XMLElementPosition positionOfChildNode(XMLNode x) const;
|
||||
XMLElementPosition positionOfChildNode(XMLCSTR name, int i=0) const; ///< return the position of the ith childNode with the specified name if (name==NULL) return the position of the ith childNode
|
||||
/** @} */
|
||||
|
||||
/// Enumeration for XML character encoding.
|
||||
typedef enum XMLCharEncoding
|
||||
{
|
||||
char_encoding_error=0,
|
||||
char_encoding_UTF8=1,
|
||||
char_encoding_legacy=2,
|
||||
char_encoding_ShiftJIS=3,
|
||||
char_encoding_GB2312=4,
|
||||
char_encoding_Big5=5,
|
||||
char_encoding_GBK=6 // this is actually the same as Big5
|
||||
} XMLCharEncoding;
|
||||
|
||||
/** \addtogroup conversions
|
||||
* @{ */
|
||||
|
||||
/// Sets the global options for the conversions
|
||||
static char setGlobalOptions(XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8, char guessWideCharChars=1,
|
||||
char dropWhiteSpace=1, char removeCommentsInMiddleOfText=1);
|
||||
/**< The "setGlobalOptions" function allows you to change four global parameters that affect string & file
|
||||
* parsing. First of all, you most-probably will never have to change these 3 global parameters.
|
||||
*
|
||||
* @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in WideChar mode, then the
|
||||
* XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains ASCII
|
||||
* characters. If this is the case, then the file will be loaded and converted in memory to
|
||||
* WideChar before being parsed. If 0, no conversion will be performed.
|
||||
*
|
||||
* @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in ASCII/UTF8/char* mode, then the
|
||||
* XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains WideChar
|
||||
* characters. If this is the case, then the file will be loaded and converted in memory to
|
||||
* ASCII/UTF8/char* before being parsed. If 0, no conversion will be performed.
|
||||
*
|
||||
* @param characterEncoding This parameter is only meaningful when compiling in char* mode (multibyte character mode).
|
||||
* In wchar_t* (wide char mode), this parameter is ignored. This parameter should be one of the
|
||||
* three currently recognized encodings: XMLNode::encoding_UTF8, XMLNode::encoding_ascii,
|
||||
* XMLNode::encoding_ShiftJIS.
|
||||
*
|
||||
* @param dropWhiteSpace In most situations, text fields containing only white spaces (and carriage returns)
|
||||
* are useless. Even more, these "empty" text fields are annoying because they increase the
|
||||
* complexity of the user's code for parsing. So, 99% of the time, it's better to drop
|
||||
* the "empty" text fields. However The XML specification indicates that no white spaces
|
||||
* should be lost when parsing the file. So to be perfectly XML-compliant, you should set
|
||||
* dropWhiteSpace=0. A note of caution: if you set "dropWhiteSpace=0", the parser will be
|
||||
* slower and your code will be more complex.
|
||||
*
|
||||
* @param removeCommentsInMiddleOfText To explain this parameter, let's consider this code:
|
||||
* \code
|
||||
* XMLNode x=XMLNode::parseString("<a>foo<!-- hello -->bar<!DOCTYPE world >chu</a>","a");
|
||||
* \endcode
|
||||
* If removeCommentsInMiddleOfText=0, then we will have:
|
||||
* \code
|
||||
* x.getText(0) -> "foo"
|
||||
* x.getText(1) -> "bar"
|
||||
* x.getText(2) -> "chu"
|
||||
* x.getClear(0) --> "<!-- hello -->"
|
||||
* x.getClear(1) --> "<!DOCTYPE world >"
|
||||
* \endcode
|
||||
* If removeCommentsInMiddleOfText=1, then we will have:
|
||||
* \code
|
||||
* x.getText(0) -> "foobar"
|
||||
* x.getText(1) -> "chu"
|
||||
* x.getClear(0) --> "<!DOCTYPE world >"
|
||||
* \endcode
|
||||
*
|
||||
* \return "0" when there are no errors. If you try to set an unrecognized encoding then the return value will be "1" to signal an error.
|
||||
*
|
||||
* \note Sometime, it's useful to set "guessWideCharChars=0" to disable any conversion
|
||||
* because the test to detect the file-type (ASCII/UTF8/char* or WideChar) may fail (rarely). */
|
||||
|
||||
/// Guess the character encoding of the string (ascii, utf8 or shift-JIS)
|
||||
static XMLCharEncoding guessCharEncoding(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
|
||||
/**< The "guessCharEncoding" function try to guess the character encoding. You most-probably will never
|
||||
* have to use this function. It then returns the appropriate value of the global parameter
|
||||
* "characterEncoding" described in the XMLNode::setGlobalOptions. The guess is based on the content of a buffer of length
|
||||
* "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
|
||||
* file to be parsed. The XMLNode::openFileHelper function is using this function to automatically compute
|
||||
* the value of the "characterEncoding" global parameter. There are several heuristics used to do the
|
||||
* guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
|
||||
* forbids to use this attribute to do the guess but you can still use it if you set
|
||||
* "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers).
|
||||
* If an inconsistency in the encoding is detected, then the return value is "0". */
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
// these are functions and structures used internally by the XMLNode class (don't bother about them):
|
||||
|
||||
typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
|
||||
{
|
||||
XMLCSTR lpszName; // Element name (=NULL if root)
|
||||
int nChild, // Number of child nodes
|
||||
nText, // Number of text fields
|
||||
nClear, // Number of Clear fields (comments)
|
||||
nAttribute; // Number of attributes
|
||||
char isDeclaration; // Whether node is an XML declaration - '<?xml ?>'
|
||||
struct XMLNodeDataTag *pParent; // Pointer to parent element (=NULL if root)
|
||||
XMLNode *pChild; // Array of child nodes
|
||||
XMLCSTR *pText; // Array of text fields
|
||||
XMLClear *pClear; // Array of clear fields
|
||||
XMLAttribute *pAttribute; // Array of attributes
|
||||
int *pOrder; // order of the child_nodes,text_fields,clear_fields
|
||||
int ref_count; // for garbage collection (smart pointers)
|
||||
} XMLNodeData;
|
||||
XMLNodeData *d;
|
||||
|
||||
char parseClearTag(void *px, void *pa);
|
||||
char maybeAddTxT(void *pa, XMLCSTR tokenPStr);
|
||||
int ParseXMLElement(void *pXML);
|
||||
void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype);
|
||||
int indexText(XMLCSTR lpszValue) const;
|
||||
int indexClear(XMLCSTR lpszValue) const;
|
||||
XMLNode addChild_priv(int,XMLSTR,char,int);
|
||||
XMLAttribute *addAttribute_priv(int,XMLSTR,XMLSTR);
|
||||
XMLCSTR addText_priv(int,XMLSTR,int);
|
||||
XMLClear *addClear_priv(int,XMLSTR,XMLCSTR,XMLCSTR,int);
|
||||
void emptyTheNode(char force);
|
||||
static inline XMLElementPosition findPosition(XMLNodeData *d, int index, XMLElementType xtype);
|
||||
static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat);
|
||||
static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
|
||||
static void exactMemory(XMLNodeData *d);
|
||||
static int detachFromParent(XMLNodeData *d);
|
||||
} XMLNode;
|
||||
|
||||
/// This structure is given by the function XMLNode::enumContents.
|
||||
typedef struct XMLNodeContents
|
||||
{
|
||||
/// This dictates what's the content of the XMLNodeContent
|
||||
enum XMLElementType etype;
|
||||
/**< should be an union to access the appropriate data. Compiler does not allow union of object with constructor... too bad. */
|
||||
XMLNode child;
|
||||
XMLAttribute attrib;
|
||||
XMLCSTR text;
|
||||
XMLClear clear;
|
||||
|
||||
} XMLNodeContents;
|
||||
|
||||
/** @defgroup StringAlloc String Allocation/Free functions
|
||||
* @ingroup xmlModify
|
||||
* @{ */
|
||||
/// Duplicate (copy in a new allocated buffer) the source string.
|
||||
XMLDLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=-1);
|
||||
/**< This is
|
||||
* a very handy function when used with all the "XMLNode::*_WOSD" functions (\link xmlWOSD \endlink).
|
||||
* @param cbData If !=0 then cbData is the number of chars to duplicate. New strings allocated with
|
||||
* this function should be free'd using the "freeXMLString" function. */
|
||||
|
||||
/// to free the string allocated inside the "stringDup" function or the "createXMLString" function.
|
||||
XMLDLLENTRY void freeXMLString(XMLSTR t); // {free(t);}
|
||||
/** @} */
|
||||
|
||||
/** @defgroup atoX ato? like functions
|
||||
* @ingroup XMLParserGeneral
|
||||
* The "xmlto?" functions are equivalents to the atoi, atol, atof functions.
|
||||
* The only difference is: If the variable "xmlString" is NULL, than the return value
|
||||
* is "defautValue". These 6 functions are only here as "convenience" functions for the
|
||||
* user (they are not used inside the XMLparser). If you don't need them, you can
|
||||
* delete them without any trouble.
|
||||
*
|
||||
* @{ */
|
||||
XMLDLLENTRY char xmltob(XMLCSTR xmlString,char defautValue=0);
|
||||
XMLDLLENTRY int xmltoi(XMLCSTR xmlString,int defautValue=0);
|
||||
XMLDLLENTRY long xmltol(XMLCSTR xmlString,long defautValue=0);
|
||||
XMLDLLENTRY double xmltof(XMLCSTR xmlString,double defautValue=.0);
|
||||
XMLDLLENTRY XMLCSTR xmltoa(XMLCSTR xmlString,XMLCSTR defautValue=_CXML(""));
|
||||
XMLDLLENTRY XMLCHAR xmltoc(XMLCSTR xmlString,const XMLCHAR defautValue=_CXML('\0'));
|
||||
/** @} */
|
||||
|
||||
/** @defgroup ToXMLStringTool Helper class to create XML files using "printf", "fprintf", "cout",... functions.
|
||||
* @ingroup XMLParserGeneral
|
||||
* @{ */
|
||||
/// Helper class to create XML files using "printf", "fprintf", "cout",... functions.
|
||||
/** The ToXMLStringTool class helps you creating XML files using "printf", "fprintf", "cout",... functions.
|
||||
* The "ToXMLStringTool" class is processing strings so that all the characters
|
||||
* &,",',<,> are replaced by their XML equivalent:
|
||||
* \verbatim &, ", ', <, > \endverbatim
|
||||
* Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient
|
||||
* way to produce VERY large XML documents VERY fast.
|
||||
* \note If you are creating from scratch an XML file using the provided XMLNode class
|
||||
* you must not use the "ToXMLStringTool" class (because the "XMLNode" class does the
|
||||
* processing job for you during rendering).*/
|
||||
typedef struct XMLDLLENTRY ToXMLStringTool
|
||||
{
|
||||
public:
|
||||
ToXMLStringTool(): buf(NULL),buflen(0){}
|
||||
~ToXMLStringTool();
|
||||
void freeBuffer();///<call this function when you have finished using this object to release memory used by the internal buffer.
|
||||
|
||||
XMLSTR toXML(XMLCSTR source);///< returns a pointer to an internal buffer that contains a XML-encoded string based on the "source" parameter.
|
||||
|
||||
/** The "toXMLUnSafe" function is deprecated because there is a possibility of
|
||||
* "destination-buffer-overflow". It converts the string
|
||||
* "source" to the string "dest". */
|
||||
static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source); ///< deprecated: use "toXML" instead
|
||||
static int lengthXMLString(XMLCSTR source); ///< deprecated: use "toXML" instead
|
||||
|
||||
private:
|
||||
XMLSTR buf;
|
||||
int buflen;
|
||||
} ToXMLStringTool;
|
||||
/** @} */
|
||||
|
||||
/** @defgroup XMLParserBase64Tool Helper class to include binary data inside XML strings using "Base64 encoding".
|
||||
* @ingroup XMLParserGeneral
|
||||
* @{ */
|
||||
/// Helper class to include binary data inside XML strings using "Base64 encoding".
|
||||
/** The "XMLParserBase64Tool" class allows you to include any binary data (images, sounds,...)
|
||||
* into an XML document using "Base64 encoding". This class is completely
|
||||
* separated from the rest of the xmlParser library and can be removed without any problem.
|
||||
* To include some binary data into an XML file, you must convert the binary data into
|
||||
* standard text (using "encode"). To retrieve the original binary data from the
|
||||
* b64-encoded text included inside the XML file, use "decode". Alternatively, these
|
||||
* functions can also be used to "encrypt/decrypt" some critical data contained inside
|
||||
* the XML (it's not a strong encryption at all, but sometimes it can be useful). */
|
||||
typedef struct XMLDLLENTRY XMLParserBase64Tool
|
||||
{
|
||||
public:
|
||||
XMLParserBase64Tool(): buf(NULL),buflen(0){}
|
||||
~XMLParserBase64Tool();
|
||||
void freeBuffer();///< Call this function when you have finished using this object to release memory used by the internal buffer.
|
||||
|
||||
/**
|
||||
* @param formatted If "formatted"=true, some space will be reserved for a carriage-return every 72 chars. */
|
||||
static int encodeLength(int inBufLen, char formatted=0); ///< return the length of the base64 string that encodes a data buffer of size inBufLen bytes.
|
||||
|
||||
/**
|
||||
* The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
|
||||
* from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
|
||||
* The string will be free'd when the XMLParserBase64Tool object is deleted.
|
||||
* All returned strings are sharing the same memory space. */
|
||||
XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0); ///< returns a pointer to an internal buffer containing the base64 string containing the binary data encoded from "inByteBuf"
|
||||
|
||||
/// returns the number of bytes which will be decoded from "inString".
|
||||
static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
|
||||
|
||||
/**
|
||||
* The "decode" function returns a pointer to a buffer containing the binary data decoded from "inString"
|
||||
* The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
|
||||
* All output buffer are sharing the same memory space.
|
||||
* @param inString If "instring" is malformed, NULL will be returned */
|
||||
unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL); ///< returns a pointer to an internal buffer containing the binary data decoded from "inString"
|
||||
|
||||
/**
|
||||
* decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
|
||||
* in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
|
||||
* will be returned; otherwise "TRUE". */
|
||||
static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL); ///< deprecated.
|
||||
|
||||
private:
|
||||
void *buf;
|
||||
int buflen;
|
||||
void alloc(int newsize);
|
||||
}XMLParserBase64Tool;
|
||||
/** @} */
|
||||
|
||||
#undef XMLDLLENTRY
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user