summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NT/src/factory.cpp186
-rw-r--r--NT/src/factory.h15
-rw-r--r--NT/src/nodes.h20
-rw-r--r--NT/src/rotor.cpp12
-rw-r--r--NT/src/rotor.h41
-rw-r--r--NT/src/xmlIO.cpp673
6 files changed, 922 insertions, 25 deletions
diff --git a/NT/src/factory.cpp b/NT/src/factory.cpp
index 6888a19..db50919 100644
--- a/NT/src/factory.cpp
+++ b/NT/src/factory.cpp
@@ -5,7 +5,185 @@ using namespace Rotor;
Node_factory::Node_factory(){
//for now, statically load prototype map in constructor
- add_type("time",new Time(),"nodes");
- add_type("multiply",new Multiply(),"nodes");
- add_type("print",new Print(),"nodes");
-} \ No newline at end of file
+ add_type(new Time(),"nodes");
+ add_type(new Multiply(),"nodes");
+ add_type(new Print(),"nodes");
+}
+bool Node_factory::list_node(const string &t,xmlIO XML){
+ for (auto& type: type_map) {
+ if (type.first==t) {
+ list_node(type.second,XML);
+ return true;
+ }
+ }
+ XML.addValue("error","Node /"+t+"/ not found");
+ return false;
+};
+bool Node_factory::list_node(const string &t,Json::Value &JSON){
+ for (auto& type: type_map) {
+ if (type.first==t) {
+ JSON["node"]=list_node(type.second);
+ return true;
+ }
+ }
+ JSON["error"]="Node /"+t+"/ not found";
+ return false;
+};
+Json::Value Node_factory::list_node(Rotor::Node* _node){
+ Json::Value node;
+ node["node_type"]=_node->node_type;
+ node["title"]=_node->title;
+ node["output_type"]=_node->output_type;
+ node["description"]=_node->description;
+ node["node_id"]=_node->node_id;
+ node["ui_type"]=_node->ui_type;
+
+ if (_node->vars.size()){
+ node["vars"]=Json::arrayValue;
+ for (auto& var: _node->vars) {
+ Json::Value newvar;
+ newvar["type"]=var.second->get_type();
+ newvar["connectable"]=var.second->connectable?"yes":"no";
+ node["vars"].append(newvar);
+ }
+ }
+/*
+ if (_node->inputs.size()){
+ node["signal_inputs"]=Json::arrayValue;
+ for (auto& input: _node->inputs) {
+ Json::Value signal_input;
+ signal_input["title"]=input->title;
+ signal_input["description"]=input->description;
+ node["signal_inputs"].append(signal_input);
+ }
+ }
+ if (dynamic_cast<Image_node*> (_node)!=nullptr) {
+ if ((dynamic_cast<Image_node*>(_node))->image_inputs.size()){
+ node["image_inputs"]=Json::arrayValue;
+ for (auto& input: (dynamic_cast<Image_node*>(_node))->image_inputs) {
+ Json::Value image_input;
+ image_input["title"]=input->title;
+ image_input["description"]=input->description;
+ node["image_inputs"].append(image_input);
+ }
+ }
+ }
+ if (_node->parameters.size()){
+ node["parameters"]=Json::arrayValue;
+ for (auto& param: _node->parameters) {
+ Json::Value parameter;
+ parameter["name"]=param.first;
+ parameter["type"]=param.second->type;
+ parameter["title"]=param.second->title;
+ parameter["description"]=param.second->description;
+ parameter["value"]=param.second->value;
+ parameter["min"]=param.second->min;
+ parameter["max"]=param.second->max;
+ parameter["step"]=param.second->step;
+ node["parameters"].append(parameter);
+ }
+ }
+ if (_node->attributes.size()){
+ node["attributes"]=Json::arrayValue;
+ for (auto& attr: _node->attributes) {
+ Json::Value attribute;
+ attribute["name"]=attr.first;
+ attribute["title"]=attr.second->title;
+ attribute["description"]=attr.second->description;
+ if (attr.second->vals.size()){ //document attribute enumeration
+ attribute["value"]=attr.second->value;
+ attribute["type"]="enum";
+ attribute["options"]=Json::arrayValue;
+ for (auto val: attr.second->vals){
+ attribute["options"].append(val);
+ }
+ }
+ else {
+ attribute["type"]=attr.second->type;
+ if (attr.second->type=="array"){
+ attribute["value"]=Json::arrayValue;
+ }
+ else attribute["value"]=attr.second->value;
+ }
+ node["attributes"].append(attribute);
+ }
+ }
+*/
+ return node;
+}
+
+void Node_factory::list_node(Rotor::Node* type,xmlIO XML,int i){
+ XML.addTag("node");
+ XML.addAttribute("node","output_type",type->output_type,i);
+ XML.addAttribute("node","node_type",type->node_type,i);
+ XML.addAttribute("node","title",type->title,i);
+ XML.addAttribute("node","description",type->description,i);
+ XML.addAttribute("node","node_id",type->node_id,i);
+ XML.addAttribute("node","ui_type",type->ui_type,i);
+ XML.pushTag("node",i);
+/*
+ //if (type->description!="") {
+ // XML.addTag("description");
+ // XML.setValue("description",type->description,0);
+ //}
+ int j=0;
+ for (auto& input: type->inputs) {
+ XML.addTag("signal_input");
+ XML.addAttribute("signal_input","title",input->title,j);
+ XML.addAttribute("signal_input","description",input->description,j);
+ j++;
+ }
+ j=0;
+ if (dynamic_cast<Image_node*> (type)!=nullptr) {
+ for (auto& input: (dynamic_cast<Image_node*>(type))->image_inputs) {
+ XML.addTag("image_input");
+ XML.addAttribute("image_input","title",input->title,j);
+ XML.addAttribute("image_input","description",input->description,j);
+ j++;
+ }
+ }
+ j=0;
+ for (auto& parameter: type->parameters) {
+ XML.addTag("parameter");
+ XML.addAttribute("parameter","name",parameter.first,j);
+ XML.addAttribute("parameter","type",parameter.second->type,j);
+ XML.addAttribute("parameter","title",parameter.second->title,j);
+ XML.addAttribute("parameter","description",parameter.second->description,j);
+ XML.addAttribute("parameter","value",parameter.second->value,j);
+ XML.addAttribute("parameter","min",parameter.second->min,j);
+ XML.addAttribute("parameter","max",parameter.second->max,j);
+ XML.addAttribute("parameter","step",parameter.second->step,j);
+ j++;
+ }
+ j=0;
+ for (auto& attribute: type->attributes) {
+ XML.addTag("attribute");
+ XML.addAttribute("attribute","name",attribute.first,j);
+ XML.addAttribute("attribute","title",attribute.second->title,j);
+ XML.addAttribute("attribute","description",attribute.second->description,j);
+ if (attribute.second->vals.size()){ //document attribute enumeration
+ XML.addAttribute("attribute","value",attribute.second->value,j);
+ XML.addAttribute("attribute","type","enum",j);
+ XML.pushTag("attribute",j);
+ int k=0;
+ for (auto val: attribute.second->vals){
+ XML.addTag("option");
+ XML.addAttribute("option","value",val,k);
+ k++;
+ }
+ XML.popTag();
+ }
+ else {
+ XML.addAttribute("attribute","type",attribute.second->type,j);
+ if (attribute.second->type=="array"){
+ XML.pushTag("attribute",j);
+ XML.addTag("value");
+ XML.popTag();
+ }
+ else XML.addAttribute("attribute","value",attribute.second->value,j);
+ }
+ j++;
+ }
+*/
+ XML.popTag();
+}
diff --git a/NT/src/factory.h b/NT/src/factory.h
index ac204a0..8c44507 100644
--- a/NT/src/factory.h
+++ b/NT/src/factory.h
@@ -12,19 +12,18 @@ namespace Rotor {
~Node_factory(){
for (auto t:type_map) delete t.second;
}
- void add_type(std::string type,Node* proto){
- type_map[type]=proto;
- type_map[type]->type=type;
+ void add_type(Node* proto){
+ type_map[proto->node_type]=proto;
};
- void add_type(std::string type,Node* proto,std::string category){
- add_type(type,proto);
+ void add_type(Node* proto,std::string category){
+ add_type(proto);
if (category_map.find(category)==category_map.end()) category_map[category]=vector<Node*>();
category_map[category].push_back(proto);
};
Node *create(std::map<std::string,std::string> &settings){
- if (settings.find("type")!=settings.end()) {
- if (type_map.find(settings["type"])!=type_map.end()) {
- return type_map[settings["type"]]->clone(settings);
+ if (settings.find("node_type")!=settings.end()) {
+ if (type_map.find(settings["node_type"])!=type_map.end()) {
+ return type_map[settings["node_type"]]->clone(settings);
}
}
return NULL;
diff --git a/NT/src/nodes.h b/NT/src/nodes.h
index a32408e..da24292 100644
--- a/NT/src/nodes.h
+++ b/NT/src/nodes.h
@@ -6,9 +6,13 @@
using namespace std;
namespace Rotor{
- class Time: public Node_type<double> {
+ class Double_node: public Node_type<double> {
public:
- Time(){};
+ Double_node(){output_type="double";};
+ };
+ class Time: public Double_node {
+ public:
+ Time(){node_type="time";};
Time(map<string,string> &settings):Time() {
init(settings);
};
@@ -20,11 +24,12 @@ namespace Rotor{
private:
double value;
};
- class Multiply: public Node_type<double> {
+ class Multiply: public Double_node {
public:
Multiply(){
inlet=create_inlet<double>("inlet");
value=create_inlet<double>("value");
+ node_type="multiply";
}
Multiply(map<string,string> &settings):Multiply() {
init(settings);
@@ -39,10 +44,15 @@ namespace Rotor{
Variable_type<double> *value;
double result;
};
- class Print: public Node_type<std::string> {
+ class String_node: public Node_type<string> {
+ public:
+ String_node(){output_type="string";};
+ };
+ class Print: public String_node {
public:
Print(){
- inlet=create_inlet<double>("inlet");
+ inlet=create_inlet<double>("inlet");
+ node_type="print";
}
Print(map<string,string> &settings):Print() {
init(settings);
diff --git a/NT/src/rotor.cpp b/NT/src/rotor.cpp
index 677fae0..c08734c 100644
--- a/NT/src/rotor.cpp
+++ b/NT/src/rotor.cpp
@@ -11,12 +11,13 @@ using namespace Rotor;
int main(){
Node_factory f;
- map<string,string> settings={{"type","time"}};
+/*
+ map<string,string> settings={{"node_type","time"}};
Node *t=f.create(settings);
- settings={{"value","2"},{"type","multiply"}};
+ settings={{"value","2"},{"node_type","multiply"}};
Node *m=f.create(settings);
if (!m->connect("inlet",t)) printf("not connected...\n");
- settings={{"type","print"}};
+ settings={{"node_type","print"}};
Node *p=f.create(settings);
if (!p->connect("inlet",m)) printf("not connected...\n");
for (double t=0;t<10.0;t+=0.765){
@@ -26,4 +27,9 @@ int main(){
delete t;
delete m;
delete p;
+*/
+Json::Value js;
+f.list_node("multiply",js);
+Json::StyledWriter writer;
+cerr<<writer.write(js)<<endl;
}
diff --git a/NT/src/rotor.h b/NT/src/rotor.h
index c83fe63..e64095c 100644
--- a/NT/src/rotor.h
+++ b/NT/src/rotor.h
@@ -50,6 +50,7 @@ namespace Rotor {
virtual void init(std::string s)=0;
virtual ~Variable(){};
virtual bool connect(Node* target)=0;
+ virtual std::string get_type()=0;
Node* connection;
bool connectable;
};
@@ -60,6 +61,9 @@ namespace Rotor {
std::istringstream cur(s);
cur >> value;
}
+ std::string get_type(){ //need this to output node templates
+ return "unknown";
+ }
bool connect(Node* target){
if (connectable){
if (dynamic_cast<Node_type<T>*>(target)){
@@ -77,6 +81,27 @@ namespace Rotor {
}
T value;
};
+ template <class T> class Variable_array: public Variable_type<T> {
+ public:
+ Variable_array(){};
+ void add(int num=1){
+ for (int i=0;i<num;i++) values.push_back(T());
+ }
+ bool connect(int which,Node* target){
+ if (values.size()>which){
+ return values[which].connect(target);
+ }
+ return false;
+ }
+ const T& get(int which,const Frame_parameters &frame){
+ if (values.size()>which){
+ return values[which].get(frame);
+ }
+ return value;
+ }
+ std::vector<Variable_type<T>> values;
+ T value;
+ };
//don't forget the dupliicate inlets
//it needs to be a property of a var
//vars need to be:
@@ -104,11 +129,13 @@ namespace Rotor {
return false;
}
virtual Node* clone(std::map<std::string,std::string> &_settings)=0;
- std::string type;
- std::string type;
- std::string type;
- std::string type;
- protected:
+ std::string node_type;
+ std::string node_id;
+ std::string id;
+ std::string description;
+ std::string title;
+ std::string ui_type;
+ std::string output_type;
std::unordered_map<std::string,Variable*> vars;
};
template <class NT> class Node_type : public Node {
@@ -130,6 +157,10 @@ namespace Rotor {
vars[name]=new Variable_type<IT>(false);
return (dynamic_cast<Variable_type<IT>*>(vars[name]));
}
+ template <class IT> Variable_array<IT>* create_array(std::string name){
+ vars[name]=new Variable_array<IT>();
+ return (dynamic_cast<Variable_array<IT>*>(vars[name]));
+ }
};
}
diff --git a/NT/src/xmlIO.cpp b/NT/src/xmlIO.cpp
new file mode 100644
index 0000000..be5efc0
--- /dev/null
+++ b/NT/src/xmlIO.cpp
@@ -0,0 +1,673 @@
+#include "xmlIO.h"
+
+#include <vector>
+#include <string>
+#include <iostream>
+
+//----------------------------------------
+// a pretty useful tokenization system:
+static vector<string> tokenize(const string & str, const string & delim);
+static vector<string> tokenize(const string & str, const string & delim)
+{
+ vector<string> tokens;
+
+ size_t p0 = 0, p1 = string::npos;
+ while(p0 != string::npos)
+ {
+ p1 = str.find_first_of(delim, p0);
+ if(p1 != p0)
+ {
+ string token = str.substr(p0, p1 - p0);
+ tokens.push_back(token);
+ }
+ p0 = str.find_first_not_of(delim, p1);
+ }
+ return tokens;
+}
+//----------------------------------------
+
+//----------------------------------------
+xmlIO::xmlIO():
+ storedHandle(NULL)
+{
+ level = 0;
+ //we do this so that we have a valid handle
+ //without the need for loadFile
+ storedHandle = TiXmlHandle(&doc);
+}
+
+//----------------------------------------
+xmlIO::xmlIO(const string& xmlFile):
+ storedHandle(NULL)
+{
+ level = 0;
+ //we do this so that we have a valid handle
+ //without the need for loadFile
+ storedHandle = TiXmlHandle(&doc);
+ loadFile(xmlFile);
+}
+
+//---------------------------------------------------------
+xmlIO::~xmlIO()
+{
+}
+
+//---------------------------------------------------------
+void xmlIO::setVerbose(bool _verbose){
+}
+
+//---------------------------------------------------------
+void xmlIO::clear(){
+ //we clear from our root level
+ //this is usually the document
+ //but if we are pushed - it could
+ //be all the tags inside of the pushed
+ //node - including the node itself!
+
+ storedHandle.ToNode()->Clear();
+}
+
+//---------------------------------------------------------
+bool xmlIO::loadFile(const string& xmlFile){
+
+ //string fullXmlFile = toDataPath(xmlFile);
+
+ bool loadOkay = doc.LoadFile(xmlFile);
+
+ //theo removed bool check as it would
+ //return false if the file exists but was
+ //empty
+
+ //our push pop level should be set to 0!
+ level = 0;
+
+ storedHandle = TiXmlHandle(&doc);
+ return loadOkay;
+}
+
+//---------------------------------------------------------
+bool xmlIO::saveFile(const string& xmlFile){
+
+ //string fullXmlFile = toDataPath(xmlFile);
+ return doc.SaveFile(xmlFile);
+}
+
+//---------------------------------------------------------
+bool xmlIO::saveFile(){
+ return doc.SaveFile();
+}
+
+//---------------------------------------------------------
+void xmlIO::clearTagContents(const string& tag, int which){
+ //we check it first to see if it exists
+ //otherwise setValue will make a new empty tag
+ if( tagExists(tag, which) )setValue(tag, "", which);
+}
+
+//---------------------------------------------------------
+void xmlIO::removeTag(const string& tag, int which){
+
+ vector<string> tokens = tokenize(tag,":");
+
+ //no tags so we return
+ if( tokens.size() == 0 ) return;
+
+ //grab the handle from the level we are at
+ //normally this is the doc but could be a pushed node
+ TiXmlHandle tagHandle = storedHandle;
+
+ if(which < 0) which = 0;
+
+ for(int x=0;x<(int)tokens.size();x++){
+
+ //we only support multi tags
+ //with same name at root level
+ if(x > 0) which = 0;
+
+ TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);
+
+ if ( !isRealHandle.ToNode() ) break;
+ else{
+ if (x == (int)tokens.size()-1){
+ //if we are at the last tag and it exists
+ //we use its parent to remove it - haha
+ tagHandle.ToNode()->RemoveChild( isRealHandle.ToNode() );
+ }
+ tagHandle = isRealHandle;
+ }
+ }
+}
+
+//---------------------------------------------------------
+int xmlIO::getValue(const string& tag, int defaultValue, int which){
+ TiXmlHandle valHandle(NULL);
+ if (readTag(tag, valHandle, which)){
+ return toInt(valHandle.ToText()->Value());
+ }
+ return defaultValue;
+}
+
+//---------------------------------------------------------
+double xmlIO::getValue(const string& tag, double defaultValue, int which){
+ TiXmlHandle valHandle(NULL);
+ if (readTag(tag, valHandle, which)){
+ return toFloat(valHandle.ToText()->Value());
+ }
+ return defaultValue;
+}
+
+//---------------------------------------------------------
+string xmlIO::getValue(const string& tag, const string& defaultValue, int which){
+ TiXmlHandle valHandle(NULL);
+ if (readTag(tag, valHandle, which)){
+ return valHandle.ToText()->ValueStr();
+ }
+ return defaultValue;
+}
+
+//---------------------------------------------------------
+bool xmlIO::readTag(const string& tag, TiXmlHandle& valHandle, int which){
+
+ vector<string> tokens = tokenize(tag,":");
+
+ TiXmlHandle tagHandle = storedHandle;
+ for(int x=0;x<(int)tokens.size();x++){
+ if(x == 0)tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else tagHandle = tagHandle.FirstChildElement( tokens.at(x) );
+ }
+
+ // once we've walked, let's get that value...
+ valHandle = tagHandle.Child( 0 );
+ return (valHandle.ToText() != NULL);
+}
+
+
+//---------------------------------------------------------
+bool xmlIO::pushTag(const string& tag, int which){
+
+ int pos = tag.find(":");
+
+ // Either find the tag specified, or the first tag if colon-seperated.
+ string tagToFind((pos > 0) ? tag.substr(0,pos) :tag);
+
+ //we only allow to push one tag at a time.
+ TiXmlHandle isRealHandle = storedHandle.ChildElement(tagToFind, which);
+
+ if( isRealHandle.ToNode() ){
+ storedHandle = isRealHandle;
+ level++;
+ return true;
+ }else{
+ //ofLog( OF_LOG_ERROR, "pushTag - <" + tag + "> tag not found");
+ }
+
+ return false;
+}
+
+//---------------------------------------------------------
+int xmlIO::popTag(){
+
+ if(level >= 1){
+ TiXmlHandle parent( (storedHandle.ToNode() )->Parent() );
+ storedHandle = parent;
+ level--;
+ }else{
+ storedHandle = TiXmlHandle(&doc);
+ level = 0;
+ }
+
+ return level;
+}
+
+//---------------------------------------------------------
+int xmlIO::getPushLevel(){
+ return level;
+}
+
+//---------------------------------------------------------
+bool xmlIO::tagExists(const string& tag, int which){
+
+ vector<string> tokens = tokenize(tag,":");
+
+ bool found = false;
+
+ //grab the handle from the level we are at
+ //normally this is the doc but could be a pushed node
+ TiXmlHandle tagHandle = storedHandle;
+
+ if(which < 0) which = 0;
+
+ for(int x=0;x<(int)tokens.size();x++){
+
+ //we only support multi tags
+ //with same name at root level
+ if(x > 0) which = 0;
+
+ TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);
+
+ //as soon as we find a tag that doesn't exist
+ //we return false;
+ if ( !isRealHandle.ToNode() ){
+ found = false;
+ break;
+ }
+ else{
+ found = true;
+ tagHandle = isRealHandle;
+ }
+ }
+
+ return found;
+}
+
+
+//---------------------------------------------------------
+int xmlIO::getNumTags(const string& tag){
+ //this only works for tags at the current root level
+
+ int pos = tag.find(":");
+
+ // Either find the tag specified, or the first tag if colon-seperated.
+ string tagToFind((pos > 0) ? tag.substr(0,pos) :tag);
+
+ //grab the handle from the level we are at
+ //normally this is the doc but could be a pushed node
+ //TiXmlHandle tagHandle = storedHandle;
+
+ int count = 0;
+
+ //ripped from tinyXML as doing this ourselves once is a LOT! faster
+ //than having this called n number of times in a while loop - we go from n*n iterations to n iterations
+
+ TiXmlElement* child = ( storedHandle.FirstChildElement( tagToFind ) ).ToElement();
+ for (count = 0; child; child = child->NextSiblingElement( tagToFind ), ++count){
+ //nothing
+ }
+
+ return count;
+}
+
+
+
+//---------------------------------------------------------
+int xmlIO::writeTag(const string& tag, const string& valueStr, int which){
+
+ vector<string> tokens = tokenize(tag,":");
+
+ // allocate on the stack
+ vector<TiXmlElement> elements;
+ elements.reserve(tokens.size());
+ for(int x=0;x<(int)tokens.size();x++)
+ elements.push_back(tokens.at(x));
+
+
+ TiXmlText Value(valueStr);
+
+ // search our way up - do these tags exist?
+ // find the first that DOESNT exist, then move backwards...
+ TiXmlHandle tagHandle = storedHandle;
+
+ bool addNewTag = false;
+ if(which == -1)addNewTag = true;
+
+ for(int x=0;x<(int)tokens.size();x++){
+
+ if( x > 0 ){
+ //multi tags of same name
+ //only for the root level
+ which = 0;
+ addNewTag = false;
+ }
+
+ TiXmlHandle isRealHandle = tagHandle.ChildElement( tokens.at(x), which);
+
+ if ( !isRealHandle.ToNode() || addNewTag){
+
+ for(int i=(int)tokens.size()-1;i>=x;i--){
+ if (i == (int)tokens.size()-1){
+ elements[i].InsertEndChild(Value);
+ } else {
+ elements[i].InsertEndChild(elements[i+1]);
+ }
+ }
+
+ tagHandle.ToNode()->InsertEndChild(elements[x]);
+
+ break;
+
+ } else {
+ tagHandle = isRealHandle;
+ if (x == (int)tokens.size()-1){
+ // what we want to change : TiXmlHandle valHandle = tagHandle.Child( 0 );
+ tagHandle.ToNode()->Clear();
+ tagHandle.ToNode()->InsertEndChild(Value);
+ }
+ }
+ }
+
+
+ //lets count how many tags with our name exist so we can return an index
+
+ //ripped from tinyXML as doing this ourselves once is a LOT! faster
+ //than having this called n number of times in a while loop - we go from n*n iterations to n iterations
+ int numSameTags;
+ TiXmlElement* child = ( storedHandle.FirstChildElement( tokens.at(0) ) ).ToElement();
+ for (numSameTags = 0; child; child = child->NextSiblingElement( tokens.at(0) ), ++numSameTags){
+ //nothing
+ }
+
+ return numSameTags;
+}
+
+//---------------------------------------------------------
+int xmlIO::setValue(const string& tag, int value, int which){
+ int tagID = writeTag(tag, toString(value).c_str(), which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::setValue(const string& tag, double value, int which){
+ int tagID = writeTag(tag, toString(value).c_str(), which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::setValue(const string& tag, const string& value, int which){
+ int tagID = writeTag(tag, value, which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addValue(const string& tag, int value){
+ int tagID = writeTag(tag, toString(value).c_str(), -1) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addValue(const string& tag, double value){
+ int tagID = writeTag(tag, toString(value).c_str(), -1) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addValue(const string& tag, const string& value){
+ int tagID = writeTag(tag, value, -1) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addTag(const string& tag){
+ int tagID = writeTag(tag, "", -1) -1;
+ return tagID;
+}
+
+/*******************
+* Attribute addons *
+*******************/
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, int value, int which){
+ int tagID = writeAttribute(tag, attribute, toString(value).c_str(), which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, int value){
+ return addAttribute(tag,attribute,value,-1);
+}
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, double value, int which){
+ int tagID = writeAttribute(tag, attribute, toString(value).c_str(), which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, double value){
+ return addAttribute(tag,attribute,value,-1);
+}
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, const string& value, int which){
+ int tagID = writeAttribute(tag, attribute, value, which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::addAttribute(const string& tag, const string& attribute, const string& value){
+ return addAttribute(tag,attribute,value,-1);
+}
+
+//---------------------------------------------------------
+void xmlIO::removeAttribute(const string& tag, const string& attribute, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+
+ if (tagHandle.ToElement()) {
+ TiXmlElement* elem = tagHandle.ToElement();
+ elem->RemoveAttribute(attribute);
+ }
+}
+
+//---------------------------------------------------------
+void xmlIO::clearTagAttributes(const string& tag, int which){
+ vector<string> names;
+ getAttributeNames( tag, names, which );
+ for (vector<string>::iterator i = names.begin(); i != names.end(); i++)
+ removeAttribute(tag, *i, which);
+}
+
+//---------------------------------------------------------
+int xmlIO::getNumAttributes(const string& tag, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+
+ if (tagHandle.ToElement()) {
+ TiXmlElement* elem = tagHandle.ToElement();
+
+ // Do stuff with the element here
+ TiXmlAttribute* first = elem->FirstAttribute();
+ if (first) {
+ int count = 1;
+ for (TiXmlAttribute* curr = first; curr != elem->LastAttribute(); curr = curr->Next())
+ count++;
+ return count;
+ }
+ }
+ return 0;
+}
+
+//---------------------------------------------------------
+bool xmlIO::attributeExists(const string& tag, const string& attribute, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+
+ if (tagHandle.ToElement()) {
+ TiXmlElement* elem = tagHandle.ToElement();
+
+ // Do stuff with the element here
+ for (TiXmlAttribute* a = elem->FirstAttribute(); a; a = a->Next()) {
+ if (a->Name() == attribute)
+ return true;
+ }
+ }
+ return false;
+}
+
+//---------------------------------------------------------
+bool xmlIO::getAttributeNames(const string& tag, vector<string>& outNames, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+
+ if (tagHandle.ToElement()) {
+ TiXmlElement* elem = tagHandle.ToElement();
+
+ // Do stuff with the element here
+ for (TiXmlAttribute* a = elem->FirstAttribute(); a; a = a->Next())
+ outNames.push_back( string(a->Name()) );
+ }
+ return !outNames.empty();
+}
+
+//---------------------------------------------------------
+int xmlIO::getAttribute(const string& tag, const string& attribute, int defaultValue, int which){
+ int value = defaultValue;
+ readIntAttribute(tag, attribute, value, which);
+ return value;
+}
+
+//---------------------------------------------------------
+double xmlIO::getAttribute(const string& tag, const string& attribute, double defaultValue, int which){
+ double value = defaultValue;
+ readDoubleAttribute(tag, attribute, value, which);
+ return value;
+}
+
+//---------------------------------------------------------
+string xmlIO::getAttribute(const string& tag, const string& attribute, const string& defaultValue, int which){
+ string value = defaultValue;
+ readStringAttribute(tag, attribute, value, which);
+ return value;
+}
+
+//---------------------------------------------------------
+int xmlIO::setAttribute(const string& tag, const string& attribute, int value, int which){
+ char valueStr[255];
+ sprintf(valueStr, "%i", value);
+ int tagID = writeAttribute(tag, attribute, valueStr, which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::setAttribute(const string& tag, const string& attribute, double value, int which){
+ char valueStr[255];
+ sprintf(valueStr, "%lf", value);
+ int tagID = writeAttribute(tag, attribute, valueStr, which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+int xmlIO::setAttribute(const string& tag, const string& attribute, const string& value, int which){
+ int tagID = writeAttribute(tag, attribute, value, which) -1;
+ return tagID;
+}
+
+//---------------------------------------------------------
+TiXmlElement* xmlIO::getElementForAttribute(const string& tag, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+ return tagHandle.ToElement();
+}
+
+//---------------------------------------------------------
+bool xmlIO::readIntAttribute(const string& tag, const string& attribute, int& outValue, int which){
+
+ TiXmlElement* elem = getElementForAttribute(tag, which);
+ if (elem)
+ return (elem->QueryIntAttribute(attribute, &outValue) == TIXML_SUCCESS);
+ return false;
+}
+
+//---------------------------------------------------------
+bool xmlIO::readDoubleAttribute(const string& tag, const string& attribute, double& outValue, int which){
+
+ TiXmlElement* elem = getElementForAttribute(tag, which);
+ if (elem)
+ return (elem->QueryDoubleAttribute(attribute, &outValue) == TIXML_SUCCESS);
+ return false;
+}
+
+//---------------------------------------------------------
+bool xmlIO::readStringAttribute(const string& tag, const string& attribute, string& outValue, int which){
+
+ TiXmlElement* elem = getElementForAttribute(tag, which);
+ if (elem)
+ {
+ const string* value = elem->Attribute(attribute);
+ if (value)
+ {
+ outValue = *value;
+ return true;
+ }
+ }
+ return false;
+}
+
+//---------------------------------------------------------
+int xmlIO::writeAttribute(const string& tag, const string& attribute, const string& valueString, int which){
+ vector<string> tokens = tokenize(tag,":");
+ TiXmlHandle tagHandle = storedHandle;
+ for (int x = 0; x < (int)tokens.size(); x++) {
+ if (x == 0)
+ tagHandle = tagHandle.ChildElement(tokens.at(x), which);
+ else
+ tagHandle = tagHandle.FirstChildElement(tokens.at(x));
+ }
+
+ int ret = 0;
+ if (tagHandle.ToElement()) {
+ TiXmlElement* elem = tagHandle.ToElement();
+ elem->SetAttribute(attribute, valueString);
+
+ // Do we really need this? We could just ignore this and remove the 'addAttribute' functions...
+ // Now, just get the ID.
+ int numSameTags;
+ TiXmlElement* child = ( storedHandle.FirstChildElement( tokens.at(0) ) ).ToElement();
+ for (numSameTags = 0; child; child = child->NextSiblingElement( tokens.at(0) ), ++numSameTags) {
+ // nothing
+ }
+ ret = numSameTags;
+ }
+ return ret;
+}
+
+//---------------------------------------------------------
+bool xmlIO::loadFromBuffer( string buffer )
+{
+
+ int size = buffer.size();
+
+ bool loadOkay = doc.ReadFromMemory( buffer.c_str(), size);//, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING);
+
+ return loadOkay;
+
+}
+//---------------------------------------------------------
+void xmlIO::copyXmlToString(string & str)
+{
+ TiXmlPrinter printer;
+ doc.Accept(&printer);
+
+ str = printer.CStr();
+}
+