// // Copyright 2010 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #ifndef INCLUDED_WAX_HPP #define INCLUDED_WAX_HPP #include #include #include /*! * WAX - it's a metaphor! * * The WAX framework allows object to have generic/anyobj properties. * These properties can be addressed through generic/anyobj identifiers. * A property of a WAX object may even be another WAX object. * * When a property is a WAX object, the returned value must be an obj pointer. * A WAX object provides two objs of pointers: obj::ptr and obj::sptr. * The choice of pointer vs smart pointer depends on the owner of the memory. * * Proprties may be referenced though the [] overloaded operator. * The [] operator returns a special proxy that allows for assigment. * Also, the [] operators may be chained as in the folowing examples: * my_obj[prop1][prop2][prop3] = value * value = my_obj[prop1][prop2][prop3] * * Any value returned from an access operation is of wax::obj. * To use this value, it must be cast with wax::cast(value). */ namespace wax{ typedef boost::bad_any_cast bad_cast; /*! * WAX object base class: * * A wax obj has two major purposes: * 1) to act as a polymorphic container, just like boost any * 2) to provide a nested set/get properties interface * * Internally, the polymorphic container is handled by a boost any. * For properties, a subclass should override the set and get methods. * For property nesting, wax obj subclasses return special links * to other wax obj subclasses, and the api handles the magic. */ class obj{ public: //obj pointer typedefs typedef boost::shared_ptr sptr; typedef obj* ptr; /*! * Default constructor: * The contents will be empty. */ obj(void); /*! * Copy constructor: * The contents will be cloned. * \param o another wax::obj */ obj(const obj &o); /*! * Templated any type constructor: * The contents can be anything. * Uses the boost::any to handle the magic. * \param o an object of any type */ template obj(const T &o){ _contents = o; } /*! * Destructor. */ virtual ~obj(void); /*! * The chaining operator: * This operator allows access objs with properties. * A call to the [] operator will return a new proxy obj. * The proxy object is an obj with special proxy contents. * Assignment and casting can be used on this special object * to access the property referenced by the obj key. * \param key a key to identify a property within this obj * \return a special wax obj that proxies the obj and key */ obj operator[](const obj &key); /*! * The assignment operator: * This operator allows for assignment of new contents. * In the special case where this obj contains a proxy, * the value will be set to the proxy's property reference. * \param val the new value to assign to the wax obj * \return a reference to this obj (*this) */ obj & operator=(const obj &val); /*! * Get a link in the chain: * When a wax obj returns another wax obj as part of a get call, * the return value should be set to the result of this method. * Doing so will ensure chain-ability of the returned object. * \return an obj containing a valid link to a wax obj */ obj get_link(void) const; /*! * Get the type of the contents of this obj. * \return a reference to the type_info */ const std::type_info & type(void) const; private: //private interface (override in subclasses) virtual void get(const obj &, obj &); virtual void set(const obj &, const obj &); /*! * Resolve the contents of this obj. * In the case where this obj is a proxy, * the referenced property will be resolved. * Otherwise, just get the private contents. * \return a boost any type with contents */ boost::any resolve(void) const; template friend T cast(const obj &); //private contents of this obj boost::any _contents; }; /*! * Cast a wax::obj into the desired obj. * Usage wax::cast(my_value). * * \param val the obj to cast * \return an object of the desired type * \throw wax::bad_cast when the cast fails */ template T cast(const obj &val){ return boost::any_cast(val.resolve()); } } //namespace wax //ability to use wax::obj with stream operators std::ostream& operator<<(std::ostream &, const wax::obj &); #endif /* INCLUDED_WAX_HPP */