check node number limits
This commit is contained in:
@@ -118,6 +118,14 @@ namespace xml {
|
|||||||
Node* _node;
|
Node* _node;
|
||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
class empty_attribute_list: public exception {
|
||||||
|
public:
|
||||||
|
empty_attribute_list(const std::string& name) throw():
|
||||||
|
exception("list of attribute is empty access to first element failed"
|
||||||
|
"\nattribute: "+name) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
class no_parent: public exception {
|
class no_parent: public exception {
|
||||||
public:
|
public:
|
||||||
no_parent(const Node& t) throw(): exception("node has no parent", t) {}
|
no_parent(const Node& t) throw(): exception("node has no parent", t) {}
|
||||||
@@ -175,6 +183,8 @@ namespace xml {
|
|||||||
public:
|
public:
|
||||||
stream_error(const std::string& reason, const Node& t,
|
stream_error(const std::string& reason, const Node& t,
|
||||||
std::istream& is, const Tag& tag, char c=0) throw();
|
std::istream& is, const Tag& tag, char c=0) throw();
|
||||||
|
stream_error(const std::string& reason, const Node& t,
|
||||||
|
std::istream& is) throw();
|
||||||
~stream_error() throw();
|
~stream_error() throw();
|
||||||
const char* what() const throw();
|
const char* what() const throw();
|
||||||
private:
|
private:
|
||||||
@@ -264,16 +274,19 @@ namespace xml {
|
|||||||
class wrong_node_number: public stream_error {
|
class wrong_node_number: public stream_error {
|
||||||
public:
|
public:
|
||||||
wrong_node_number(const Node& t, std::istream& is,
|
wrong_node_number(const Node& t, std::istream& is,
|
||||||
const Tag& tag, const std::string& name,
|
const std::string& name,
|
||||||
unsigned long num,
|
unsigned long num,
|
||||||
unsigned long min, unsigned long max) throw():
|
unsigned long min, unsigned long max) throw():
|
||||||
stream_error(((std::stringstream&)
|
stream_error("wrong number of child nodes\nname of child: "+name
|
||||||
(std::stringstream()
|
+"\nnumber of nodes: "+conv(num)
|
||||||
<<"wrong number of child nodes\nname of child: "<<name
|
+"\nminimuml number: "+conv(min)
|
||||||
<<"\nnumber of nodes: "<<num
|
+"\nmaximum number: "+conv(max), t, is) {
|
||||||
<<"\nminimuml number: "<<min
|
}
|
||||||
<<"\nmaximum number: "<<max)).str(),
|
private:
|
||||||
t, is, tag, 0) {
|
static std::string conv(unsigned long i) throw() {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss<<i;
|
||||||
|
return ss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -309,6 +322,8 @@ namespace xml {
|
|||||||
operator unsigned long() const throw();
|
operator unsigned long() const throw();
|
||||||
operator List() const throw();
|
operator List() const throw();
|
||||||
List toList(const std::string& separators=" \t\n\r") const throw();
|
List toList(const std::string& separators=" \t\n\r") const throw();
|
||||||
|
std::string front(const std::string& separators=" \t\n\r") const
|
||||||
|
throw(empty_attribute_list);
|
||||||
private:
|
private:
|
||||||
Value(); // not implemented, key must always be given
|
Value(); // not implemented, key must always be given
|
||||||
};
|
};
|
||||||
@@ -358,6 +373,10 @@ namespace xml {
|
|||||||
virtual Node& set(const Attributes& o) throw();
|
virtual Node& set(const Attributes& o) throw();
|
||||||
Node& clear() throw ();
|
Node& clear() throw ();
|
||||||
std::string name() const throw();
|
std::string name() const throw();
|
||||||
|
Node& min(size_type m) throw();
|
||||||
|
size_type min() const throw();
|
||||||
|
Node& max(size_type m) throw();
|
||||||
|
size_type max() const throw();
|
||||||
bool isChild() const throw();
|
bool isChild() const throw();
|
||||||
Node& parent() const throw(no_parent);
|
Node& parent() const throw(no_parent);
|
||||||
bool hasAttr(const std::string& name) const throw();
|
bool hasAttr(const std::string& name) const throw();
|
||||||
@@ -398,14 +417,16 @@ namespace xml {
|
|||||||
Contents _contents;
|
Contents _contents;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
Node* _parent;
|
Node* _parent;
|
||||||
typedef std::pair<Node::size_type, Node::size_type> Limits;
|
size_type _min;
|
||||||
Limits _limits;
|
size_type _max;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class String: public Node {
|
class String: public Node {
|
||||||
public:
|
public:
|
||||||
String(std::string name, const std::string& text = std::string()) throw();
|
String(std::string name, size_type min=0, size_type max=0) throw();
|
||||||
|
String(std::string name, const std::string& text,
|
||||||
|
size_type min=0, size_type max=0) throw();
|
||||||
virtual std::auto_ptr<Node> clone() const throw();
|
virtual std::auto_ptr<Node> clone() const throw();
|
||||||
virtual ~String() throw() {}
|
virtual ~String() throw() {}
|
||||||
virtual std::string text() const throw();
|
virtual std::string text() const throw();
|
||||||
@@ -422,7 +443,8 @@ namespace xml {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class UnsignedInteger: public String {
|
class UnsignedInteger: public String {
|
||||||
public:
|
public:
|
||||||
UnsignedInteger(std::string name, unsigned long i = 0) throw();
|
UnsignedInteger(std::string name, unsigned long i=0,
|
||||||
|
size_type min=0, size_type max=0) throw();
|
||||||
virtual std::auto_ptr<Node> clone() const throw();
|
virtual std::auto_ptr<Node> clone() const throw();
|
||||||
virtual ~UnsignedInteger() throw() {}
|
virtual ~UnsignedInteger() throw() {}
|
||||||
virtual UnsignedInteger& text(const std::string& txt)
|
virtual UnsignedInteger& text(const std::string& txt)
|
||||||
@@ -456,12 +478,15 @@ namespace xml {
|
|||||||
attributes_in_end_tag,
|
attributes_in_end_tag,
|
||||||
illegal_attribute, mandatory_attribute_missing,
|
illegal_attribute, mandatory_attribute_missing,
|
||||||
wrong_node_number);
|
wrong_node_number);
|
||||||
|
std::auto_ptr<Node> checkChildren(const xml::Node& tpl,
|
||||||
|
std::auto_ptr<Node> node,
|
||||||
|
std::istream& is) const
|
||||||
|
throw(wrong_node_number);
|
||||||
Tag tag(std::istream& is, const Node& position)
|
Tag tag(std::istream& is, const Node& position)
|
||||||
throw(second_slash_in_tag, wrong_start_tag, character_after_slash,
|
throw(second_slash_in_tag, wrong_start_tag, character_after_slash,
|
||||||
missing_end_tag, attributes_in_end_tag, tag_expected,
|
missing_end_tag, attributes_in_end_tag, tag_expected,
|
||||||
attribute_value_not_quoted, access_error, duplicate_attribute,
|
attribute_value_not_quoted, access_error, duplicate_attribute,
|
||||||
illegal_attribute, mandatory_attribute_missing,
|
illegal_attribute, mandatory_attribute_missing);
|
||||||
wrong_node_number);
|
|
||||||
Node _template;
|
Node _template;
|
||||||
unsigned long _line;
|
unsigned long _line;
|
||||||
long _open;
|
long _open;
|
||||||
|
120
src/xml.cxx
120
src/xml.cxx
@@ -10,6 +10,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
class MethodTrace {
|
class MethodTrace {
|
||||||
public:
|
public:
|
||||||
@@ -33,7 +34,7 @@ class MethodTrace {
|
|||||||
};
|
};
|
||||||
unsigned int MethodTrace::_level(0);
|
unsigned int MethodTrace::_level(0);
|
||||||
#define TRACE MethodTrace XXX_METHOD(this, __PRETTY_FUNCTION__)
|
#define TRACE MethodTrace XXX_METHOD(this, __PRETTY_FUNCTION__)
|
||||||
#define LOG(X) std::cout<<__PRETTY_FUNCTION__<<"\t**** "<<X<<std::endl
|
#define LOG(X) std::clog<<__PRETTY_FUNCTION__<<"\t**** "<<X<<std::endl
|
||||||
|
|
||||||
namespace xml {
|
namespace xml {
|
||||||
|
|
||||||
@@ -105,6 +106,10 @@ namespace xml {
|
|||||||
std::istream& is, const Tag& tag, char c) throw():
|
std::istream& is, const Tag& tag, char c) throw():
|
||||||
exception(reason, t), _pos(is.tellg()), _tag(new Tag(tag)), _char(c) {
|
exception(reason, t), _pos(is.tellg()), _tag(new Tag(tag)), _char(c) {
|
||||||
}
|
}
|
||||||
|
stream_error::stream_error(const std::string& reason, const Node& t,
|
||||||
|
std::istream& is) throw():
|
||||||
|
exception(reason, t), _pos(is.tellg()), _tag(0), _char(0) {
|
||||||
|
}
|
||||||
stream_error::~stream_error() throw() {
|
stream_error::~stream_error() throw() {
|
||||||
delete _tag;
|
delete _tag;
|
||||||
}
|
}
|
||||||
@@ -117,12 +122,14 @@ namespace xml {
|
|||||||
if (_char)
|
if (_char)
|
||||||
ss<<"\nactual character: "<<(_char>31?_char:'?')
|
ss<<"\nactual character: "<<(_char>31?_char:'?')
|
||||||
<<" (ascii="<<(int)_char<<")";
|
<<" (ascii="<<(int)_char<<")";
|
||||||
ss<<"\ntag type: "<<(_tag->type==START?"START"
|
if (_tag) {
|
||||||
:(_tag->type==END?"END"
|
ss<<"\ntag type: "<<(_tag->type==START?"START"
|
||||||
:(_tag->type==EMPTY?"EMPTY"
|
:(_tag->type==END?"END"
|
||||||
:"???? <UNKNOWN>")));
|
:(_tag->type==EMPTY?"EMPTY"
|
||||||
if (_tag->name.size()) ss<<"\nnode name read: "<<_tag->name;
|
:"???? <UNKNOWN>")));
|
||||||
if (_tag->text.size()) ss<<"\ncontained text: "<<_tag->text;
|
if (_tag->name.size()) ss<<"\nnode name read: "<<_tag->name;
|
||||||
|
if (_tag->text.size()) ss<<"\ncontained text: "<<_tag->text;
|
||||||
|
}
|
||||||
w = ss.str();
|
w = ss.str();
|
||||||
}
|
}
|
||||||
return w.c_str();
|
return w.c_str();
|
||||||
@@ -193,6 +200,12 @@ namespace xml {
|
|||||||
l.push_back(second.substr(it, pos-it));
|
l.push_back(second.substr(it, pos-it));
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
std::string Attributes::Value::front(const std::string& separators) const
|
||||||
|
throw(empty_attribute_list) {
|
||||||
|
List l(toList(separators));
|
||||||
|
if (!l.size()) throw empty_attribute_list(first);
|
||||||
|
return l.front();
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//! Empty attribute list
|
//! Empty attribute list
|
||||||
Attributes::Attributes() throw() {}
|
Attributes::Attributes() throw() {}
|
||||||
@@ -219,12 +232,13 @@ namespace xml {
|
|||||||
//! Nodes must be given a name.
|
//! Nodes must be given a name.
|
||||||
/*! Unnamed nodes are not allowed, therefore there's no default
|
/*! Unnamed nodes are not allowed, therefore there's no default
|
||||||
constructor. */
|
constructor. */
|
||||||
Node::Node(std::string name, size_type min, size_type max) throw():
|
Node::Node(std::string name,
|
||||||
_name(name), _parent(0), _limits(min, max) {
|
Node::size_type min, Node::size_type max) throw():
|
||||||
|
_name(name), _parent(0), _min(min), _max(max) {
|
||||||
}
|
}
|
||||||
Node::Node(const Node& o) throw():
|
Node::Node(const Node& o) throw():
|
||||||
_attributes(o._attributes), _name(o.name()), _parent(0),
|
_attributes(o._attributes), _name(o.name()), _parent(0),
|
||||||
_limits(o._limits) {
|
_min(o._min), _max(o._max) {
|
||||||
for (Contents::const_iterator it(o._contents.begin());
|
for (Contents::const_iterator it(o._contents.begin());
|
||||||
it!=o._contents.end(); ++it)
|
it!=o._contents.end(); ++it)
|
||||||
_contents.push_back((*it)->clone(this).release());
|
_contents.push_back((*it)->clone(this).release());
|
||||||
@@ -233,7 +247,8 @@ namespace xml {
|
|||||||
_attributes=o._attributes;
|
_attributes=o._attributes;
|
||||||
_name = o.name();
|
_name = o.name();
|
||||||
_parent = 0;
|
_parent = 0;
|
||||||
_limits = o._limits;
|
_min = o._min;
|
||||||
|
_max = o._max;
|
||||||
for (Contents::const_iterator it(o._contents.begin());
|
for (Contents::const_iterator it(o._contents.begin());
|
||||||
it!=o._contents.end(); ++it)
|
it!=o._contents.end(); ++it)
|
||||||
_contents.push_back((*it)->clone(this).release());
|
_contents.push_back((*it)->clone(this).release());
|
||||||
@@ -296,6 +311,20 @@ namespace xml {
|
|||||||
std::string Node::name() const throw() {
|
std::string Node::name() const throw() {
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
Node& Node::min(Node::size_type m) throw() {
|
||||||
|
_min = m;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Node::size_type Node::min() const throw() {
|
||||||
|
return _min;
|
||||||
|
}
|
||||||
|
Node& Node::max(Node::size_type m) throw() {
|
||||||
|
_max = m;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Node::size_type Node::max() const throw() {
|
||||||
|
return _max;
|
||||||
|
}
|
||||||
bool Node::isChild() const throw() {
|
bool Node::isChild() const throw() {
|
||||||
return _parent;
|
return _parent;
|
||||||
}
|
}
|
||||||
@@ -336,8 +365,8 @@ namespace xml {
|
|||||||
return _attributes;
|
return _attributes;
|
||||||
}
|
}
|
||||||
Node& Node::limits(size_type min, size_type max) throw() {
|
Node& Node::limits(size_type min, size_type max) throw() {
|
||||||
_limits.first = min;
|
_min = min;
|
||||||
_limits.second = max;
|
_min = max;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Node::List Node::list(const std::string& name) const throw() {
|
Node::List Node::list(const std::string& name) const throw() {
|
||||||
@@ -405,8 +434,13 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
String::String(std::string name, const std::string& text) throw():
|
String::String(std::string name,
|
||||||
Node(name), _text(text) {
|
Node::size_type min, Node::size_type max) throw():
|
||||||
|
Node(name, min, max) {
|
||||||
|
}
|
||||||
|
String::String(std::string name, const std::string& text,
|
||||||
|
Node::size_type min, Node::size_type max) throw():
|
||||||
|
Node(name, min, max), _text(text) {
|
||||||
}
|
}
|
||||||
std::auto_ptr<Node> String::clone() const throw() {
|
std::auto_ptr<Node> String::clone() const throw() {
|
||||||
return std::auto_ptr<Node>(new String(*this));
|
return std::auto_ptr<Node>(new String(*this));
|
||||||
@@ -443,9 +477,11 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
UnsignedInteger::UnsignedInteger(std::string name, unsigned long i) throw():
|
UnsignedInteger::UnsignedInteger(std::string name, unsigned long i,
|
||||||
|
size_type min, size_type max) throw():
|
||||||
String(name,
|
String(name,
|
||||||
dynamic_cast<std::stringstream&>(std::stringstream()<<i).str()) {
|
dynamic_cast<std::stringstream&>(std::stringstream()<<i).str(),
|
||||||
|
min, max) {
|
||||||
}
|
}
|
||||||
std::auto_ptr<Node> UnsignedInteger::clone() const throw() {
|
std::auto_ptr<Node> UnsignedInteger::clone() const throw() {
|
||||||
return std::auto_ptr<Node>(new UnsignedInteger(*this));
|
return std::auto_ptr<Node>(new UnsignedInteger(*this));
|
||||||
@@ -482,7 +518,10 @@ namespace xml {
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Factory::Factory(const Node& t) throw():
|
Factory::Factory(const Node& t) throw():
|
||||||
_template(xml::Node("<xml::start>")<<t), _line(0) {}
|
_template(xml::Node("<xml::start>")<<t), _line(0) {
|
||||||
|
_template[0].min(1);
|
||||||
|
_template[0].max(1);
|
||||||
|
}
|
||||||
const Node& Factory::operator*() const throw() {
|
const Node& Factory::operator*() const throw() {
|
||||||
return _template[0];
|
return _template[0];
|
||||||
}
|
}
|
||||||
@@ -500,21 +539,6 @@ namespace xml {
|
|||||||
if (node->children()==0)
|
if (node->children()==0)
|
||||||
throw tag_expected(_template[0], _template[0].name());
|
throw tag_expected(_template[0], _template[0].name());
|
||||||
return (*node)[0].clone();
|
return (*node)[0].clone();
|
||||||
/*node->clear();
|
|
||||||
Tag res;
|
|
||||||
while (true) {
|
|
||||||
res = tag(is, _template);
|
|
||||||
*node<<res.attributes;
|
|
||||||
switch (res.type) {
|
|
||||||
case END: throw wrong_end_tag(*node, is, res);
|
|
||||||
case EMPTY:
|
|
||||||
return node; // empty
|
|
||||||
case START:
|
|
||||||
return read(is, _template[res.name]);
|
|
||||||
//! @todo store instead of ignore
|
|
||||||
case SPECIAL: break;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
e.line(_line);
|
e.line(_line);
|
||||||
throw;
|
throw;
|
||||||
@@ -545,22 +569,37 @@ namespace xml {
|
|||||||
if (res.name!=node.name()) throw wrong_end_tag(node, is, res);
|
if (res.name!=node.name()) throw wrong_end_tag(node, is, res);
|
||||||
} return result;
|
} return result;
|
||||||
case EMPTY: {
|
case EMPTY: {
|
||||||
*result<<(node[res.name].clone()->clear()<<res.attributes);
|
std::auto_ptr<Node> current(node[res.name].clone());
|
||||||
|
current->clear()<<res.attributes;
|
||||||
|
*result<<*checkChildren(node[res.name], current, is);
|
||||||
} break;
|
} break;
|
||||||
case START: {
|
case START: {
|
||||||
++_open;
|
++_open;
|
||||||
*result<<(*read(is, node[res.name])<<res.attributes);
|
*result<<(*checkChildren(node[res.name], read(is, node[res.name]), is)
|
||||||
|
<<res.attributes);
|
||||||
} break;
|
} break;
|
||||||
case SPECIAL: break; //! @todo ignored could be stored
|
case SPECIAL: break; //! @todo ignored could be stored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::auto_ptr<Node> Factory::checkChildren(const xml::Node& tpl,
|
||||||
|
std::auto_ptr<Node> node,
|
||||||
|
std::istream& is) const
|
||||||
|
throw(wrong_node_number) {
|
||||||
|
for (Node::size_type i(0); i<tpl.children(); ++i)
|
||||||
|
if (tpl[i].min()>0 && node->list(tpl[i].name()).size()<tpl[i].min()
|
||||||
|
|| 0<tpl[i].max() && tpl[i].max()<node->list(tpl[i].name()).size())
|
||||||
|
throw wrong_node_number(*node, is, tpl[i].name(),
|
||||||
|
node->list(tpl[i].name()).size(),
|
||||||
|
tpl[i].min(), tpl[i].max());
|
||||||
|
return node;
|
||||||
|
}
|
||||||
Tag Factory::tag(std::istream& is, const Node& position)
|
Tag Factory::tag(std::istream& is, const Node& position)
|
||||||
throw(second_slash_in_tag, character_after_slash, tag_expected,
|
throw(second_slash_in_tag, character_after_slash, tag_expected,
|
||||||
missing_end_tag, attribute_value_not_quoted,
|
missing_end_tag, attribute_value_not_quoted,
|
||||||
access_error, duplicate_attribute, attributes_in_end_tag,
|
access_error, duplicate_attribute, attributes_in_end_tag,
|
||||||
illegal_attribute, mandatory_attribute_missing,
|
illegal_attribute, mandatory_attribute_missing,
|
||||||
wrong_start_tag, wrong_node_number) {
|
wrong_start_tag) {
|
||||||
char c(0);
|
char c(0);
|
||||||
Tag tag((Tag){"", START, "", Attributes(), "", false});
|
Tag tag((Tag){"", START, "", Attributes(), "", false});
|
||||||
while (is && is.get(c) && ws(c)); // skip ws
|
while (is && is.get(c) && ws(c)); // skip ws
|
||||||
@@ -596,7 +635,8 @@ namespace xml {
|
|||||||
if (nameRead) { // read attribute
|
if (nameRead) { // read attribute
|
||||||
if (tag.type!=START) throw attributes_in_end_tag(position, is, tag);
|
if (tag.type!=START) throw attributes_in_end_tag(position, is, tag);
|
||||||
std::string attrname(1, c), attrvalue;
|
std::string attrname(1, c), attrvalue;
|
||||||
while (is && is.get(c) && c!='=' && c!='>' && !ws(c)) attrname+=c;
|
while (is && is.get(c) && c!='=' && c!='>' && c!='/'
|
||||||
|
&& !ws(c)) attrname+=c;
|
||||||
while (ws(c) && is && is.get(c)); // skip ws, search '='
|
while (ws(c) && is && is.get(c)); // skip ws, search '='
|
||||||
if (c=='=') { // get the value
|
if (c=='=') { // get the value
|
||||||
while (is && is.get(c) && ws(c)); // skip ws
|
while (is && is.get(c) && ws(c)); // skip ws
|
||||||
@@ -629,9 +669,9 @@ namespace xml {
|
|||||||
else
|
else
|
||||||
throw tag_expected(position, tag.text);
|
throw tag_expected(position, tag.text);
|
||||||
}
|
}
|
||||||
for (Attributes::const_iterator it
|
const xml::Node& node(position[tag.name]);
|
||||||
(position[tag.name].attributes().begin());
|
for (Attributes::const_iterator it(node.attributes().begin());
|
||||||
it!=position[tag.name].attributes().end(); ++it)
|
it!=node.attributes().end(); ++it)
|
||||||
if (tag.attributes.find(it->first)==tag.attributes.end()) {
|
if (tag.attributes.find(it->first)==tag.attributes.end()) {
|
||||||
if (it->second=="xml::mandatory")
|
if (it->second=="xml::mandatory")
|
||||||
throw mandatory_attribute_missing(position, is, tag, it->first);
|
throw mandatory_attribute_missing(position, is, tag, it->first);
|
||||||
|
@@ -265,32 +265,49 @@ class ComplexTest: public CppUnit::TestFixture {
|
|||||||
} {
|
} {
|
||||||
std::stringstream file("<base one two three></base>");
|
std::stringstream file("<base one two three></base>");
|
||||||
CPPUNIT_ASSERT_THROW(factory.read(file), xml::illegal_attribute);
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::illegal_attribute);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base one/>");
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(factory.read(file));
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base one=\"abc def ghi\"/>");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("abc"),
|
||||||
|
(*factory.read(file)).attribute("one").front());
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base one=\"abc def ghi\"/>");
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3,
|
||||||
|
(*factory.read(file)).attribute("one").toList()
|
||||||
|
.size());
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base one=\"abc\"/>");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("abc"),
|
||||||
|
(*factory.read(file)).attribute("one").front());
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base one/>");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string(""),
|
||||||
|
(*factory.read(file)).attribute("one").front());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ranges() {
|
void ranges() {
|
||||||
xml::Factory factory(xml::Node("base", 2, 2)
|
xml::Factory factory(xml::Node("base")
|
||||||
<<xml::Node("mandatory", 1)
|
<<xml::Node("mandatory", 1, 1)
|
||||||
<<xml::Node("optional", 0, 1));
|
<<xml::Node("optional", 0, 1));
|
||||||
{
|
{
|
||||||
std::stringstream file("<base><mandatory></mandatory></base>"
|
std::stringstream file("<base><mandatory/><optional/></base>");
|
||||||
"<base><mandatory/><optional/></base>");
|
|
||||||
CPPUNIT_ASSERT_NO_THROW(factory.read(file));
|
CPPUNIT_ASSERT_NO_THROW(factory.read(file));
|
||||||
} /*{
|
} {
|
||||||
std::stringstream file("<base><mandatory></mandatory></base>"
|
std::stringstream file("<base><optional/></base>");
|
||||||
"<base><mandatory/><optional/></base>");
|
|
||||||
CPPUNIT_ASSERT_THROW(factory.read(file),
|
CPPUNIT_ASSERT_THROW(factory.read(file),
|
||||||
xml::wrong_node_number);
|
xml::wrong_node_number);
|
||||||
} {
|
} {
|
||||||
std::stringstream file("<base><mandatory></mandatory></base>"
|
std::stringstream file("<base><mandatory/><optional/>"
|
||||||
"<base><mandatory/><optional/></base>");
|
"<optional/></base>");
|
||||||
CPPUNIT_ASSERT_THROW(factory.read(file),
|
CPPUNIT_ASSERT_THROW(factory.read(file),
|
||||||
xml::wrong_node_number);
|
xml::wrong_node_number);
|
||||||
} {
|
} {
|
||||||
std::stringstream file("<base><mandatory></mandatory></base>"
|
std::stringstream file("<base><mandatory/><mandatory/></base>");
|
||||||
"<base><mandatory/><optional/></base>");
|
|
||||||
CPPUNIT_ASSERT_THROW(factory.read(file),
|
CPPUNIT_ASSERT_THROW(factory.read(file),
|
||||||
xml::wrong_node_number);
|
xml::wrong_node_number);
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
CPPUNIT_TEST_SUITE(ComplexTest);
|
CPPUNIT_TEST_SUITE(ComplexTest);
|
||||||
CPPUNIT_TEST(nodes);
|
CPPUNIT_TEST(nodes);
|
||||||
|
Reference in New Issue
Block a user