|
|
@ -200,7 +200,7 @@ namespace xml { |
|
|
|
s+=***it; |
|
|
|
s+=***it; |
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
Node& Node::text(const std::string& txt) throw(tag_expected) { |
|
|
|
Node& Node::text(const std::string& txt) throw(tag_expected, type_mismatch) { |
|
|
|
throw tag_expected(*this, txt); |
|
|
|
throw tag_expected(*this, txt); |
|
|
|
} |
|
|
|
} |
|
|
|
Node& Node::append(const Node& o) throw(cannot_have_children) { |
|
|
|
Node& Node::append(const Node& o) throw(cannot_have_children) { |
|
|
@ -281,7 +281,8 @@ namespace xml { |
|
|
|
std::string Node::operator*() const throw() { |
|
|
|
std::string Node::operator*() const throw() { |
|
|
|
return text(); |
|
|
|
return text(); |
|
|
|
} |
|
|
|
} |
|
|
|
Node& Node::operator=(const std::string& contents) throw(tag_expected) { |
|
|
|
Node& Node::operator=(const std::string& contents) throw(tag_expected, |
|
|
|
|
|
|
|
type_mismatch) { |
|
|
|
return text(contents); |
|
|
|
return text(contents); |
|
|
|
} |
|
|
|
} |
|
|
|
std::ostream& operator<<(std::ostream& o, const Node& t) throw() { |
|
|
|
std::ostream& operator<<(std::ostream& o, const Node& t) throw() { |
|
|
@ -310,7 +311,8 @@ namespace xml { |
|
|
|
std::string String::text() const throw() { |
|
|
|
std::string String::text() const throw() { |
|
|
|
return _text; |
|
|
|
return _text; |
|
|
|
} |
|
|
|
} |
|
|
|
String& String::text(const std::string& txt) throw(tag_expected) { |
|
|
|
String& String::text(const std::string& txt) throw(tag_expected, |
|
|
|
|
|
|
|
type_mismatch) { |
|
|
|
_text = txt; |
|
|
|
_text = txt; |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
@ -337,13 +339,52 @@ namespace xml { |
|
|
|
return text(contents); |
|
|
|
return text(contents); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
UnsingedInteger::UnsingedInteger(std::string name, const std::string& text) throw(): |
|
|
|
|
|
|
|
Node(name), _text(text) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::auto_ptr<Node> UnsingedInteger::clone() const throw() { |
|
|
|
|
|
|
|
return std::auto_ptr<Node>(new UnsingedInteger(*this)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::string UnsingedInteger::text() const throw() { |
|
|
|
|
|
|
|
return _text; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
UnsingedInteger& UnsingedInteger::text(const std::string& txt) throw(tag_expected, |
|
|
|
|
|
|
|
type_mismatch) { |
|
|
|
|
|
|
|
_text = txt; |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::ostream& UnsingedInteger::out(std::ostream& o, unsigned int level) const throw() { |
|
|
|
|
|
|
|
if (_text.size()) { |
|
|
|
|
|
|
|
o<<std::string(level, '\t')<<'<'<<name(); |
|
|
|
|
|
|
|
for (Attributes::const_iterator it(_attributes.begin()); |
|
|
|
|
|
|
|
it!=_attributes.end(); ++it) |
|
|
|
|
|
|
|
o<<' '<<it->first<<"=\""<<it->second<<'"'; |
|
|
|
|
|
|
|
o<<'>'<<_text<<"</"<<name()<<'>'; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
o<<std::string(level, '\t')<<'<'<<name(); |
|
|
|
|
|
|
|
for (Attributes::const_iterator it(_attributes.begin()); |
|
|
|
|
|
|
|
it!=_attributes.end(); ++it) |
|
|
|
|
|
|
|
o<<' '<<it->first<<"=\""<<it->second<<'"'; |
|
|
|
|
|
|
|
o<<"/>"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return o; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
UnsingedInteger& UnsingedInteger::append(const Node& o) throw(cannot_have_children) { |
|
|
|
|
|
|
|
throw cannot_have_children(*this, o); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Node& UnsingedInteger::operator=(const std::string& contents) throw() { |
|
|
|
|
|
|
|
return text(contents); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
Factory::Factory(const Node& t) throw(): _template(t.clone()) {} |
|
|
|
Factory::Factory(const Node& t) throw(): _template(t.clone()) {} |
|
|
|
const Node& Factory::operator*() const throw() { |
|
|
|
const Node& Factory::operator*() const throw() { |
|
|
|
return *_template; |
|
|
|
return *_template; |
|
|
|
} |
|
|
|
} |
|
|
|
std::auto_ptr<Node> Factory::read(std::istream& is) |
|
|
|
std::auto_ptr<Node> Factory::read(std::istream& is) |
|
|
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, second_slash_in_tag, |
|
|
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch, |
|
|
|
|
|
|
|
second_slash_in_tag, |
|
|
|
character_after_slash, missing_end_tag, attribute_value_not_quoted, |
|
|
|
character_after_slash, missing_end_tag, attribute_value_not_quoted, |
|
|
|
access_error, empty_stream, duplicate_attribute, |
|
|
|
access_error, empty_stream, duplicate_attribute, |
|
|
|
attributes_in_end_tag) { |
|
|
|
attributes_in_end_tag) { |
|
|
@ -356,18 +397,19 @@ namespace xml { |
|
|
|
throw empty_stream(*node, is, res); |
|
|
|
throw empty_stream(*node, is, res); |
|
|
|
} |
|
|
|
} |
|
|
|
*node<<res.attributes; |
|
|
|
*node<<res.attributes; |
|
|
|
switch (res.type) { |
|
|
|
while (true) switch (res.type) { |
|
|
|
case END: throw wrong_end_tag(*node, is, res); |
|
|
|
case END: throw wrong_end_tag(*node, is, res); |
|
|
|
case EMPTY: return node; // empty
|
|
|
|
case EMPTY: return node; // empty
|
|
|
|
case START: return read(is, *_template); |
|
|
|
case START: return read(is, *_template); |
|
|
|
|
|
|
|
case SPECIAL: break; //! @todo ignored could be stored
|
|
|
|
} |
|
|
|
} |
|
|
|
abort(); // coding error: should not reach here
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
bool Factory::ws(char c) const throw() { |
|
|
|
bool Factory::ws(char c) const throw() { |
|
|
|
return c==' '||c=='\t'||c=='\n'||c=='\r'; |
|
|
|
return c==' '||c=='\t'||c=='\n'||c=='\r'; |
|
|
|
} |
|
|
|
} |
|
|
|
std::auto_ptr<Node> Factory::read(std::istream& is, const Node& node) |
|
|
|
std::auto_ptr<Node> Factory::read(std::istream& is, const Node& node) |
|
|
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, second_slash_in_tag, |
|
|
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch, |
|
|
|
|
|
|
|
second_slash_in_tag, |
|
|
|
character_after_slash, missing_end_tag, attribute_value_not_quoted, |
|
|
|
character_after_slash, missing_end_tag, attribute_value_not_quoted, |
|
|
|
access_error, duplicate_attribute, attributes_in_end_tag) { |
|
|
|
access_error, duplicate_attribute, attributes_in_end_tag) { |
|
|
|
std::auto_ptr<Node> result(node.clone()); |
|
|
|
std::auto_ptr<Node> result(node.clone()); |
|
|
@ -387,6 +429,7 @@ namespace xml { |
|
|
|
case START: { |
|
|
|
case START: { |
|
|
|
*result<<(*read(is, node[res.name])<<res.attributes); |
|
|
|
*result<<(*read(is, node[res.name])<<res.attributes); |
|
|
|
} break; |
|
|
|
} break; |
|
|
|
|
|
|
|
case SPECIAL: break; //! @todo ignored could be stored
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return result; |
|
|
|
return result; |
|
|
@ -401,8 +444,7 @@ namespace xml { |
|
|
|
if (!is) throw missing_end_tag(position, is, tag); |
|
|
|
if (!is) throw missing_end_tag(position, is, tag); |
|
|
|
if (c!='<') do tag.text+=c; while (is && is.get(c) && c!='<'); |
|
|
|
if (c!='<') do tag.text+=c; while (is && is.get(c) && c!='<'); |
|
|
|
bool nameRead(false); |
|
|
|
bool nameRead(false); |
|
|
|
while (is && is.get(c) && c!='>') { |
|
|
|
for (char last(c); is && is.get(c) && c!='>'; last = c) switch (c) { |
|
|
|
switch (c) { |
|
|
|
|
|
|
|
case ' ': case '\t': case '\n': case '\r': |
|
|
|
case ' ': case '\t': case '\n': case '\r': |
|
|
|
if (!nameRead && tag.name.size()) nameRead=true; |
|
|
|
if (!nameRead && tag.name.size()) nameRead=true; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -411,6 +453,11 @@ namespace xml { |
|
|
|
if (tag.type!=START) throw second_slash_in_tag(position, is, tag, c); |
|
|
|
if (tag.type!=START) throw second_slash_in_tag(position, is, tag, c); |
|
|
|
tag.type = nameRead?EMPTY:END; |
|
|
|
tag.type = nameRead?EMPTY:END; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case '!': case '?': |
|
|
|
|
|
|
|
if (last=='<') { // <! tag or <?xml.. starts
|
|
|
|
|
|
|
|
do tag.special+=c; while (c!='>' && is && is.get(c)); |
|
|
|
|
|
|
|
return tag; |
|
|
|
|
|
|
|
} |
|
|
|
default: |
|
|
|
default: |
|
|
|
if (tag.type==EMPTY) throw character_after_slash(position, is, tag, c); |
|
|
|
if (tag.type==EMPTY) throw character_after_slash(position, is, tag, c); |
|
|
|
if (nameRead) { // read attribute
|
|
|
|
if (nameRead) { // read attribute
|
|
|
@ -431,7 +478,7 @@ namespace xml { |
|
|
|
} else { // part of a tag name
|
|
|
|
} else { // part of a tag name
|
|
|
|
tag.name+=c; |
|
|
|
tag.name+=c; |
|
|
|
} |
|
|
|
} |
|
|
|
}} |
|
|
|
} |
|
|
|
return tag; |
|
|
|
return tag; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|