2009-09-19 15:41:08 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: wx/any.h
|
|
|
|
// Purpose: wxAny class
|
|
|
|
// Author: Jaakko Salli
|
|
|
|
// Modified by:
|
|
|
|
// Created: 07/05/2009
|
|
|
|
// RCS-ID: $Id$
|
|
|
|
// Copyright: (c) wxWidgets team
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifndef _WX_ANY_H_
|
|
|
|
#define _WX_ANY_H_
|
|
|
|
|
|
|
|
#include "wx/defs.h"
|
|
|
|
|
|
|
|
#if wxUSE_ANY
|
|
|
|
|
|
|
|
#include "wx/string.h"
|
|
|
|
#include "wx/meta/movable.h"
|
|
|
|
#include "wx/meta/if.h"
|
2009-11-19 19:27:24 +00:00
|
|
|
#include "wx/typeinfo.h"
|
2009-09-19 15:41:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Size of the wxAny value buffer.
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
WX_ANY_VALUE_BUFFER_SIZE = 16
|
|
|
|
};
|
|
|
|
|
|
|
|
union wxAnyValueBuffer
|
|
|
|
{
|
2009-09-27 16:30:26 +00:00
|
|
|
union Alignment
|
|
|
|
{
|
|
|
|
#if wxHAS_INT64
|
|
|
|
wxInt64 m_int64;
|
|
|
|
#endif
|
|
|
|
long double m_longDouble;
|
|
|
|
void ( *m_funcPtr )(void);
|
|
|
|
void ( wxAnyValueBuffer::*m_mFuncPtr )(void);
|
|
|
|
} m_alignment;
|
|
|
|
|
2009-09-19 15:41:08 +00:00
|
|
|
void* m_ptr;
|
|
|
|
wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// wxAnyValueType is base class for value type functionality for C++ data
|
|
|
|
// types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
|
|
|
|
// will create a satisfactory wxAnyValueType implementation for a data type.
|
|
|
|
//
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueType
|
|
|
|
{
|
2009-11-19 19:27:24 +00:00
|
|
|
WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType)
|
2009-09-19 15:41:08 +00:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
Default constructor.
|
|
|
|
*/
|
|
|
|
wxAnyValueType();
|
|
|
|
|
|
|
|
/**
|
|
|
|
Destructor.
|
|
|
|
*/
|
|
|
|
virtual ~wxAnyValueType()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
This function is used for internal type matching.
|
|
|
|
*/
|
|
|
|
virtual bool IsSameType(const wxAnyValueType* otherType) const = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
This function is called every time the data in wxAny
|
|
|
|
buffer needs to be freed.
|
|
|
|
*/
|
|
|
|
virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0;
|
|
|
|
|
|
|
|
/**
|
2009-09-29 13:38:20 +00:00
|
|
|
Implement this for buffer-to-buffer copy.
|
|
|
|
|
|
|
|
@param src
|
|
|
|
This is the source data buffer.
|
|
|
|
|
|
|
|
@param dst
|
|
|
|
This is the destination data buffer that is in either
|
|
|
|
uninitialized or freed state.
|
2009-09-19 15:41:08 +00:00
|
|
|
*/
|
|
|
|
virtual void CopyBuffer(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueBuffer& dst) const = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Convert value into buffer of different type. Return false if
|
|
|
|
not possible.
|
|
|
|
*/
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Use this template function for checking if wxAnyValueType represents
|
|
|
|
a specific C++ data type.
|
|
|
|
|
|
|
|
@remarks This template function does not work on some older compilers
|
|
|
|
(such as Visual C++ 6.0). For full compiler ccompatibility
|
|
|
|
please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
|
|
|
|
instead.
|
|
|
|
|
|
|
|
@see wxAny::CheckType()
|
|
|
|
*/
|
|
|
|
// FIXME-VC6: remove this hack when VC6 is no longer supported
|
|
|
|
template <typename T>
|
|
|
|
bool CheckType(T* reserved = NULL);
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// This method of checking the type is compatible with VC6
|
|
|
|
#define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
|
|
|
|
wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Helper macro for defining user value types.
|
|
|
|
|
2009-11-19 19:27:24 +00:00
|
|
|
Even though C++ RTTI would be fully available to use, we'd have to to
|
|
|
|
facilitate sub-type system which allows, for instance, wxAny with
|
|
|
|
signed short '15' to be treated equal to wxAny with signed long long '15'.
|
|
|
|
Having sm_instance is important here.
|
2009-09-19 15:41:08 +00:00
|
|
|
*/
|
|
|
|
#define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
|
|
|
|
friend class wxAny; \
|
2009-11-19 19:27:24 +00:00
|
|
|
WX_DECLARE_TYPEINFO_INLINE(CLS) \
|
2009-09-19 15:41:08 +00:00
|
|
|
public: \
|
|
|
|
static bool IsSameClass(const wxAnyValueType* otherType) \
|
|
|
|
{ \
|
2009-11-19 19:27:24 +00:00
|
|
|
return wxTypeId(*sm_instance) == wxTypeId(*otherType); \
|
2009-09-19 15:41:08 +00:00
|
|
|
} \
|
|
|
|
virtual bool IsSameType(const wxAnyValueType* otherType) const \
|
|
|
|
{ \
|
|
|
|
return IsSameClass(otherType); \
|
|
|
|
} \
|
|
|
|
private: \
|
|
|
|
static CLS* sm_instance; \
|
|
|
|
public: \
|
|
|
|
static wxAnyValueType* GetInstance() \
|
|
|
|
{ \
|
|
|
|
return sm_instance; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
|
|
|
|
CLS* CLS::sm_instance = new CLS();
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __VISUALC6__
|
|
|
|
// "non dll-interface class 'xxx' used as base interface
|
|
|
|
#pragma warning (push)
|
|
|
|
#pragma warning (disable:4275)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
Following are helper classes for the wxAnyValueTypeImplBase.
|
|
|
|
*/
|
|
|
|
namespace wxPrivate
|
|
|
|
{
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class wxAnyValueTypeOpsMovable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static void DeleteValue(wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
wxUnusedVar(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SetValue(const T& value,
|
|
|
|
wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
memcpy(buf.m_buffer, &value, sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const T& GetValue(const wxAnyValueBuffer& buf)
|
|
|
|
{
|
2010-04-04 15:22:43 +00:00
|
|
|
// Breaking this code into two lines should supress
|
|
|
|
// GCC's 'type-punned pointer will break strict-aliasing rules'
|
|
|
|
// warning.
|
|
|
|
const T* value = reinterpret_cast<const T*>(&buf.m_buffer[0]);
|
|
|
|
return *value;
|
2009-09-19 15:41:08 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class wxAnyValueTypeOpsGeneric
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
template<typename T2>
|
|
|
|
class DataHolder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DataHolder(const T2& value)
|
|
|
|
{
|
|
|
|
m_value = value;
|
|
|
|
}
|
|
|
|
virtual ~DataHolder() { }
|
|
|
|
|
|
|
|
T2 m_value;
|
|
|
|
private:
|
|
|
|
wxDECLARE_NO_COPY_CLASS(DataHolder);
|
|
|
|
};
|
|
|
|
|
|
|
|
static void DeleteValue(wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr);
|
|
|
|
delete holder;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SetValue(const T& value,
|
|
|
|
wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
DataHolder<T>* holder = new DataHolder<T>(value);
|
|
|
|
buf.m_ptr = holder;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const T& GetValue(const wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr);
|
|
|
|
return holder->m_value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace wxPrivate
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Intermediate template for the generic value type implementation.
|
|
|
|
We can derive from this same value type for multiple actual types
|
|
|
|
(for instance, we can have wxAnyValueTypeImplInt for all signed
|
|
|
|
integer types), and also easily implement specialized templates
|
|
|
|
with specific dynamic type conversion.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
class wxAnyValueTypeImplBase : public wxAnyValueType
|
|
|
|
{
|
|
|
|
typedef typename wxIf< wxIsMovable<T>::value &&
|
|
|
|
sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE,
|
|
|
|
wxPrivate::wxAnyValueTypeOpsMovable<T>,
|
|
|
|
wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value
|
|
|
|
Ops;
|
|
|
|
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImplBase() : wxAnyValueType() { }
|
|
|
|
virtual ~wxAnyValueTypeImplBase() { }
|
|
|
|
|
|
|
|
virtual void DeleteValue(wxAnyValueBuffer& buf) const
|
|
|
|
{
|
|
|
|
Ops::DeleteValue(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void CopyBuffer(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueBuffer& dst) const
|
|
|
|
{
|
|
|
|
Ops::SetValue(Ops::GetValue(src), dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
It is important to reimplement this in any specialized template
|
|
|
|
classes that inherit from wxAnyValueTypeImplBase.
|
|
|
|
*/
|
|
|
|
static void SetValue(const T& value,
|
|
|
|
wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
Ops::SetValue(value, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
It is important to reimplement this in any specialized template
|
|
|
|
classes that inherit from wxAnyValueTypeImplBase.
|
|
|
|
*/
|
|
|
|
static const T& GetValue(const wxAnyValueBuffer& buf)
|
|
|
|
{
|
|
|
|
return Ops::GetValue(buf);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Generic value type template. Note that bulk of the implementation
|
|
|
|
resides in wxAnyValueTypeImplBase.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
class wxAnyValueTypeImpl : public wxAnyValueTypeImplBase<T>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<T>)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImpl() : wxAnyValueTypeImplBase<T>() { }
|
|
|
|
virtual ~wxAnyValueTypeImpl() { }
|
|
|
|
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const
|
|
|
|
{
|
|
|
|
wxUnusedVar(src);
|
|
|
|
wxUnusedVar(dstType);
|
|
|
|
wxUnusedVar(dst);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
wxAnyValueTypeImpl<T>* wxAnyValueTypeImpl<T>::sm_instance =
|
|
|
|
new wxAnyValueTypeImpl<T>();
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Helper macro for using same base value type implementation for multiple
|
|
|
|
// actual C++ data types.
|
|
|
|
//
|
|
|
|
#define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
|
|
|
|
template<> \
|
|
|
|
class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
|
|
|
|
{ \
|
|
|
|
typedef wxAnyBase##CLSTYPE##Type UseDataType; \
|
|
|
|
public: \
|
|
|
|
wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
|
|
|
|
virtual ~wxAnyValueTypeImpl() { } \
|
|
|
|
static void SetValue(const T& value, wxAnyValueBuffer& buf) \
|
|
|
|
{ \
|
2010-04-04 15:22:43 +00:00
|
|
|
void* voidPtr = reinterpret_cast<void*>(&buf.m_buffer[0]); \
|
|
|
|
UseDataType* dptr = reinterpret_cast<UseDataType*>(voidPtr); \
|
|
|
|
*dptr = static_cast<UseDataType>(value); \
|
2009-09-19 15:41:08 +00:00
|
|
|
} \
|
|
|
|
static T GetValue(const wxAnyValueBuffer& buf) \
|
|
|
|
{ \
|
2010-04-04 15:22:43 +00:00
|
|
|
const void* voidPtr = \
|
|
|
|
reinterpret_cast<const void*>(&buf.m_buffer[0]); \
|
|
|
|
const UseDataType* sptr = \
|
|
|
|
reinterpret_cast<const UseDataType*>(voidPtr); \
|
|
|
|
return static_cast<T>(*sptr); \
|
2009-09-19 15:41:08 +00:00
|
|
|
} \
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Integer value types
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifdef wxLongLong_t
|
|
|
|
typedef wxLongLong_t wxAnyBaseIntType;
|
|
|
|
typedef wxULongLong_t wxAnyBaseUintType;
|
|
|
|
#else
|
|
|
|
typedef long wxAnyBaseIntType;
|
|
|
|
typedef unsigned long wxAnyBaseUintType;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt :
|
|
|
|
public wxAnyValueTypeImplBase<wxAnyBaseIntType>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImplInt() :
|
|
|
|
wxAnyValueTypeImplBase<wxAnyBaseIntType>() { }
|
|
|
|
virtual ~wxAnyValueTypeImplInt() { }
|
|
|
|
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint :
|
|
|
|
public wxAnyValueTypeImplBase<wxAnyBaseUintType>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImplUint() :
|
|
|
|
wxAnyValueTypeImplBase<wxAnyBaseUintType>() { }
|
|
|
|
virtual ~wxAnyValueTypeImplUint() { }
|
|
|
|
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(signed long, Int)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(signed int, Int)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(signed short, Int)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(signed char, Int)
|
|
|
|
#ifdef wxLongLong_t
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t, Int)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint)
|
|
|
|
#ifdef wxLongLong_t
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t, Uint)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// String value type
|
|
|
|
//
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueTypeImplString :
|
|
|
|
public wxAnyValueTypeImplBase<wxString>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImplString() :
|
|
|
|
wxAnyValueTypeImplBase<wxString>() { }
|
|
|
|
virtual ~wxAnyValueTypeImplString() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
Convert value into buffer of different type. Return false if
|
|
|
|
not possible.
|
|
|
|
*/
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
class wxAnyValueTypeImpl<wxString> : public wxAnyValueTypeImplString
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
|
|
|
|
virtual ~wxAnyValueTypeImpl() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Bool value type
|
|
|
|
//
|
|
|
|
template<>
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueTypeImpl<bool> :
|
|
|
|
public wxAnyValueTypeImplBase<bool>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImpl() :
|
|
|
|
wxAnyValueTypeImplBase<bool>() { }
|
|
|
|
virtual ~wxAnyValueTypeImpl() { }
|
|
|
|
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Floating point value type
|
|
|
|
//
|
|
|
|
class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble :
|
|
|
|
public wxAnyValueTypeImplBase<double>
|
|
|
|
{
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
|
|
|
|
public:
|
|
|
|
wxAnyValueTypeImplDouble() :
|
|
|
|
wxAnyValueTypeImplBase<double>() { }
|
|
|
|
virtual ~wxAnyValueTypeImplDouble() { }
|
|
|
|
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
|
|
|
wxAnyValueType* dstType,
|
|
|
|
wxAnyValueBuffer& dst) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
// WX_ANY_DEFINE_SUB_TYPE requires this
|
|
|
|
typedef double wxAnyBaseDoubleType;
|
|
|
|
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(float, Double)
|
|
|
|
WX_ANY_DEFINE_SUB_TYPE(double, Double)
|
|
|
|
|
|
|
|
|
2009-10-03 10:43:21 +00:00
|
|
|
//
|
|
|
|
// Defines a dummy wxAnyValueTypeImpl<> with given export
|
|
|
|
// declaration. This is needed if a class is used with
|
|
|
|
// wxAny in both user shared library and application.
|
|
|
|
//
|
|
|
|
#define wxDECLARE_ANY_TYPE(CLS, DECL) \
|
|
|
|
template<> \
|
|
|
|
class DECL wxAnyValueTypeImpl<CLS> : \
|
|
|
|
public wxAnyValueTypeImplBase<CLS> \
|
|
|
|
{ \
|
|
|
|
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<CLS>) \
|
|
|
|
public: \
|
|
|
|
wxAnyValueTypeImpl() : \
|
|
|
|
wxAnyValueTypeImplBase<CLS>() { } \
|
|
|
|
virtual ~wxAnyValueTypeImpl() { } \
|
|
|
|
\
|
|
|
|
virtual bool ConvertValue(const wxAnyValueBuffer& src, \
|
|
|
|
wxAnyValueType* dstType, \
|
|
|
|
wxAnyValueBuffer& dst) const \
|
|
|
|
{ \
|
|
|
|
wxUnusedVar(src); \
|
|
|
|
wxUnusedVar(dstType); \
|
|
|
|
wxUnusedVar(dst); \
|
|
|
|
return false; \
|
|
|
|
} \
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure some of wx's own types get the right wxAnyValueType export
|
|
|
|
// (this is needed only for types that are referred to from wxBase.
|
|
|
|
// currently we may not use any of these types from there, but let's
|
|
|
|
// use the macro on at least one to make sure it compiles since we can't
|
|
|
|
// really test it properly in unittests since a separate DLL would
|
|
|
|
// be needed).
|
|
|
|
#if wxUSE_DATETIME
|
|
|
|
#include "wx/datetime.h"
|
|
|
|
wxDECLARE_ANY_TYPE(wxDateTime, WXDLLIMPEXP_BASE)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//#include "wx/object.h"
|
|
|
|
//wxDECLARE_ANY_TYPE(wxObject*, WXDLLIMPEXP_BASE)
|
|
|
|
|
|
|
|
//#include "wx/arrstr.h"
|
|
|
|
//wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE)
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-19 15:41:08 +00:00
|
|
|
#ifdef __VISUALC6__
|
|
|
|
// Re-enable useless VC6 warnings
|
|
|
|
#pragma warning (pop)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Let's define a discrete Null value so we don't have to really
|
|
|
|
ever check if wxAny.m_type pointer is NULL or not. This is an
|
|
|
|
optimization, mostly. Implementation of this value type is
|
|
|
|
"hidden" in the source file.
|
|
|
|
*/
|
|
|
|
extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType*) wxAnyNullValueType;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// We need to implement custom signed/unsigned int equals operators
|
|
|
|
// for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
|
|
|
|
#define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
|
|
|
|
bool operator==(TS value) const \
|
|
|
|
{ \
|
|
|
|
if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
|
|
|
|
return (value == static_cast<TS> \
|
|
|
|
(wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
|
|
|
|
if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
|
|
|
|
return (value == static_cast<TS> \
|
|
|
|
(wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
|
|
|
|
return false; \
|
|
|
|
} \
|
|
|
|
bool operator==(TUS value) const \
|
|
|
|
{ \
|
|
|
|
if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
|
|
|
|
return (value == static_cast<TUS> \
|
|
|
|
(wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
|
|
|
|
if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
|
|
|
|
return (value == static_cast<TUS> \
|
|
|
|
(wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
|
|
|
|
return false; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// The wxAny class represents a container for any type. A variant's value
|
|
|
|
// can be changed at run time, possibly to a different type of value.
|
|
|
|
//
|
|
|
|
// As standard, wxAny can store value of almost any type, in a fairly
|
|
|
|
// optimal manner even.
|
|
|
|
//
|
2009-09-20 12:37:16 +00:00
|
|
|
class wxAny
|
2009-09-19 15:41:08 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
Default constructor.
|
|
|
|
*/
|
|
|
|
wxAny()
|
|
|
|
{
|
|
|
|
m_type = wxAnyNullValueType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Destructor.
|
|
|
|
*/
|
|
|
|
~wxAny()
|
|
|
|
{
|
|
|
|
m_type->DeleteValue(m_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/**
|
|
|
|
Various constructors.
|
|
|
|
*/
|
|
|
|
wxAny(const char* value)
|
|
|
|
{
|
|
|
|
m_type = wxAnyNullValueType;
|
|
|
|
Assign(wxString(value));
|
|
|
|
}
|
|
|
|
wxAny(const wchar_t* value)
|
|
|
|
{
|
|
|
|
m_type = wxAnyNullValueType;
|
|
|
|
Assign(wxString(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
wxAny(const wxAny& any)
|
|
|
|
{
|
|
|
|
m_type = wxAnyNullValueType;
|
|
|
|
AssignAny(any);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
wxAny(const T& value)
|
|
|
|
{
|
|
|
|
m_type = wxAnyValueTypeImpl<T>::sm_instance;
|
|
|
|
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
|
|
|
|
}
|
|
|
|
//@}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Use this template function for checking if this wxAny holds
|
|
|
|
a specific C++ data type.
|
|
|
|
|
|
|
|
@remarks This template function does not work on some older compilers
|
|
|
|
(such as Visual C++ 6.0). For full compiler ccompatibility
|
|
|
|
please use wxANY_CHECK_TYPE(any, T) macro instead.
|
|
|
|
|
|
|
|
@see wxAnyValueType::CheckType()
|
|
|
|
*/
|
|
|
|
// FIXME-VC6: remove this hack when VC6 is no longer supported
|
|
|
|
template <typename T>
|
|
|
|
bool CheckType(T* = NULL)
|
|
|
|
{
|
|
|
|
return m_type->CheckType<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Returns the value type as wxAnyValueType instance.
|
|
|
|
|
|
|
|
@remarks You cannot reliably test whether two wxAnys are of
|
|
|
|
same value type by simply comparing return values
|
|
|
|
of wxAny::GetType(). Instead use
|
|
|
|
wxAnyValueType::CheckType<T>() template function.
|
|
|
|
*/
|
|
|
|
const wxAnyValueType* GetType() const
|
|
|
|
{
|
|
|
|
return m_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Tests if wxAny is null (that is, whether there is data).
|
|
|
|
*/
|
|
|
|
bool IsNull() const
|
|
|
|
{
|
|
|
|
return (m_type == wxAnyNullValueType);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Makes wxAny null (that is, clears it).
|
|
|
|
*/
|
|
|
|
void MakeNull()
|
|
|
|
{
|
|
|
|
m_type->DeleteValue(m_buffer);
|
|
|
|
m_type = wxAnyNullValueType;
|
|
|
|
}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/**
|
|
|
|
Assignment operators.
|
|
|
|
*/
|
|
|
|
wxAny& operator=(const wxAny &any)
|
|
|
|
{
|
2009-12-02 16:36:50 +00:00
|
|
|
if (this != &any)
|
|
|
|
AssignAny(any);
|
2009-09-19 15:41:08 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
wxAny& operator=(const T &value)
|
|
|
|
{
|
|
|
|
m_type->DeleteValue(m_buffer);
|
|
|
|
m_type = wxAnyValueTypeImpl<T>::sm_instance;
|
|
|
|
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxAny& operator=(const char* value)
|
|
|
|
{ Assign(wxString(value)); return *this; }
|
|
|
|
wxAny& operator=(const wchar_t* value)
|
|
|
|
{ Assign(wxString(value)); return *this; }
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/**
|
|
|
|
Equality operators.
|
|
|
|
*/
|
|
|
|
bool operator==(const wxString& value) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<wxString>::IsSameClass(m_type) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return value ==
|
|
|
|
static_cast<wxString>
|
|
|
|
(wxAnyValueTypeImpl<wxString>::GetValue(m_buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const char* value) const
|
|
|
|
{ return (*this) == wxString(value); }
|
|
|
|
bool operator==(const wchar_t* value) const
|
|
|
|
{ return (*this) == wxString(value); }
|
|
|
|
|
|
|
|
//
|
|
|
|
// We need to implement custom signed/unsigned int equals operators
|
|
|
|
// for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
|
|
|
|
WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
|
|
|
|
WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
|
|
|
|
WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
|
|
|
|
WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
|
|
|
|
#ifdef wxLongLong_t
|
|
|
|
WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t, wxULongLong_t)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool operator==(float value) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<float>::IsSameClass(m_type) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return value ==
|
|
|
|
static_cast<float>
|
|
|
|
(wxAnyValueTypeImpl<float>::GetValue(m_buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(double value) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<double>::IsSameClass(m_type) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return value ==
|
|
|
|
static_cast<double>
|
|
|
|
(wxAnyValueTypeImpl<double>::GetValue(m_buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(bool value) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<bool>::IsSameClass(m_type) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return value == (wxAnyValueTypeImpl<bool>::GetValue(m_buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/**
|
|
|
|
Inequality operators (implement as template).
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
bool operator!=(const T& value) const
|
|
|
|
{ return !((*this) == value); }
|
|
|
|
//@}
|
|
|
|
|
|
|
|
/**
|
|
|
|
This template function converts wxAny into given type. No dynamic
|
|
|
|
conversion is performed, so if the type is incorrect an assertion
|
|
|
|
failure will occur in debug builds, and a bogus value is returned
|
|
|
|
in release ones.
|
|
|
|
|
|
|
|
@remarks This template function does not work on some older compilers
|
2010-04-11 13:20:10 +00:00
|
|
|
(such as Visual C++ 6.0). For full compiler compatibility
|
2009-09-19 15:41:08 +00:00
|
|
|
please use wxANY_AS(any, T) macro instead.
|
|
|
|
*/
|
|
|
|
// FIXME-VC6: remove this hack when VC6 is no longer supported
|
|
|
|
template<typename T>
|
|
|
|
T As(T* = NULL) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
|
2009-09-19 16:29:42 +00:00
|
|
|
{
|
2009-09-19 15:41:08 +00:00
|
|
|
wxFAIL_MSG("Incorrect or non-convertible data type");
|
2009-09-19 16:29:42 +00:00
|
|
|
}
|
|
|
|
|
2009-09-19 15:41:08 +00:00
|
|
|
return static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Template function that etrieves and converts the value of this
|
|
|
|
variant to the type that T* value is.
|
|
|
|
|
|
|
|
@return Returns @true if conversion was succesfull.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
bool GetAs(T* value) const
|
|
|
|
{
|
|
|
|
if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
|
|
|
|
{
|
|
|
|
wxAnyValueType* otherType =
|
|
|
|
wxAnyValueTypeImpl<T>::sm_instance;
|
|
|
|
wxAnyValueBuffer temp_buf;
|
|
|
|
|
|
|
|
if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value =
|
|
|
|
static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(temp_buf));
|
|
|
|
otherType->DeleteValue(temp_buf);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
*value = static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Assignment functions
|
2009-09-20 12:37:16 +00:00
|
|
|
void AssignAny(const wxAny& any)
|
|
|
|
{
|
2009-09-29 13:38:20 +00:00
|
|
|
// Must delete value - CopyBuffer() never does that
|
|
|
|
m_type->DeleteValue(m_buffer);
|
|
|
|
|
|
|
|
wxAnyValueType* newType = any.m_type;
|
|
|
|
|
|
|
|
if ( !newType->IsSameType(m_type) )
|
|
|
|
m_type = newType;
|
|
|
|
|
|
|
|
newType->CopyBuffer(any.m_buffer, m_buffer);
|
2009-09-20 12:37:16 +00:00
|
|
|
}
|
2009-09-19 15:41:08 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void Assign(const T &value)
|
|
|
|
{
|
|
|
|
m_type->DeleteValue(m_buffer);
|
|
|
|
m_type = wxAnyValueTypeImpl<T>::sm_instance;
|
|
|
|
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Data
|
|
|
|
wxAnyValueBuffer m_buffer;
|
2009-09-27 14:52:34 +00:00
|
|
|
wxAnyValueType* m_type;
|
2009-09-19 15:41:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// This method of checking the type is compatible with VC6
|
|
|
|
#define wxANY_CHECK_TYPE(any, T) \
|
|
|
|
wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T)
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// This method of getting the value is compatible with VC6
|
|
|
|
#define wxANY_AS(any, T) \
|
|
|
|
any.As(static_cast<T*>(NULL))
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline bool wxAnyValueType::CheckType(T* reserved)
|
|
|
|
{
|
|
|
|
wxUnusedVar(reserved);
|
|
|
|
return wxAnyValueTypeImpl<T>::IsSameClass(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // wxUSE_ANY
|
|
|
|
|
|
|
|
#endif // _WX_ANY_H_
|