204 lines
7.7 KiB
C++
204 lines
7.7 KiB
C++
/*! @file
|
|
|
|
@id $Id$
|
|
|
|
taken from boost.org boost::Any
|
|
|
|
*/
|
|
// 1 2 3 4 5 6 7 8
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
// See http://www.boost.org/libs/any for Documentation.
|
|
|
|
#ifndef XML_CXX_ANY_INCLUDED
|
|
#define XML_CXX_ANY_INCLUDED
|
|
|
|
#include <algorithm>
|
|
#include <typeinfo>
|
|
#include <stdexcept>
|
|
|
|
namespace xml {
|
|
|
|
class Serialize;
|
|
|
|
//! @cond INTERNAL
|
|
|
|
//! @addtogroup serialization
|
|
//@{
|
|
|
|
/*! @defgroup xmlAny (internal) Any Object with limited Polymorfism
|
|
|
|
@internal The implementation of xml::Any is an adaption of @c
|
|
boost::any (see http://www.boost.org), but instead of
|
|
holding any element, but without polymorfism, the
|
|
implementation of xml::Any only holds basic C++ types
|
|
(@c int, @c long, @c float, ...), plus @c std::string
|
|
and xml::Serialize. All other non-standard-C++ types
|
|
are stored as xml::Serialize*. This way, we can get a
|
|
polymorfic any type, but only for children of
|
|
xml::Serialize, but in fact, that's all we
|
|
need. Another limitation is, that xml::Any only stores
|
|
pointer types. Simply because we don't need more. */
|
|
//@{
|
|
|
|
//! @internal Number of supported types that can be stored as XML.
|
|
const int MAX_NUM(14);
|
|
|
|
template<int NUM> struct ToType {typedef Serialize Type;};
|
|
template<> struct ToType<1> {typedef Serialize Type;};
|
|
template<> struct ToType<2> {typedef std::string Type;};
|
|
template<> struct ToType<3> {typedef bool Type;};
|
|
template<> struct ToType<4> {typedef unsigned char Type;};
|
|
template<> struct ToType<5> {typedef signed char Type;};
|
|
template<> struct ToType<6> {typedef char Type;};
|
|
template<> struct ToType<7> {typedef unsigned short Type;};
|
|
template<> struct ToType<8> {typedef signed short Type;};
|
|
template<> struct ToType<9> {typedef unsigned int Type;};
|
|
template<> struct ToType<10> {typedef signed int Type;};
|
|
template<> struct ToType<11> {typedef unsigned long Type;};
|
|
template<> struct ToType<12> {typedef signed long Type;};
|
|
template<> struct ToType<13> {typedef float Type;};
|
|
template<> struct ToType<14> {typedef double Type;};
|
|
|
|
template<typename T> struct ToNum {static const int NUM = 1;};
|
|
template<> struct ToNum<Serialize > {static const int NUM = 1;};
|
|
template<> struct ToNum<std::string > {static const int NUM = 2;};
|
|
template<> struct ToNum<bool > {static const int NUM = 3;};
|
|
template<> struct ToNum<unsigned char > {static const int NUM = 4;};
|
|
template<> struct ToNum<signed char > {static const int NUM = 5;};
|
|
template<> struct ToNum< char > {static const int NUM = 6;};
|
|
template<> struct ToNum<unsigned short> {static const int NUM = 7;};
|
|
template<> struct ToNum<signed short> {static const int NUM = 8;};
|
|
template<> struct ToNum<unsigned int > {static const int NUM = 9;};
|
|
template<> struct ToNum<signed int > {static const int NUM = 10;};
|
|
template<> struct ToNum<unsigned long > {static const int NUM = 11;};
|
|
template<> struct ToNum<signed long > {static const int NUM = 12;};
|
|
template<> struct ToNum<float > {static const int NUM = 13;};
|
|
template<> struct ToNum<double > {static const int NUM = 14;};
|
|
|
|
template<typename T> bool isSerialize() {
|
|
return ToNum<T>::NUM == 1;
|
|
}
|
|
|
|
template <typename T, bool GOOD=(ToNum<T>::NUM==1)> struct Mapper {
|
|
static Serialize* toSerialize(T& obj) {
|
|
return 0;
|
|
}
|
|
};
|
|
template <typename T> struct Mapper<T, true> {
|
|
static Serialize* toSerialize(T& obj) {
|
|
return dynamic_cast<Serialize*>(&obj);
|
|
}
|
|
};
|
|
|
|
class Any {
|
|
public:
|
|
Any(): _content(0) {}
|
|
template<typename TYPE> Any(TYPE* value):
|
|
_content(new Holder<TYPE>(value)) {
|
|
}
|
|
Any(const Any& other):
|
|
_content(other._content?other._content->clone():0) {
|
|
}
|
|
~Any() {
|
|
delete _content;
|
|
}
|
|
Any& swap(Any& rhs) {
|
|
std::swap(_content, rhs._content);
|
|
return *this;
|
|
}
|
|
template<typename TYPE> Any& operator=(TYPE* rhs) {
|
|
Any(rhs).swap(*this);
|
|
return *this;
|
|
}
|
|
Any& operator=(const Any& rhs) {
|
|
Any(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<typename TYPE> class Holder: public Placeholder {
|
|
public:
|
|
Holder(typename ToType<ToNum<TYPE>::NUM>::Type* value):
|
|
_held(value) {
|
|
}
|
|
virtual const std::type_info& type() const {
|
|
return typeid(typename ToType<ToNum<TYPE>::NUM>::Type);
|
|
}
|
|
virtual Placeholder* clone() const {
|
|
return new Holder(_held);
|
|
}
|
|
typename ToType<ToNum<TYPE>::NUM>::Type* _held;
|
|
};
|
|
private:
|
|
template<typename TYPE> friend TYPE* any_cast(Any*);
|
|
template<typename TYPE> friend TYPE* any_cast(Any&);
|
|
Placeholder* _content;
|
|
};
|
|
template<typename TYPE> TYPE* any_cast(Any* operand) {
|
|
return operand && operand->type() == typeid(TYPE)
|
|
? static_cast<Any::Holder<TYPE>*>(operand->_content)->_held
|
|
: 0;
|
|
}
|
|
template<typename TYPE> const TYPE* any_cast(const Any* operand) {
|
|
return any_cast<TYPE>(const_cast<Any*>(operand));
|
|
}
|
|
template<typename TYPE> TYPE* any_cast(Any& operand) {
|
|
if (operand.type()==typeid(TYPE))
|
|
return static_cast<Any::Holder<TYPE>*>(operand._content)->_held;
|
|
throw std::bad_cast();
|
|
}
|
|
template<typename TYPE> const TYPE* any_cast(const Any& operand) {
|
|
return any_cast<TYPE>(const_cast<Any&>(operand));
|
|
}
|
|
|
|
//@}
|
|
//@}
|
|
|
|
//! @endcond INTERNAL
|
|
|
|
}
|
|
|
|
// Note for this file only (this file is in large parts taken from boost):
|
|
|
|
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// 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.
|
|
|
|
#endif
|