/*! @file @id $Id$ */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 #include #include #include #include #include class MethodTrace { public: MethodTrace(const void* addr, const std::string& name) throw(): _addr(addr), _name(name) { std::clog<second = value; _active = end(); return *this; } //================================================================= EXCEPTIONS //---------------------------------------------------------------------------- exception::exception(std::string reason, const Node& t) throw(): _what(reason), _node(t.clone().release()) { } exception::~exception() throw() { delete _node; } const char* exception::what() const throw() { static std::string w; if (!w.size()) { if (_node) if (_node->isChild()) w = _what+"\ntag: "+_node->name()+"\nparent: "+_node->parent().name(); else w = _what+"\ntag: "+_node->name()+" (root element)"; else w = _what; } return w.c_str(); } //---------------------------------------------------------------------------- access_error::access_error(const Node& t, const std::string& name) throw(): exception("child not available", t), _name(name) { } const char* access_error::what() const throw() { static std::string w; if (!w.size()) w = std::string(exception::what())+"\nchild name: "+_name; return w.c_str(); } //---------------------------------------------------------------------------- out_of_range::out_of_range(const Node& t, size_t pos) throw(): exception("child not available", t), _pos(pos) { } const char* out_of_range::what() const throw() { static std::stringstream w; if (!w.str().size()) w<name(); return w.c_str(); } //---------------------------------------------------------------------------- stream_error::stream_error(const std::string& reason, const Node& t, std::istream& is, Tag tag, char c) throw(): exception(reason, t), _pos(is.tellg()), _tag(tag), _char(c) { } const char* stream_error::what() const throw() { static std::string w; if (!w.size()) { std::stringstream ss; ss<31?_char:'?') <<" (ascii="<<(int)_char<<")"; ss<<"\ntag type: "<<(_tag.type==START?"START" :(_tag.type==END?"END" :(_tag.type==EMPTY?"EMPTY" :"???? "))); if (_tag.name.size()) ss<<"\nnode name read: "<<_tag.name; if (_tag.text.size()) ss<<"\ncontained text: "<<_tag.text; w = ss.str(); } return w.c_str(); } //============================================================================ //---------------------------------------------------------------------------- Node::Node(std::string name) throw(): _name(name), _parent(0) { } Node::Node(const Node& o) throw(): _attributes(o._attributes), _name(o.name()), _parent(0) { for (Contents::const_iterator it(o._contents.begin()); it!=o._contents.end(); ++it) _contents.push_back((*it)->clone(this).release()); } Node& Node::operator=(const Node& o) throw() { _attributes=o._attributes; _name = o.name(); _parent = 0; for (Contents::const_iterator it(o._contents.begin()); it!=o._contents.end(); ++it) _contents.push_back((*it)->clone(this).release()); } Node::~Node() throw() { clear(); } std::auto_ptr Node::clone() const throw() { std::auto_ptr res(new Node(*this)); res->_parent = 0; return res; } std::ostream& Node::out(std::ostream& o, unsigned int level) const throw() { if (_contents.size()) { o<first<<"=\""<second<<'"'; o<<'>'<out(o, level+1)<'; } else { o<first<<"=\""<second<<'"'; o<<"/>"; } return o; } std::string Node::text() const throw() { std::string s; for (Contents::const_iterator it(_contents.begin()); it!=_contents.end(); ++it) s+=***it; return s; } Node& Node::text(const std::string& txt) throw(tag_expected, type_mismatch) { throw tag_expected(*this, txt); } Node& Node::append(const Node& o) throw(cannot_have_children) { _contents.push_back(o.clone(this).release()); return *this; } Node& Node::set(const Attributes& o) throw() { _attributes.insert(o.begin(), o.end()); return *this; } Node& Node::clear() throw () { for (Contents::const_iterator it(_contents.begin()); it!=_contents.end(); ++it) delete *it; _contents.clear(); _attributes.clear(); return *this; } std::string Node::name() const throw() { return _name; } bool Node::isChild() const throw() { return _parent; } Node& Node::parent() const throw(no_parent) { if (!_parent) throw no_parent(*this); return *_parent; } bool Node::hasAttr(const std::string& name) const throw() { return _attributes.find(name)!=_attributes.end(); } Node& Node::attr(const std::string& name, bool mandatory) throw() { _attributes[name] = mandatory?"mandatory":"optional"; return *this; } std::string Node::attr(const std::string& name) const throw() { Attributes::const_iterator it(_attributes.find(name)); if (it!=_attributes.end()) return it->second; return std::string(); } std::string& Node::attr(const std::string&name) throw() { return _attributes[name]; } bool Node::operator()(const std::string& child) const throw() { return find(child); } Node& Node::operator<<(const Node& o) throw(cannot_have_children) { return append(o); } Node& Node::operator<<(const Attributes& o) throw() { return set(o); } Node::size_type Node::children() const throw() { return _contents.size(); } const Node& Node::operator[](Node::size_type child) const throw(access_error) try { return *_contents.at(child); } catch (...) { throw out_of_range(*this, child); } Node& Node::operator[](Node::size_type child) throw(access_error) try { return *_contents.at(child); } catch (...) { throw out_of_range(*this, child); } const Node& Node::operator[](const std::string& child) const throw(access_error) { const Node* const t(find(child)); if (!t) throw access_error(*this, child); return *t; } Node& Node::operator[](const std::string& child) throw(access_error) { Node* const t(find(child)); if (!t) throw access_error(*this, child); return *t; } std::string Node::operator*() const throw() { return text(); } Node& Node::operator=(const std::string& contents) throw(tag_expected, type_mismatch) { return text(contents); } std::ostream& operator<<(std::ostream& o, const Node& t) throw() { return t.out(o); } Node* Node::find(const std::string& child) const throw() { for (Contents::const_iterator it(_contents.begin()); it!=_contents.end(); ++it) { if ((*it)->name()==child) return *it; } return 0; } std::auto_ptr Node::clone(Node* p) const throw() { std::auto_ptr c(clone()); c->_parent = p; return c; } //---------------------------------------------------------------------------- String::String(std::string name, const std::string& text) throw(): Node(name), _text(text) { } std::auto_ptr String::clone() const throw() { return std::auto_ptr(new String(*this)); } std::string String::text() const throw() { return _text; } String& String::text(const std::string& txt) throw(tag_expected, type_mismatch) { _text = txt; return *this; } std::ostream& String::out(std::ostream& o, unsigned int level) const throw() { if (_text.size()) { o<first<<"=\""<second<<'"'; o<<'>'<<_text<<"'; } else { o<first<<"=\""<second<<'"'; o<<"/>"; } return o; } String& String::append(const Node& o) throw(cannot_have_children) { throw cannot_have_children(*this, o); } Node& String::operator=(const std::string& contents) throw() { return text(contents); } //---------------------------------------------------------------------------- UnsingedInteger::UnsingedInteger(std::string name, const std::string& text) throw(): Node(name), _text(text) { } std::auto_ptr UnsingedInteger::clone() const throw() { return std::auto_ptr(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<first<<"=\""<second<<'"'; o<<'>'<<_text<<"'; } else { o<first<<"=\""<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()) {} const Node& Factory::operator*() const throw() { return *_template; } std::auto_ptr Factory::read(std::istream& is) 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, access_error, empty_stream, duplicate_attribute, attributes_in_end_tag) { std::auto_ptr node(_template->clone()); node->clear(); Tag res; try { res = tag(is, *node); } catch (missing_end_tag&) { throw empty_stream(*node, is, res); } *node< Factory::read(std::istream& is, const Node& node) 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, access_error, duplicate_attribute, attributes_in_end_tag) { std::auto_ptr result(node.clone()); result->clear(); for (bool finished(false); is && !finished;) { Tag res(tag(is, node)); if (res.text.size()) result->text(res.text); switch (res.type) { case END: { if (res.attributes.size()) throw attributes_in_end_tag(node, is, res); if (res.name!=node.name()) throw wrong_end_tag(node, is, res); finished = true; } break; case EMPTY: { *result<<(node[res.name].clone()->clear()<