From: <br...@us...> - 2008-09-26 04:14:15
|
Revision: 3693 http://openvrml.svn.sourceforge.net/openvrml/?rev=3693&view=rev Author: braden Date: 2008-09-26 04:14:04 +0000 (Fri, 26 Sep 2008) Log Message: ----------- Moved PROTO implementation classes to the openvrml::local namespace and out of browser.cpp. Modified Paths: -------------- trunk/ChangeLog trunk/src/Makefile.am trunk/src/libopenvrml/openvrml/browser.cpp trunk/src/libopenvrml/openvrml/node.h Added Paths: ----------- trunk/src/libopenvrml/openvrml/local/proto.cpp trunk/src/libopenvrml/openvrml/local/proto.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2008-09-25 02:08:05 UTC (rev 3692) +++ trunk/ChangeLog 2008-09-26 04:14:04 UTC (rev 3693) @@ -1,3 +1,16 @@ +2008-09-26 Braden McDaniel <br...@en...> + + Moved PROTO implementation classes to the openvrml::local + namespace and out of browser.cpp. + + * src/Makefile.am + (libopenvrml_libopenvrml_la_SOURCES): Added + libopenvrml/openvrml/local/proto.{cpp,h}. + * src/libopenvrml/openvrml/browser.cpp + * src/libopenvrml/openvrml/local/proto.cpp + * src/libopenvrml/openvrml/local/proto.h + * src/libopenvrml/openvrml/node.h + 2008-09-24 Braden McDaniel <br...@en...> Moved dlopen/LoadLibrary wrapper functions, the XML parser Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2008-09-25 02:08:05 UTC (rev 3692) +++ trunk/src/Makefile.am 2008-09-26 04:14:04 UTC (rev 3693) @@ -155,7 +155,9 @@ libopenvrml/openvrml/local/uri.cpp \ libopenvrml/openvrml/local/uri.h \ libopenvrml/openvrml/local/xml_reader.cpp \ - libopenvrml/openvrml/local/xml_reader.h + libopenvrml/openvrml/local/xml_reader.h \ + libopenvrml/openvrml/local/proto.cpp \ + libopenvrml/openvrml/local/proto.h libopenvrml_libopenvrml_la_LDFLAGS = \ -version-info $(LIBOPENVRML_LIBRARY_VERSION) \ Modified: trunk/src/libopenvrml/openvrml/browser.cpp =================================================================== --- trunk/src/libopenvrml/openvrml/browser.cpp 2008-09-25 02:08:05 UTC (rev 3692) +++ trunk/src/libopenvrml/openvrml/browser.cpp 2008-09-26 04:14:04 UTC (rev 3693) @@ -42,6 +42,7 @@ # include "x3d_cad_geometry.h" # include <openvrml/local/uri.h> # include <openvrml/local/xml_reader.h> +# include <openvrml/local/proto.h> # include <private.h> # include <boost/algorithm/string/predicate.hpp> # include <boost/bind.hpp> @@ -107,2221 +108,6 @@ const initial_value_map & initial_values) const OPENVRML_NOTHROW; }; - - - class proto_node; - class proto_node_type; - class proto_impl_cloner; - - /** - * @internal - * - * @brief @c node_metatype for @c PROTO%s. - * - * The @c proto_node_metatype is OpenVRML's in-memory representation of a - * @c PROTO (as opposed to a @c PROTO instance). Through the - * @c proto_node_type intermediary, it facilitates spawning any number of - * @c proto_node instances. - */ - class OPENVRML_LOCAL proto_node_metatype : public node_metatype { - friend class proto_node; - friend class proto_node_type; - friend class proto_impl_cloner; - - public: - class is_target { - public: - node * impl_node; - std::string impl_node_interface; - - is_target(node & impl_node, - const std::string & impl_node_interface); - }; - - typedef std::multimap<std::string, is_target> is_map_t; - - class route { - public: - node * from; - std::string eventout; - node * to; - std::string eventin; - - route(node & from, const std::string & eventout, - node & to, const std::string & eventin); - }; - - typedef std::vector<route> routes_t; - - typedef std::map<std::string, boost::shared_ptr<field_value> > - default_value_map_t; - - private: - node_interface_set interfaces; - default_value_map_t default_value_map; - std::vector<boost::intrusive_ptr<node> > impl_nodes; - routes_t routes; - is_map_t is_map; - - public: - proto_node_metatype( - const node_metatype_id & id, - openvrml::browser & browser, - const node_interface_set & interfaces, - const default_value_map_t & default_value_map, - const std::vector<boost::intrusive_ptr<node> > & impl_nodes, - const is_map_t & is_map, - const routes_t & routes); - virtual ~proto_node_metatype() OPENVRML_NOTHROW; - - virtual const boost::shared_ptr<node_type> - do_create_type(const std::string & id, - const node_interface_set & interfaces) const - OPENVRML_THROW2(unsupported_interface, std::bad_alloc); - }; - - - /** - * @internal - * - * @brief @c node_type for @c PROTO node instances. - */ - class OPENVRML_LOCAL proto_node_type : public node_type { - node_interface_set interfaces_; - - public: - proto_node_type(const proto_node_metatype & node_metatype, - const std::string & id, - const node_interface_set & interfaces) - OPENVRML_THROW2(unsupported_interface, std::bad_alloc); - virtual ~proto_node_type() OPENVRML_NOTHROW; - - private: - virtual const node_interface_set & do_interfaces() const - OPENVRML_NOTHROW; - virtual const boost::intrusive_ptr<node> - do_create_node(const boost::shared_ptr<openvrml::scope> & scope, - const initial_value_map & initial_values) const - OPENVRML_THROW1(std::bad_alloc); - }; - - - class OPENVRML_LOCAL abstract_proto_node : public openvrml::node { - public: - virtual ~abstract_proto_node() OPENVRML_NOTHROW = 0; - - protected: - template <typename FieldValue> - class proto_eventin : public node_field_value_listener<FieldValue> { - typedef std::set<field_value_listener<FieldValue> *> listeners; - listeners listeners_; - - public: - typedef FieldValue field_value_type; - typedef field_value_listener<FieldValue> event_listener_type; - - explicit proto_eventin(abstract_proto_node & node); - virtual ~proto_eventin() OPENVRML_NOTHROW; - - bool is(event_listener_type & listener) - OPENVRML_THROW1(std::bad_alloc); - - protected: - virtual void do_process_event(const FieldValue & value, - double timestamp) - OPENVRML_THROW1(std::bad_alloc); - - private: - virtual const std::string do_eventin_id() const OPENVRML_NOTHROW; - }; - - struct proto_eventin_creator { - proto_eventin_creator( - const openvrml::field_value::type_id type, - abstract_proto_node & node, - boost::shared_ptr<openvrml::event_listener> & listener): - type_(type), - node_(&node), - listener_(&listener) - {} - - template <typename T> - void operator()(T) const - { - if (T::field_value_type_id == this->type_) { - this->listener_->reset(new proto_eventin<T>(*this->node_)); - } - } - - private: - openvrml::field_value::type_id type_; - abstract_proto_node * node_; - boost::shared_ptr<openvrml::event_listener> * listener_; - }; - - static boost::shared_ptr<openvrml::event_listener> - create_eventin(field_value::type_id, abstract_proto_node & node) - OPENVRML_THROW1(std::bad_alloc); - - struct eventin_is { - eventin_is(const field_value::type_id field_type, - openvrml::event_listener & impl_eventin, - openvrml::event_listener & interface_eventin): - type_(field_type), - impl_eventin_(&impl_eventin), - interface_eventin_(&interface_eventin) - {} - - template <typename T> - void operator()(T) const - { - if (T::field_value_type_id == this->type_) { - dynamic_cast<proto_eventin<T> &>(*interface_eventin_).is( - dynamic_cast<field_value_listener<T> &>( - *impl_eventin_)); - } - } - - private: - field_value::type_id type_; - openvrml::event_listener * impl_eventin_; - openvrml::event_listener * interface_eventin_; - }; - - template <typename FieldValue> - class proto_eventout : public field_value_emitter<FieldValue> { - protected: - class listener_t : public node_field_value_listener<FieldValue> { - proto_eventout & emitter; - - public: - abstract_proto_node & node; - FieldValue value; - - listener_t(proto_eventout & emitter, - abstract_proto_node & node, - const FieldValue & initial_value); - virtual ~listener_t() OPENVRML_NOTHROW; - - private: - virtual const std::string do_eventin_id() const - OPENVRML_NOTHROW; - virtual void do_process_event(const FieldValue & value, - double timestamp) - OPENVRML_THROW1(std::bad_alloc); - } listener; - - public: - typedef FieldValue field_value_type; - typedef field_value_emitter<FieldValue> event_emitter_type; - typedef field_value_listener<FieldValue> event_listener_type; - - proto_eventout( - abstract_proto_node & node, - const FieldValue & initial_value = FieldValue()); - virtual ~proto_eventout() OPENVRML_NOTHROW; - - bool is(event_emitter_type & emitter) - OPENVRML_THROW1(std::bad_alloc); - - private: - const std::string do_eventout_id() const OPENVRML_NOTHROW; - }; - - struct proto_eventout_creator { - proto_eventout_creator( - const openvrml::field_value::type_id type, - abstract_proto_node & node, - boost::shared_ptr<openvrml::event_emitter> & emitter): - type_(type), - node_(&node), - emitter_(&emitter) - {} - - template <typename T> - void operator()(T) const - { - if (T::field_value_type_id == this->type_) { - this->emitter_->reset(new proto_eventout<T>(*this->node_)); - } - } - - private: - openvrml::field_value::type_id type_; - abstract_proto_node * node_; - boost::shared_ptr<openvrml::event_emitter> * emitter_; - }; - - static boost::shared_ptr<openvrml::event_emitter> - create_eventout(field_value::type_id, abstract_proto_node & node) - OPENVRML_THROW1(std::bad_alloc); - - struct eventout_is { - eventout_is(const field_value::type_id field_type, - openvrml::event_emitter & impl_eventout, - openvrml::event_emitter & interface_eventout): - type_(field_type), - impl_eventout_(&impl_eventout), - interface_eventout_(&interface_eventout) - {} - - template <typename T> - void operator()(T) const - { - if (T::field_value_type_id == this->type_) { - dynamic_cast<proto_eventout<T> &>(*interface_eventout_).is( - dynamic_cast<field_value_emitter<T> &>( - *impl_eventout_)); - } - } - - private: - field_value::type_id type_; - openvrml::event_emitter * impl_eventout_; - openvrml::event_emitter * interface_eventout_; - }; - - typedef boost::shared_ptr<openvrml::event_listener> eventin_ptr; - typedef std::map<std::string, eventin_ptr> eventin_map_t; - - struct proto_eventin_equal_to : - std::unary_function<eventin_map_t::value_type, bool> { - - explicit proto_eventin_equal_to( - const openvrml::event_listener & listener): - listener_(&listener) - {} - - bool operator()(const eventin_map_t::value_type & arg) const - { - return this->listener_ == arg.second.get(); - } - - private: - const openvrml::event_listener * listener_; - }; - - eventin_map_t eventin_map; - - typedef boost::shared_ptr<openvrml::event_emitter> eventout_ptr; - typedef std::map<std::string, eventout_ptr> eventout_map_t; - - struct proto_eventout_equal_to : - std::unary_function<eventout_map_t::value_type, bool> { - - explicit proto_eventout_equal_to( - const openvrml::event_emitter & emitter): - emitter_(&emitter) - {} - - bool operator()(const eventout_map_t::value_type & arg) const - { - return this->emitter_ == arg.second.get(); - } - - private: - const openvrml::event_emitter * emitter_; - }; - - eventout_map_t eventout_map; - - abstract_proto_node(const openvrml::node_type & type, - const boost::shared_ptr<openvrml::scope> & scope) - OPENVRML_NOTHROW; - }; - - abstract_proto_node::abstract_proto_node( - const openvrml::node_type & type, - const boost::shared_ptr<openvrml::scope> & scope) - OPENVRML_NOTHROW: - openvrml::node(type, scope) - {} - - abstract_proto_node::~abstract_proto_node() OPENVRML_NOTHROW - {} - - - /** - * @internal - * - * @brief A @c PROTO instance node. - * - * Like a typical node implementation, @c proto_node%s have a many-to-one - * relationship with the @c proto_node_type instance that creates them. - * And @c proto_node_type has, in turn, a many-to-one relationship with - * the @c proto_node_metatype instance that creates them. Unlike a - * typical node implementation, there will very likely be more than one - * @c proto_node_metatype instance known to the @c browser instance; there - * will be one for each @c PROTO known to the @c browser. - * - * As the @c proto_node_metatype encodes the data in a @c PROTO, the - * @c proto_node_type can be seen as modeling @c EXTERNPROTO. Each - * @c EXTERNPROTO will spawn a new @c proto_node_type from the - * @c proto_node_metatype that corresponds to the @c PROTO to which the - * @c EXTERNPROTO refers. Recall that an @c EXTERNPROTO provides a subset - * of the interfaces defined for a @c PROTO; thus, for a @c PROTO with - * <var>n</var> interfaces, there are <var>n</var>! possible unique - * @c EXTERNPROTO%s (and thus unique @c proto_node_type instances). - * - * Structurally, the implementation of @c proto_node is very similar to - * that of @c proto_node_metatype. The difference is that event pathways - * for @c ROUTE%s and @c IS mappings are actually created in the - * @c proto_node. The @c proto_node_metatype, on the other hand, includes - * metadata about how these event pathways @e should be created. - */ - class OPENVRML_LOCAL proto_node : public abstract_proto_node { - friend class externproto_node; - - template <typename FieldValue> - class proto_exposedfield : public proto_eventin<FieldValue>, - public proto_eventout<FieldValue> { - public: - proto_exposedfield(abstract_proto_node & node, - const FieldValue & initial_value); - virtual ~proto_exposedfield() OPENVRML_NOTHROW; - - private: - virtual void do_process_event(const FieldValue & value, - double timestamp) - OPENVRML_THROW1(std::bad_alloc); - }; - - struct proto_exposedfield_creator { - proto_exposedfield_creator( - const field_value & initial_value, - proto_node & node, - boost::shared_ptr<openvrml::event_listener> & exposedfield): - initial_value_(&initial_value), - node_(&node), - exposedfield_(&exposedfield) - {} - - template <typename T> - void operator()(T) const - { - if (T::field_value_type_id == this->initial_value_->type()) { - using boost::polymorphic_downcast; - this->exposedfield_->reset( - new proto_exposedfield<T>( - *this->node_, - *polymorphic_downcast<const T *>( - this->initial_value_))); - } - } - - private: - const openvrml::field_value * initial_value_; - proto_node * node_; - boost::shared_ptr<openvrml::event_listener> * exposedfield_; - }; - - static boost::shared_ptr<openvrml::event_listener> - create_exposedfield(const field_value & initial_value, - proto_node & node) - OPENVRML_THROW1(std::bad_alloc); - - boost::shared_ptr<openvrml::scope> proto_scope; - std::vector<boost::intrusive_ptr<node> > impl_nodes; - - public: - proto_node(const node_type & type, - const boost::shared_ptr<openvrml::scope> & scope, - const initial_value_map & initial_values) - OPENVRML_THROW1(std::bad_alloc); - virtual ~proto_node() OPENVRML_NOTHROW; - - virtual bool modified() const; - - private: - virtual void do_initialize(double timestamp) - OPENVRML_THROW1(std::bad_alloc); - - virtual const field_value & do_field(const std::string & id) const - OPENVRML_THROW1(unsupported_interface); - virtual openvrml::event_listener & - do_event_listener(const std::string & id) - OPENVRML_THROW1(unsupported_interface); - virtual openvrml::event_emitter & - do_event_emitter(const std::string & id) - OPENVRML_THROW1(unsupported_interface); - - virtual void do_shutdown(double timestamp) OPENVRML_NOTHROW; - - virtual script_node * to_script() OPENVRML_NOTHROW; - virtual appearance_node * to_appearance() OPENVRML_NOTHROW; - virtual bounded_volume_node * to_bounded_volume() OPENVRML_NOTHROW; - virtual child_node * to_child() OPENVRML_NOTHROW; - virtual color_node * to_color() OPENVRML_NOTHROW; - virtual color_rgba_node * to_color_rgba() OPENVRML_NOTHROW; - virtual coordinate_node * to_coordinate() OPENVRML_NOTHROW; - virtual font_style_node * to_font_style() OPENVRML_NOTHROW ; - virtual geometry_node * to_geometry() OPENVRML_NOTHROW; - virtual grouping_node * to_grouping() OPENVRML_NOTHROW; - virtual light_node * to_light() OPENVRML_NOTHROW; - virtual material_node * to_material() OPENVRML_NOTHROW; - virtual navigation_info_node * to_navigation_info() OPENVRML_NOTHROW; - virtual normal_node * to_normal() OPENVRML_NOTHROW; - virtual pointing_device_sensor_node * to_pointing_device_sensor() - OPENVRML_NOTHROW; - virtual scoped_light_node * to_scoped_light() OPENVRML_NOTHROW; - virtual sound_source_node * to_sound_source() OPENVRML_NOTHROW; - virtual texture_node * to_texture() OPENVRML_NOTHROW; - virtual texture_coordinate_node * to_texture_coordinate() - OPENVRML_NOTHROW; - virtual texture_transform_node * to_texture_transform() - OPENVRML_NOTHROW; - virtual time_dependent_node * to_time_dependent() OPENVRML_NOTHROW; - virtual transform_node * to_transform() OPENVRML_NOTHROW; - virtual viewpoint_node * to_viewpoint() OPENVRML_NOTHROW; - }; - - - class OPENVRML_LOCAL node_path_element { - public: - std::vector<boost::intrusive_ptr<node> >::size_type index; - field_value::type_id field_type; - std::string field_id; - - node_path_element(); - }; - - node_path_element::node_path_element(): - index(0), - field_type(field_value::invalid_type_id) - {} - - /** - * @brief A @c node path is used to store the path to a @c node for the - * purpose of duplicating a route in a cloned @c node hierarchy. - */ - typedef std::list<node_path_element> node_path_t; - - class OPENVRML_LOCAL path_getter : boost::noncopyable { - const node & objective; - node_path_t & node_path; - bool found; - - public: - path_getter(const node & objective, node_path_t & node_path) - OPENVRML_NOTHROW; - - void get_path_from(const boost::intrusive_ptr<node> & node) - OPENVRML_THROW1(std::bad_alloc); - void get_path_from( - const std::vector<boost::intrusive_ptr<node> > & nodes) - OPENVRML_THROW1(std::bad_alloc); - - private: - void traverse_children(node & n) OPENVRML_THROW1(std::bad_alloc); - }; - - path_getter::path_getter(const node & objective, node_path_t & node_path) - OPENVRML_NOTHROW: - objective(objective), - node_path(node_path), - found(false) - {} - - void path_getter::get_path_from(const boost::intrusive_ptr<node> & node) - OPENVRML_THROW1(std::bad_alloc) - { - if (node) { - this->node_path.push_back(node_path_element()); - if (node.get() == &objective) { - this->found = true; - return; - } - this->traverse_children(*node); - if (!this->found) { this->node_path.pop_back(); } - } - } - - void path_getter::get_path_from( - const std::vector<boost::intrusive_ptr<node> > & nodes) - OPENVRML_THROW1(std::bad_alloc) - { - this->node_path.push_back(node_path_element()); - node_path_element & back = this->node_path.back(); - while (back.index < nodes.size()) { - assert(&back == &this->node_path.back()); - if (nodes[back.index].get() == &this->objective) { - this->found = true; - return; - } - if (nodes[back.index].get()) { - this->traverse_children(*nodes[back.index]); - } - // - // We need to bail early to avoid incrementing the counter. - // - if (this->found) { return; } - ++back.index; - } - if (!this->found) { this->node_path.pop_back(); } - } - - void path_getter::traverse_children(node & n) - OPENVRML_THROW1(std::bad_alloc) - { - const node_interface_set & interfaces = n.type().interfaces(); - node_path_element & back = this->node_path.back(); - for (node_interface_set::const_iterator interface_ = interfaces.begin(); - !this->found && interface_ != interfaces.end(); - ++interface_) { - assert(&back == &this->node_path.back()); - if (interface_->type == node_interface::field_id - || interface_->type == node_interface::exposedfield_id) { - if (interface_->field_type == field_value::sfnode_id) { - back.field_type = field_value::sfnode_id; - back.field_id = interface_->id; - try { - const sfnode value = n.field<sfnode>(interface_->id); - this->get_path_from(value.value()); - } catch (unsupported_interface & ex) { - OPENVRML_PRINT_EXCEPTION_(ex); - } - } else if (interface_->field_type == field_value::mfnode_id) { - back.field_type = field_value::mfnode_id; - back.field_id = interface_->id; - try { - const mfnode value = n.field<mfnode>(interface_->id); - this->get_path_from(value.value()); - } catch (unsupported_interface & ex) { - OPENVRML_PRINT_EXCEPTION_(ex); - } - } - } - } - } - - /** - * @internal - * - * @brief Get the path to a node. - * - * @return the path to a node. - */ - OPENVRML_LOCAL const node_path_t - get_path(const std::vector<boost::intrusive_ptr<node> > & root, - const node & objective) - OPENVRML_THROW1(std::bad_alloc) - { - node_path_t path; - path_getter(objective, path).get_path_from(root); - return path; - } - - /** - * @internal - * - * @brief Resolve a node path against a node hierarchy. - * - * @return a pointer to the objective node in the node hierarchy - * designated by @p root. - */ - OPENVRML_LOCAL node * - resolve_node_path(const node_path_t & path, - const std::vector<boost::intrusive_ptr<node> > & root) - { - using boost::next; - using boost::prior; - assert(!path.empty()); - node * result = root[path.front().index].get(); - const node_path_t::const_iterator before_end = prior(path.end()); - for (node_path_t::const_iterator path_element = path.begin(); - path_element != before_end; - ++path_element) { - assert(result); - try { - if (path_element->field_type == field_value::sfnode_id) { - result = result->field<sfnode>(path_element->field_id) - .value().get(); - } else if (path_element->field_type == field_value::mfnode_id) - { - result = result->field<mfnode>(path_element->field_id) - .value()[next(path_element)->index].get(); - } else { - assert(!"invalid path_element->field_type"); - } - } catch (unsupported_interface & ex) { - OPENVRML_PRINT_EXCEPTION_(ex); - } - } - return result; - } - - class OPENVRML_LOCAL field_value_cloner { - protected: - const boost::shared_ptr<openvrml::scope> & target_scope; - std::set<node *> traversed_nodes; - - public: - explicit field_value_cloner( - const boost::shared_ptr<openvrml::scope> & target_scope): - target_scope(target_scope) - { - assert(target_scope); - } - - virtual ~field_value_cloner() - {} - - void clone_field_value(const boost::intrusive_ptr<node> & src_node, - const field_value & src, - field_value & dest) - OPENVRML_THROW1(std::bad_alloc) - { - assert(src.type() == dest.type()); - const field_value::type_id type = src.type(); - if (type == field_value::sfnode_id) { - this->clone_sfnode(src_node, - static_cast<const sfnode &>(src), - static_cast<sfnode &>(dest)); - } else if (type == field_value::mfnode_id) { - this->clone_mfnode(src_node, - static_cast<const mfnode &>(src), - static_cast<mfnode &>(dest)); - } else { - // - // Do a shallow copy for other types. - // - dest.assign(src); - } - } - - private: - virtual const boost::intrusive_ptr<node> - clone_node(const boost::intrusive_ptr<node> & n) - OPENVRML_THROW1(std::bad_alloc) - { - using std::set; - using boost::intrusive_ptr; - - assert(this->target_scope); - - intrusive_ptr<node> result; - - if (!n) { return result; } - - const bool already_traversed = - (this->traversed_nodes.find(n.get()) - != this->traversed_nodes.end()); - - if (already_traversed) { - result = intrusive_ptr<node>( - this->target_scope->find_node(n->id())); - assert(result); - } else { - initial_value_map initial_values; - const node_interface_set & interfaces = - n->type().interfaces(); - for (node_interface_set::const_iterator interface_ = - interfaces.begin(); - interface_ != interfaces.end(); - ++interface_) { - using std::string; - const node_interface::type_id type = interface_->type; - const string & id = interface_->id; - if (type == node_interface::exposedfield_id - || type == node_interface::field_id) { - using std::auto_ptr; - using boost::shared_ptr; - auto_ptr<field_value> src = n->field(id); - auto_ptr<field_value> dest = - field_value::create(interface_->field_type); - assert(src->type() == dest->type()); - this->clone_field_value(n, *src, *dest); - bool succeeded = - initial_values.insert( - make_pair(id, shared_ptr<field_value>(dest))) - .second; - assert(succeeded); - } - } - result = n->type().create_node(this->target_scope, - initial_values); - if (!n->id().empty()) { result->id(n->id()); } - } - return result; - } - - void clone_sfnode(const boost::intrusive_ptr<node> & src_node, - const sfnode & src, - sfnode & dest) - OPENVRML_THROW1(std::bad_alloc) - { - dest.value((src.value() == src_node) - ? node::self_tag - : this->clone_node(src.value())); - } - - void clone_mfnode(const boost::intrusive_ptr<node> & src_node, - const mfnode & src, - mfnode & dest) - OPENVRML_THROW1(std::bad_alloc) - { - using std::swap; - using std::vector; - std::vector<boost::intrusive_ptr<node> > result( - src.value().size()); - for (vector<boost::intrusive_ptr<node> >::size_type i = 0; - i < src.value().size(); - ++i) { - result[i] = (src.value()[i] == src_node) - ? node::self_tag - : this->clone_node(src.value()[i]); - } - dest.value(result); - } - }; - - // - // Clone the implementation nodes. - // - class OPENVRML_LOCAL proto_impl_cloner : public field_value_cloner { - const proto_node_metatype & node_metatype; - const initial_value_map & initial_values_; - - public: - proto_impl_cloner( - const proto_node_metatype & node_metatype, - const initial_value_map & initial_values, - const boost::shared_ptr<openvrml::scope> & target_scope): - field_value_cloner(target_scope), - node_metatype(node_metatype), - initial_values_(initial_values) - {} - - const std::vector<boost::intrusive_ptr<node> > clone() - OPENVRML_THROW1(std::bad_alloc) - { - using std::vector; - - vector<boost::intrusive_ptr<node> > result( - this->node_metatype.impl_nodes.size()); - - for (vector<boost::intrusive_ptr<node> >::size_type i = 0; - i < this->node_metatype.impl_nodes.size(); - ++i) { - result[i] = this->clone_node(this->node_metatype.impl_nodes[i]); - assert(result[i]); - } - return result; - } - - private: - struct matches_is_target : - std::unary_function<proto_node_metatype::is_map_t::value_type, - bool> { - - explicit matches_is_target( - const proto_node_metatype::is_target & is_target): - is_target(is_target) - {} - - result_type operator()(const argument_type & is_map_value) const - { - return (is_map_value.second.impl_node - == this->is_target.impl_node) - && (is_map_value.second.impl_node_interface - == this->is_target.impl_node_interface); - } - - private: - const proto_node_metatype::is_target & is_target; - }; - - virtual const boost::intrusive_ptr<node> - clone_node(const boost::intrusive_ptr<node> & n) - OPENVRML_THROW1(std::bad_alloc) - { - using std::set; - using boost::intrusive_ptr; - - assert(this->target_scope); - - intrusive_ptr<node> result; - - if (!n) { return result; } - - const bool already_traversed = - (this->traversed_nodes.find(n.get()) - != this->traversed_nodes.end()); - - if (already_traversed) { - result = intrusive_ptr<node>( - this->target_scope->find_node(n->id())); - assert(result); - } else { - initial_value_map initial_values; - const node_interface_set & interfaces = - n->type().interfaces(); - for (node_interface_set::const_iterator interface_ = - interfaces.begin(); - interface_ != interfaces.end(); - ++interface_) { - using std::string; - const node_interface::type_id type = interface_->type; - const string & id = interface_->id; - if (type == node_interface::exposedfield_id - || type == node_interface::field_id) { - using std::auto_ptr; - using std::find_if; - using boost::shared_ptr; - auto_ptr<const field_value> src_val; - auto_ptr<field_value> dest_val; - - // - // If the field/exposedField is IS'd, get the value - // from the initial_values_, or alternatively the - // default_values_. - // - typedef proto_node_metatype::is_target is_target; - typedef proto_node_metatype::is_map_t is_map; - typedef proto_node_metatype::default_value_map_t - default_value_map; - - is_map::const_iterator is_mapping = - find_if(this->node_metatype.is_map.begin(), - this->node_metatype.is_map.end(), - matches_is_target( - is_target(*n, interface_->id))); - if (is_mapping != this->node_metatype.is_map.end()) { - using boost::bind; - using std::logical_or; - // - // If an exposedField in the implementation is IS'd - // to an eventIn or an eventOut in the interface, - // we'll still get here. So if the implementation - // node interface is an exposedField, we need to - // check to see if the PROTO interface is an - // eventIn or an eventOut. - // - node_interface_set::const_iterator - proto_interface = - find_if(this->node_metatype.interfaces.begin(), - this->node_metatype.interfaces.end(), - bind(logical_or<bool>(), - bind(node_interface_matches_exposedfield(), - _1, - is_mapping->first), - bind(node_interface_matches_field(), - _1, - is_mapping->first))); - - if (proto_interface - != this->node_metatype.interfaces.end()) { - initial_value_map::const_iterator - initial_value = - this->initial_values_.find( - is_mapping->first); - if (initial_value - != this->initial_values_.end()) { - dest_val = initial_value->second->clone(); - } else { - default_value_map::const_iterator - default_value = - this->node_metatype.default_value_map - .find(is_mapping->first); - assert(default_value - != this->node_metatype - .default_value_map.end()); - src_val = default_value->second->clone(); - } - } else { - src_val = n->field(id); - } - } else { - src_val = n->field(id); - } - - // - // See above logic; we don't clone subtrees from the - // initial_values; just ones from the default values - // and the PROTO definition body. - // - if (src_val.get()) { - assert(!dest_val.get()); - dest_val = - field_value::create(interface_->field_type); - this->clone_field_value(n, *src_val, *dest_val); - } - - assert(dest_val.get()); - - bool succeeded = - initial_values.insert( - make_pair(id, - shared_ptr<field_value>(dest_val))) - .second; - assert(succeeded); - } - } - result = n->type().create_node(this->target_scope, - initial_values); - if (!n->id().empty()) { result->id(n->id()); } - } - return result; - } - - void clone_sfnode(const sfnode & src, sfnode & dest) - OPENVRML_THROW1(std::bad_alloc) - { - dest.value(this->clone_node(src.value())); - } - - void clone_mfnode(const mfnode & src, mfnode & dest) - OPENVRML_THROW1(std::bad_alloc) - { - using std::swap; - using std::vector; - vector<boost::intrusive_ptr<node> > result(src.value().size()); - for (vector<boost::intrusive_ptr<node> >::size_type i = 0; - i < src.value().size(); - ++i) { - result[i] = this->clone_node(src.value()[i]); - } - dest.value(result); - } - }; - - /** - * @brief Construct. - * - * @param[in] impl_node a node in the @c PROTO implementation. - * @param[in] impl_node_interface an interface of @p impl_node. - */ - proto_node_metatype:: - is_target::is_target(node & impl_node, - const std::string & impl_node_interface): - impl_node(&impl_node), - impl_node_interface(impl_node_interface) - {} - - /** - * @brief Construct. - * - * @param[in] from event source @c node. - * @param[in] eventout @c eventOut of @p from. - * @param[in] to event destination @c node. - * @param[in] eventin @c eventIn of @p to. - */ - proto_node_metatype::route::route(node & from, - const std::string & eventout, - node & to, - const std::string & eventin): - from(&from), - eventout(eventout), - to(&to), - eventin(eventin) - {} - - /** - * @brief Construct. - * - * @param[in] node_metatype the proto_node_metatype that spawned the - * @c proto_node_type. - * @param[in] id @c node_type identifier. - * @param[in] interfaces a subset of the interfaces supported by the - * @p node_metatype. - * - * @exception unsupported_interface if an interface in @p interfaces is not - * supported by the @p node_metatype. - * @exception std::bad_alloc if memory allocation fails. - */ - proto_node_type::proto_node_type(const proto_node_metatype & node_metatype, - const std::string & id, - const node_interface_set & interfaces) - OPENVRML_THROW2(unsupported_interface, std::bad_alloc): - node_type(node_metatype, id) - { - using std::find; - using std::invalid_argument; - for (node_interface_set::const_iterator interface_ = interfaces.begin(); - interface_ != interfaces.end(); - ++interface_) { - node_interface_set::const_iterator pos = - find(node_metatype.interfaces.begin(), - node_metatype.interfaces.end(), - *interface_); - if (pos == node_metatype.interfaces.end()) { - throw unsupported_interface(*interface_); - } - const bool succeeded = this->interfaces_.insert(*interface_).second; - assert(succeeded); - } - } - - /** - * @brief Destroy. - */ - proto_node_type::~proto_node_type() OPENVRML_NOTHROW - {} - - /** - * @brief Interfaces. - * - * @return the interfaces. - */ - const node_interface_set & - proto_node_type::do_interfaces() const OPENVRML_NOTHROW - { - return this->interfaces_; - } - - const boost::intrusive_ptr<node> - proto_node_type:: - do_create_node(const boost::shared_ptr<openvrml::scope> & scope, - const initial_value_map & initial_values) const - OPENVRML_THROW1(std::bad_alloc) - { - return boost::intrusive_ptr<node>( - new proto_node(*this, scope, initial_values)); - } - - /** - * @internal - * - * @class abstract_proto_node::proto_eventin - * - * @brief @c PROTO @c eventIn handler class template. - */ - - /** - * @typedef abstract_proto_node::proto_eventin::listeners - * - * @brief Set of event listeners. - */ - - /** - * @var abstract_proto_node::proto_eventin::listeners abstract_proto_node::proto_eventin::listeners_ - * - * @brief Set of event listeners to which events are delegated for - * processing. - */ - - /** - * @typedef abstract_proto_node::proto_eventin::field_value_type - * - * @brief Field value type. - */ - - /** - * @typedef abstract_proto_node::proto_eventin::event_listener_type - * - * @brief Type of event listeners to which the instance delegates. - */ - - /** - * @brief Construct. - * - * @param[in] node abstract_proto_node. - */ - template <typename FieldValue> - abstract_proto_node::proto_eventin<FieldValue>:: - proto_eventin(abstract_proto_node & node): - node_event_listener(node), - node_field_value_listener<FieldValue>(node) - {} - - /** - * @brief Destroy. - */ - template <typename FieldValue> - abstract_proto_node::proto_eventin<FieldValue>::~proto_eventin() - OPENVRML_NOTHROW - {} - - /** - * @brief Process event. - * - * @param[in] value field value. - * @param[in] timestamp the current time. - * - * @exception std::bad_alloc if memory allocation fails. - */ - template <typename FieldValue> - void - abstract_proto_node::proto_eventin<FieldValue>:: - do_process_event(const FieldValue & value, const double timestamp) - OPENVRML_THROW1(std::bad_alloc) - { - for (typename listeners::const_iterator listener = - this->listeners_.begin(); - listener != this->listeners_.end(); - ++listener) { - (*listener)->process_event(value, timestamp); - } - } - - /** - * @brief The name of the associated @c eventIn. - * - * @return the name of the associated @c eventIn. - */ - template <typename FieldValue> - const std::string - abstract_proto_node::proto_eventin<FieldValue>::do_eventin_id() const - OPENVRML_NOTHROW - { - using boost::polymorphic_downcast; - proto_node & n = *polymorphic_downcast<proto_node *>(&this->node()); - eventin_map_t::const_iterator pos = - std::find_if(n.eventin_map.begin(), n.eventin_map.end(), - proto_eventin_equal_to(*this)); - assert(pos != n.eventin_map.end()); - return pos->first; - } - - /** - * @brief Add a listener to delegate to. Corresponds to an @c IS statement. - * - * @param[in] listener an @c event_listener to delegate to. - * - * @return @c true if @p listener is added successfully; @c false - * otherwise (if it already exists in the list of delegates). - * - * @exception std::bad_alloc if memory allocation fails. - */ - template <typename FieldValue> - bool - abstract_proto_node::proto_eventin<FieldValue>:: - is(event_listener_type & listener) - OPENVRML_THROW1(std::bad_alloc) - { - return this->listeners_.insert(&listener).second; - } - - /** - * @brief Factory function for @c proto_eventin<FieldValue> instances. - * - * @param[in] type @c field_value::type_id. - * @param[in] node @c proto_node. - * - * @return a @c boost::shared_ptr to a @c proto_eventin<FieldValue> - * instance. - * - * @exception std::bad_alloc if memory allocation fails. - */ - boost::shared_ptr<event_listener> - abstract_proto_node::create_eventin(const field_value::type_id type, - abstract_proto_node & node) - OPENVRML_THROW1(std::bad_alloc) - { - using boost::mpl::for_each; - using openvrml_::field_value_types; - - boost::shared_ptr<openvrml::event_listener> result; - for_each<field_value_types>(proto_eventin_creator(type, node, result)); - assert(result); - return result; - } - - /** - * @internal - * - * @class abstract_proto_node::proto_eventout - * - * @brief @c PROTO @c eventOut handler class template. - */ - - /** - * @internal - * - * @class abstract_proto_node::proto_eventout::listener_t - * - * @brief Listens for events emitted from @c node%s in the @c PROTO - * implementation in order to propagate them out of the @c PROTO - * instance. - */ - - /** - * @var abstract_proto_node::proto_eventout & abstract_proto_node::proto_eventout::listener_t::emitter - * - * @brief Reference to the outer @c proto_eventout class. - * - * @todo It's annoying that we need to carry this around. Should - * investigate the possibility of promoting all this stuff to - * @c proto_eventout and have @c proto_eventout privately inherit - * @c field_value_listener<FieldValue>. - */ - - /** - * @var abstract_proto_node & abstract_proto_node::proto_eventout::listener_t::node - * - * @brief Reference to the @c abstract_proto_node instance. - */ - - /** - * @var FieldValue abstract_proto_node::proto_eventout::listener_t::value - * - * @brief The value of the most recently emitted event. - */ - - /** - * @brief Construct. - * - * @param[in] emitter @c proto_eventout. - * @param[in] node @c abstract_proto_node. - * @param[in] initial_value initial value (used for @c exposedFields). - */ - template <typename FieldValue> - abstract_proto_node::proto_eventout<FieldValue>::listener_t:: - listener_t(proto_eventout & emitter, - abstract_proto_node & node, - const FieldValue & initial_value): - node_event_listener(node), - node_field_value_listener<FieldValue>(node), - emitter(emitter), - node(node), - value(initial_value) - {} - - /** - * @brief Destroy. - */ - template <typename FieldValue> - abstract_proto_node::proto_eventout<FieldValue>::listener_t::~listener_t() - OPENVRML_NOTHROW - {} - - /** - * @brief Get the associated @c eventIn identifier. - */ - template <typename FieldValue> - const std::string - abstract_proto_node::proto_eventout<FieldValue>::listener_t:: - do_eventin_id() const - OPENVRML_NOTHROW - { - return "<proto_node::proto_eventout::listener_t>"; - } - - /** - * @brief Process event. - * - * @param[in] value new value. - * @param[in] timestamp the current time. - * - * @exception std::bad_alloc if memory allocation fails. - */ - template<typename FieldValue> - void - abstract_proto_node::proto_eventout<FieldValue>::listener_t:: - do_process_event(const FieldValue & value, const double timestamp) - OPENVRML_THROW1(std::bad_alloc) - { - if (timestamp > this->emitter.last_time()) { - this->value = value; - node::emit_event(this->emitter, timestamp); - } - } - - /** - * @var abstract_proto_node::proto_eventout::listener_t abstract_proto_node::proto_eventout::listener - * - * @brief Listens for events emitted from nodes in the @c PROTO - * implementation in order to propagate them out of the @c PROTO - * instance. - */ - - /** - * @typedef abstract_proto_node::proto_eventout<FieldValue>::field_value_type - * - * @brief Field value type. - */ - - /** - * @typedef abstract_proto_node::proto_eventout<FieldValue>::event_emitter_type - * - * @brief Event emitter type. - */ - - /** - * @typedef abstract_proto_node::proto_eventout<FieldValue>::event_listener_type - * - * @brief Event listener type. - */ - - /** - * @brief Construct. - * - * @param[in] node @c abstract_proto_node. - * @param[in] initial_value initial value. This is used by - * @c proto_exposedfield<FieldValue> - */ - template <typename FieldValue> - abstract_proto_node::proto_eventout<FieldValue>:: - proto_eventout(abstract_proto_node & node, - const FieldValue & initial_value): - openvrml::event_emitter(this->listener.value), - field_value_emitter<FieldValue>(this->listener.value), - listener(*this, node, initial_value) - {} - - /** - * @brief Destroy. - */ - template <typename FieldValue> - abstract_proto_node::proto_eventout<FieldValue>::~proto_eventout() - OPENVRML_NOTHROW - {} - - /** - * @brief Create an @c IS mapping. - * - * @param[in,out] emitter the @c event_emitter from a node in the @c PROTO - * implementation. - * - * @return @c true if the @c IS mapping is created successfully; @c false - * otherwise (i.e., if it already exists). - * - * @exception std::bad_alloc if memory allocation fails. - */ - template <typename FieldValue> - bool - abstract_proto_node::proto_eventout<FieldValue>:: - is(event_emitter_type & emitter) OPENVRML_THROW1(std::bad_alloc) - { - return emitter.add(this->listener); - } - - /** - * @brief The name of the associated @c eventOut. - * - * @return the name of the associated @c eventOut. - */ - template <typename FieldValue> - const std::string - abstract_proto_node::proto_eventout<FieldValue>::do_eventout_id() const - OPENVRML_NOTHROW - { - abstract_proto_node & n = this->listener.node; - eventout_map_t::const_iterator pos = - std::find_if(n.eventout_map.begin(), n.eventout_map.end(), - proto_eventout_equal_to(*this)); - assert(pos != n.eventout_map.end()); - return pos->first; - } - - /** - * @brief Factory function for @c proto_eventout<FieldValue> instances. - * - * @param[in] type @c field_value::type_id. - * @param[in] node @c abstract_proto_node. - * - * @return a @c boost::shared_ptr to a @c proto_eventout<FieldValue> - * instance. - * - * @exception std::bad_alloc if memory allocation fails. - */ - boost::shared_ptr<event_emitter> - abstract_proto_node::create_eventout(const field_value::type_id type, - abstract_proto_node & node) - OPENVRML_THROW1(std::bad_alloc) - { - using boost::mpl::for_each; - using openvrml_::field_value_types; - - boost::shared_ptr<openvrml::event_emitter> result; - for_each<field_value_types>( - proto_eventout_creator(type, node, result)); - assert(result); - return result; - } - - /** - * @internal - * - * @class proto_node::proto_exposedfield - * - * @brief @c PROTO @c exposedField handler class template. - */ - - /** - * @brief Construct. - * - * @param[in] node proto_node. - * @param[in] initial_value initial value. - */ - template <typename FieldValue> - proto_node::proto_exposedfield<FieldValue>:: - proto_exposedfield(abstract_proto_node & node, - const FieldValue & initial_value): - node_event_listener(node), - openvrml::event_emitter(this->listener.value), - proto_eventin<FieldValue>(node), - proto_eventout<FieldValue>(node, initial_value) - {} - - /** - * @brief Destroy. - */ - template <typename FieldValue> - proto_node::proto_exposedfield<FieldValue>::~proto_exposedfield() - OPENVRML_NOTHROW - {} - - /** - * @brief Process an event. - * - * @param[in] value event value. - * @param[in] timestamp the current time. - * - * @exception std::bad_alloc if memory allocation fails. - */ - template <typename FieldValue> - void - proto_node::proto_exposedfield<FieldValue>:: - do_process_event(const FieldValue & value, const double timestamp) - OPENVRML_THROW1(std::bad_alloc) - { - this->proto_eventin<FieldValue>::do_process_event(value, timestamp); - this->listener.value = value; - node::emit_event(*this, timestamp); - } - - /** - * @brief Factory function for @c proto_exposedfield<FieldValue> instances. - * - * @param[in] type @c field_value::type_id. - * @param[in] node @c proto_node. - * - * @return a @c boost::shared_ptr to a @c proto_exposedfield<FieldValue> - * instance. - * - * @exception std::bad_alloc if memory allocation fails. - */ - boost::shared_ptr<event_listener> - proto_node::create_exposedfield(const field_value & initial_value, - proto_node & node) - OPENVRML_THROW1(std::bad_alloc) - { - using boost::mpl::for_each; - using openvrml_::field_value_types; - - boost::shared_ptr<openvrml::event_listener> result; - for_each<field_value_types>(proto_exposedfield_creator(initial_value, - node, - result)); - assert(result.get()); - return result; - } - - /** - * @brief Construct. - * - * @param[in] type @c node_type. - * @param[in] scope @c scope. - * - * @exception std::bad_alloc if memory allocation fails. - */ - proto_node::proto_node(const node_type & type, - const boost::shared_ptr<openvrml::scope> & scope, - const initial_value_map & initial_values) - OPENVRML_THROW1(std::bad_alloc): - abstract_proto_node(type, scope), - proto_scope(scope) - { - const proto_node_metatype & node_metatype = - static_cast<const proto_node_metatype &>(type.metatype()); - - this->impl_nodes = proto_impl_cloner(node_metatype, - initial_values, - this->proto_scope).clone(); - - // - // Establish routes. - // - typedef proto_node_metatype::routes_t routes_t; - for (routes_t::const_iterator route = node_metatype.routes.begin(); - route != node_metatype.routes.end(); - ++route) { - // XXX - // XXX It would be better to store the node_paths along with the - // XXX route instead of rebuilding them every time we instantiate - // XXX the PROTO. - // XXX - node_path_t path_to_from; - assert(!node_metatype.impl_nodes.empty()); - path_getter(*route->from, path_to_from) - .get_path_from(node_metatype.impl_nodes); - assert(!path_to_from.empty()); - node * const from_node = resolve_node_path(path_to_from, - this->impl_nodes); - assert(from_node); - - node_path_t path_to_to; - path_getter(*route->to, path_to_to) - .get_path_from(node_metatype.impl_nodes); - node * const to_node = resolve_node_path(path_to_to, - this->impl_nodes); - assert(to_node); - - try { - add_route(*from_node, route->eventout, - *to_node, route->eventin); - } catch (unsupported_interface & ex) { - OPENVRML_PRINT_EXCEPTION_(ex); - } catch (field_v... [truncated message content] |