📄 node.cpp
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA/* * @$Id: node.cpp,v 1.32 2007/02/12 14:15:02 jackjansen Exp $ */#include "ambulant/lib/node.h"#include "ambulant/lib/node_impl.h"// find_if, etc#include <algorithm>#if !defined(AMBULANT_NO_IOSTREAMS) && !defined(AMBULANT_NO_STRINGSTREAM)// ostringstream#include <sstream>#endif// assert#include <cassert>// trim strings#include "ambulant/lib/string_util.h"// tree helper iterators and visitors#include "ambulant/lib/node_navigator.h" // node context#include "ambulant/lib/document.h" #include "ambulant/lib/logger.h" #include <stdio.h> using namespace ambulant;// This module starts with a set of private node visitors// and continues with the implementation of lib::node.// Node visitors are used by lib::node member functions////////////////////////// private output_visitor// Writes a tree to an ostream.#ifndef AMBULANT_NO_IOSTREAMStemplate <class Node>class output_visitor { std::ostream& os; std::basic_string<char> writesp, strincr; size_t ns; public: output_visitor(std::ostream& os_) : os(os_), strincr(" ") {ns = strincr.length();} void operator()(std::pair<bool, const Node*> x); private: void write_start_tag_no_children(const Node*& pe); void write_start_tag_with_children(const Node*& pe); void write_end_tag_with_children(const Node*& pe); const output_visitor& operator=(const output_visitor& o);};#endif////////////////////////// private trimmed_output_visitor// Writes a tree to an ostream without white space.#ifndef AMBULANT_NO_IOSTREAMStemplate <class Node>class trimmed_output_visitor { std::ostream& os; public: trimmed_output_visitor(std::ostream& os_) : os(os_) {} void operator()(std::pair<bool, const Node*> x); private: void write_start_tag_no_children(const Node*& pe); void write_start_tag_with_children(const Node*& pe); void write_end_tag_with_children(const Node*& pe); const trimmed_output_visitor& operator=(const trimmed_output_visitor& o); };#endif////////////////////////// private attr_collector// Scans the tree and creates a map attr to nodes.// Intented for unique attrs like name and idtemplate <class Node>class attr_collector { public: attr_collector(std::map<std::string, Node*>& m, const char *attr = "id") : m_attr(attr), m_map(m) {} void operator()(std::pair<bool, const Node*> x) { if(x.first) { const char *value = x.second->get_attribute(m_attr); if(value != 0) m_map[value] = const_cast<Node*>(x.second); } } private: std::string m_attr; std::map<std::string, Node*>& m_map; const attr_collector& operator=(const attr_collector& o); };///////////////////////////////////////////////// lib::node implementation// static int lib::node_impl::node_counter = 0;//////////////////////// Node constructors// Note: attrs are as per expat parser// e.g. const char* attrs[] = {"attr_name", "attr_value", ..., 0};lib::node_impl::node_impl(const char *local_name, const char **attrs, const node_context *ctx): m_qname("",(local_name?local_name:"error")), m_context(ctx), m_parent(0), m_next(0), m_child(0) { set_attributes(attrs); m_numid = ++node_counter;}lib::node_impl::node_impl(const xml_string& local_name, const char **attrs, const node_context *ctx): m_qname("", local_name), m_context(ctx), m_parent(0), m_next(0), m_child(0) { set_attributes(attrs); m_numid = ++node_counter;}lib::node_impl::node_impl(const q_name_pair& qn, const q_attributes_list& qattrs, const node_context *ctx): m_qname(qn), m_qattrs(qattrs), m_context(ctx), m_parent(0), m_next(0), m_child(0){ m_numid = ++node_counter;}// shallow copy from otherlib::node_impl::node_impl(const node_impl* other): m_qname(other->get_qname()), m_qattrs(other->get_attrs()), m_data(other->get_data()), m_context(other->get_context()), m_parent(0), m_next(0), m_child(0) { m_numid = ++node_counter;}//////////////////////// Node destructorlib::node_impl::~node_impl() { node_counter--; node_navigator<node_impl>::delete_tree(this); }///////////////////////////////// basic navigation// inline//////////////////////// set down/up/next// inline///////////////////////////////// deduced navigationconst lib::node_impl* lib::node_impl::previous() const { return node_navigator<const node_impl>::previous(this); }const lib::node_impl* lib::node_impl::get_last_child() const { return node_navigator<const node_impl>::last_child(this);}void lib::node_impl::get_children(std::list<const lib::node*>& l) const { node_navigator<const lib::node>::get_children(this, l);}///////////////////////////////// search operations lib::node_impl* lib::node_impl::get_first_child(const char *name) { node_impl *e = down(); if(!e) return 0; if(e->m_qname.second == name) return e; e = e->next(); while(e != 0) { if(e->m_qname.second == name) return e; e = e->next(); } return 0;}const lib::node_impl* lib::node_impl::get_first_child(const char *name) const { const node_impl *e = down(); if(!e) return 0; if(e->m_qname.second == name) return e; e = e->next(); while(e != 0) { if(e->m_qname.second == name) return e; e = e->next(); } return 0;}lib::node_impl* lib::node_impl::locate_node(const char *path) { if(!path || !path[0]) { return this; } tokens_vector v(path, "/"); node_impl *n = 0; tokens_vector::iterator it = v.begin(); if(path[0] == '/') { // or v.at(0) is empty // absolute it++; // skip empty n = get_root(); if(it == v.end()) return n; if(n->get_local_name() != (*it)) return 0; it++; // skip root } else n = this; for(; it != v.end() && n != 0;it++) { n = n->get_first_child((*it).c_str()); } return n;}#if 0void lib::node_impl::find_nodes_with_name(const xml_string& name, std::list<node*>& lst) { iterator last = end(); // call once for(iterator it = begin(); it != last; it++) if((*it).first && (*it).second->get_local_name() == name) lst.push_back((*it).second);}#endiflib::node_impl* lib::node_impl::get_root() { return node_navigator<node_impl>::get_root(this); }inline std::string get_path_desc_comp(const lib::node_impl *n) { std::string sbuf; const char *pid = n->get_attribute("id"); sbuf += n->get_local_name(); if(pid) {sbuf += ":"; sbuf += pid;} return sbuf;}std::string lib::node_impl::get_path_display_desc() const { std::string sbuf; std::list<const node_impl*> path; node_navigator<const node_impl>::get_path(this, path); int nc = 0; std::list<const node_impl*>::reverse_iterator it = path.rbegin(); sbuf += get_path_desc_comp(this);it++;nc++; for(;it != path.rend() && nc<3;it++) { std::string ln = (*it)->get_local_name(); if(ln != "priorityClass" && ln != "switch") { sbuf.insert(0, "/"); sbuf.insert(0, get_path_desc_comp(*it)); nc++; } } return sbuf;}///////////////////////////////// iterators// inline///////////////////////// build tree functions lib::node_impl* lib::node_impl::append_child(node_impl* child) { return node_navigator<node_impl>::append_child(this, child);} lib::node_impl* lib::node_impl::append_child(const char *name) { return append_child(new node_impl(name));}lib::node_impl* lib::node_impl::detach() { return node_navigator<node_impl>::detach(this); } void lib::node_impl::append_data(const char *data, size_t len) { if(len>0) m_data.append(data, len);}void lib::node_impl::append_data(const char *c_str) { if(c_str == 0 || c_str[0] == 0) return; m_data.append(c_str, strlen(c_str));}void lib::node_impl::append_data(const xml_string& str) { m_data += str;}void lib::node_impl::set_attribute(const char *name, const char *value){ if(name && name[0]) { q_name_pair qn("", name); q_attribute_pair qattr(qn, (value?value:"")); m_qattrs.push_back(qattr); }}void lib::node_impl::set_attribute(const char *name, const xml_string& value) { if(name && name[0]) { q_name_pair qn("", name); q_attribute_pair qattr(qn, value); m_qattrs.push_back(qattr); }}// Note: attrs are as per expat parser// e.g. const char* attrs[] = {"attr_name", "attr_value", ..., 0};void lib::node_impl::set_attributes(const char **attrs) { if(attrs == 0) return; for(int i=0;attrs[i];i+=2) set_attribute(attrs[i], attrs[i+1]);} void lib::node_impl::set_namespace(const xml_string& ns) { m_qname.first = ns;}// create a deep copy of thislib::node_impl* lib::node_impl::clone() const { node_impl* c = new node_impl(this); const node_impl *e = down(); if(e != 0) { c->append_child(e->clone());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -