/* * Boost Software License - Version 1.0 - August 17th, 2003 * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and * all derivative works of the Software, unless such copies or derivative * works are solely in the form of machine-executable object code generated by * a source language processor. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ // EQEmu::Any is a modified version of Boost::Any and as such retains the Boost licensing. #ifndef EQEMU_COMMON_ANY_H #define EQEMU_COMMON_ANY_H #include #include namespace EQEmu { class Any { public: Any() : content(nullptr) { } template Any(const ValueType &value) : content(new Holder(value)) { } Any(const Any &other) : content(other.content ? other.content->clone() : 0) { } ~Any() { if(content) delete content; } Any& swap(Any &rhs) { std::swap(content, rhs.content); return *this; } template Any& operator=(const ValueType &rhs) { Any(rhs).swap(*this); return *this; } Any& operator=(Any rhs) { rhs.swap(*this); return *this; } bool empty() const { return !content; } const std::type_info& type() const { return content ? content->type() : typeid(void); } class Placeholder { public: virtual ~Placeholder() { } virtual const std::type_info& type() const = 0; virtual Placeholder* clone() const = 0; }; template class Holder : public Placeholder { public: Holder(const ValueType &value) : held(value) { } virtual const std::type_info& type() const { return typeid(ValueType); } virtual Placeholder* clone() const { return new Holder(held); } ValueType held; private: Holder& operator=(const Holder&); }; private: template friend ValueType* any_cast(Any*); template friend ValueType* unsafe_any_cast(Any*); Placeholder* content; }; class bad_any_cast : public std::bad_cast { public: virtual const char * what() const throw() { return "DBI::bad_any_cast: failed conversion using DBI::any_cast"; } }; template ValueType* any_cast(Any* operand) { return operand && operand->type() == typeid(ValueType) ? &static_cast*>(operand->content)->held : nullptr; } template inline const ValueType* any_cast(const Any* operand) { return any_cast(const_cast(operand)); } template ValueType any_cast(Any& operand) { typedef typename std::remove_reference::type nonref; nonref* result = any_cast(&operand); if(!result) throw bad_any_cast(); return *result; } template inline ValueType any_cast(const Any& operand) { typedef typename std::remove_reference::type nonref; return any_cast(const_cast(operand)); } template inline ValueType* unsafe_any_cast(Any* operand) { return &static_cast*>(operand->content)->held; } template inline const ValueType* unsafe_any_cast(const Any* operand) { return unsafe_any_cast(const_cast(operand)); } } #endif