// // Copyright 2010-2011 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 . // #include #include #include #include /*! * The link args for internal use within this cpp file: * * It contains a link (in this case a pointer) to a wax object. * Only the methods in this file may create or parse link args. * The get_link method is the creator of a link args object. * The [] operator will resolve the link and make the [] call. * * TODO: register the link args with the wax obj that it links to. * That way, if the obj destructs, the link can be invalidated. * The operator() will throw, rather than dereferencing bad memory. */ class link_args_t{ public: link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ /* NOP */ } wax::obj & operator()(void) const{ //recursively resolve link args to get at original pointer if (_obj_ptr->type() == typeid(link_args_t)){ return _obj_ptr->as()(); } return *const_cast(_obj_ptr); } private: const wax::obj *_obj_ptr; }; /*! * The proxy args for internal use within this cpp file: * * It contains a link and a key for setting/getting a property. * Only the methods in this file may create or parse proxy args. * Class methods have special handling for the case when the * wax obj contains an instance of the proxy args. */ class proxy_args_t{ public: proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ _obj_link = obj_ptr->get_link(); } wax::obj & operator()(void) const{ return _obj_link.as()(); } const wax::obj & key(void) const{ return _key; } private: wax::obj _obj_link; const wax::obj _key; }; /*********************************************************************** * Structors **********************************************************************/ wax::obj::obj(void){ /* NOP */ } wax::obj::obj(const obj &o){ _contents = o._contents; } wax::obj::~obj(void){ /* NOP */ } /*********************************************************************** * Special Operators **********************************************************************/ wax::obj wax::obj::operator[](const obj &key){ if (_contents.type() == typeid(proxy_args_t)){ obj val = resolve(); //check if its a special link and call if (val.type() == typeid(link_args_t)){ return val.as()()[key]; } //unknown obj throw uhd::type_error("cannot use [] on non wax::obj link"); } else{ return proxy_args_t(this, key); } } wax::obj & wax::obj::operator=(const obj &val){ if (_contents.type() == typeid(proxy_args_t)){ proxy_args_t proxy_args = boost::any_cast(_contents); proxy_args().set(proxy_args.key(), val); } else{ _contents = val._contents; } return *this; } /*********************************************************************** * Public Methods **********************************************************************/ wax::obj wax::obj::get_link(void) const{ return link_args_t(this); } const std::type_info & wax::obj::type(void) const{ return resolve().type(); } /*********************************************************************** * Private Methods **********************************************************************/ boost::any wax::obj::resolve(void) const{ if (_contents.type() == typeid(proxy_args_t)){ obj val; proxy_args_t proxy_args = boost::any_cast(_contents); proxy_args().get(proxy_args.key(), val); return val.resolve(); } else{ return _contents; } } void wax::obj::get(const obj &, obj &){ throw uhd::type_error("Cannot call get on wax obj base class"); } void wax::obj::set(const obj &, const obj &){ throw uhd::type_error("Cannot call set on wax obj base class"); }