X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/178c77606f3186250b42685ca752d0bc34cd02e9..03773e400b6ff2692f2a9ba045d652c3b7b7109d:/include/wx/any.h diff --git a/include/wx/any.h b/include/wx/any.h index 9acda4ef55..26f36e7c68 100644 --- a/include/wx/any.h +++ b/include/wx/any.h @@ -1,794 +1,857 @@ -///////////////////////////////////////////////////////////////////////////// -// 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" - - -// Size of the wxAny value buffer. -enum -{ - WX_ANY_VALUE_BUFFER_SIZE = 16 -}; - -union wxAnyValueBuffer -{ - void* m_ptr; - wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; -}; - -typedef void (*wxAnyClassInfo)(); - - -// -// 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 -{ -public: - /** - Default constructor. - */ - wxAnyValueType(); - - /** - Destructor. - */ - virtual ~wxAnyValueType() - { - } - - /** - This function is used for internal type matching. - */ - virtual wxAnyClassInfo GetClassInfo() const = 0; - - /** - 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; - - /** - Implement this for buffer-to-buffer copy. src.m_ptr can - be expected to be NULL if value type of previously stored - data was different. - */ - 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 - 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::IsSameClass(valueTypePtr) - - //valueTypePtr->CheckType(static_cast(NULL)) - - -/** - Helper macro for defining user value types. - - NB: We really cannot compare sm_classInfo directly in IsSameClass(), - but instead call sm_instance->GetClassInfo(). The former technique - broke at least on GCC 4.2 (but worked on VC8 shared build). -*/ -#define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ - friend class wxAny; \ -public: \ - static void sm_classInfo() {} \ - \ - virtual wxAnyClassInfo GetClassInfo() const \ - { \ - return sm_classInfo; \ - } \ - static bool IsSameClass(const wxAnyValueType* otherType) \ - { \ - return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \ - } \ - 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 -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) - { - return *(reinterpret_cast(&buf.m_buffer[0])); - } -}; - - -template -class wxAnyValueTypeOpsGeneric -{ -public: - template - 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* holder = static_cast*>(buf.m_ptr); - delete holder; - } - - static void SetValue(const T& value, - wxAnyValueBuffer& buf) - { - DataHolder* holder = new DataHolder(value); - buf.m_ptr = holder; - } - - static const T& GetValue(const wxAnyValueBuffer& buf) - { - DataHolder* holder = static_cast*>(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 -class wxAnyValueTypeImplBase : public wxAnyValueType -{ - typedef typename wxIf< wxIsMovable::value && - sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE, - wxPrivate::wxAnyValueTypeOpsMovable, - wxPrivate::wxAnyValueTypeOpsGeneric >::value - Ops; - -public: - wxAnyValueTypeImplBase() : wxAnyValueType() { } - virtual ~wxAnyValueTypeImplBase() { } - - virtual void DeleteValue(wxAnyValueBuffer& buf) const - { - Ops::DeleteValue(buf); - buf.m_ptr = NULL; // This is important - } - - virtual void CopyBuffer(const wxAnyValueBuffer& src, - wxAnyValueBuffer& dst) const - { - Ops::DeleteValue(dst); - 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 -class wxAnyValueTypeImpl : public wxAnyValueTypeImplBase -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) -public: - wxAnyValueTypeImpl() : wxAnyValueTypeImplBase() { } - virtual ~wxAnyValueTypeImpl() { } - - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const - { - wxUnusedVar(src); - wxUnusedVar(dstType); - wxUnusedVar(dst); - return false; - } -}; - -template -wxAnyValueTypeImpl* wxAnyValueTypeImpl::sm_instance = - new wxAnyValueTypeImpl(); - - -// -// 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 : public wxAnyValueTypeImpl##CLSTYPE \ -{ \ - typedef wxAnyBase##CLSTYPE##Type UseDataType; \ -public: \ - wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \ - virtual ~wxAnyValueTypeImpl() { } \ - static void SetValue(const T& value, wxAnyValueBuffer& buf) \ - { \ - *(reinterpret_cast(&buf.m_buffer[0])) = \ - static_cast(value); \ - } \ - static T GetValue(const wxAnyValueBuffer& buf) \ - { \ - return static_cast( \ - *(reinterpret_cast(&buf.m_buffer[0]))); \ - } \ -}; - - -// -// 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 -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt) -public: - wxAnyValueTypeImplInt() : - wxAnyValueTypeImplBase() { } - virtual ~wxAnyValueTypeImplInt() { } - - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const; -}; - - -class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint : - public wxAnyValueTypeImplBase -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint) -public: - wxAnyValueTypeImplUint() : - wxAnyValueTypeImplBase() { } - 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 -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString) -public: - wxAnyValueTypeImplString() : - wxAnyValueTypeImplBase() { } - 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 : public wxAnyValueTypeImplString -{ -public: - wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { } - virtual ~wxAnyValueTypeImpl() { } -}; - - -// -// Bool value type -// -template<> -class WXDLLIMPEXP_BASE wxAnyValueTypeImpl : - public wxAnyValueTypeImplBase -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) -public: - wxAnyValueTypeImpl() : - wxAnyValueTypeImplBase() { } - virtual ~wxAnyValueTypeImpl() { } - - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const; -}; - -// -// Floating point value type -// -class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble : - public wxAnyValueTypeImplBase -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble) -public: - wxAnyValueTypeImplDouble() : - wxAnyValueTypeImplBase() { } - 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) - - -#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::IsSameClass(m_type) ) \ - return (value == static_cast \ - (wxAnyValueTypeImpl::GetValue(m_buffer))); \ - if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ - return (value == static_cast \ - (wxAnyValueTypeImpl::GetValue(m_buffer))); \ - return false; \ -} \ -bool operator==(TUS value) const \ -{ \ - if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ - return (value == static_cast \ - (wxAnyValueTypeImpl::GetValue(m_buffer))); \ - if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ - return (value == static_cast \ - (wxAnyValueTypeImpl::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. -// -class WXDLLIMPEXP_BASE wxAny -{ -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 - wxAny(const T& value) - { - m_type = wxAnyValueTypeImpl::sm_instance; - wxAnyValueTypeImpl::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 - bool CheckType(T* = NULL) - { - return m_type->CheckType(); - } - - /** - 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() 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) - { - AssignAny(any); - return *this; - } - - template - wxAny& operator=(const T &value) - { - m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; - wxAnyValueTypeImpl::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::IsSameClass(m_type) ) - return false; - - return value == - static_cast - (wxAnyValueTypeImpl::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::IsSameClass(m_type) ) - return false; - - return value == - static_cast - (wxAnyValueTypeImpl::GetValue(m_buffer)); - } - - bool operator==(double value) const - { - if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) - return false; - - return value == - static_cast - (wxAnyValueTypeImpl::GetValue(m_buffer)); - } - - bool operator==(bool value) const - { - if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) - return false; - - return value == (wxAnyValueTypeImpl::GetValue(m_buffer)); - } - - //@} - - //@{ - /** - Inequality operators (implement as template). - */ - template - 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 - (such as Visual C++ 6.0). For full compiler ccompatibility - please use wxANY_AS(any, T) macro instead. - */ - // FIXME-VC6: remove this hack when VC6 is no longer supported - template - T As(T* = NULL) const - { - if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) - wxFAIL_MSG("Incorrect or non-convertible data type"); - return static_cast(wxAnyValueTypeImpl::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 - bool GetAs(T* value) const - { - if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) - { - wxAnyValueType* otherType = - wxAnyValueTypeImpl::sm_instance; - wxAnyValueBuffer temp_buf; - - if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) - return false; - - *value = - static_cast(wxAnyValueTypeImpl::GetValue(temp_buf)); - otherType->DeleteValue(temp_buf); - - return true; - } - *value = static_cast(wxAnyValueTypeImpl::GetValue(m_buffer)); - return true; - } - -private: - // Assignment functions - void AssignAny(const wxAny &any); - - template - void Assign(const T &value) - { - m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; - wxAnyValueTypeImpl::SetValue(value, m_buffer); - } - - // Data - wxAnyValueType* m_type; - wxAnyValueBuffer m_buffer; -}; - - -// -// 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(NULL)) - - -template -inline bool wxAnyValueType::CheckType(T* reserved) -{ - wxUnusedVar(reserved); - return wxAnyValueTypeImpl::IsSameClass(this); -} - - - -#endif // wxUSE_ANY - -#endif // _WX_ANY_H_ +///////////////////////////////////////////////////////////////////////////// +// 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" +#include "wx/typeinfo.h" + + +// Size of the wxAny value buffer. +enum +{ + WX_ANY_VALUE_BUFFER_SIZE = 16 +}; + +union wxAnyValueBuffer +{ + union Alignment + { + #if wxHAS_INT64 + wxInt64 m_int64; + #endif + long double m_longDouble; + void ( *m_funcPtr )(void); + void ( wxAnyValueBuffer::*m_mFuncPtr )(void); + } m_alignment; + + 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 +{ + WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType) +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; + + /** + 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. + */ + 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 + 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::IsSameClass(valueTypePtr) + + +/** + Helper macro for defining user value types. + + 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. +*/ +#define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ + friend class wxAny; \ + WX_DECLARE_TYPEINFO_INLINE(CLS) \ +public: \ + static bool IsSameClass(const wxAnyValueType* otherType) \ + { \ + return wxTypeId(*sm_instance) == wxTypeId(*otherType); \ + } \ + 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 +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) + { + return *(reinterpret_cast(&buf.m_buffer[0])); + } +}; + + +template +class wxAnyValueTypeOpsGeneric +{ +public: + template + 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* holder = static_cast*>(buf.m_ptr); + delete holder; + } + + static void SetValue(const T& value, + wxAnyValueBuffer& buf) + { + DataHolder* holder = new DataHolder(value); + buf.m_ptr = holder; + } + + static const T& GetValue(const wxAnyValueBuffer& buf) + { + DataHolder* holder = static_cast*>(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 +class wxAnyValueTypeImplBase : public wxAnyValueType +{ + typedef typename wxIf< wxIsMovable::value && + sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE, + wxPrivate::wxAnyValueTypeOpsMovable, + wxPrivate::wxAnyValueTypeOpsGeneric >::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 +class wxAnyValueTypeImpl : public wxAnyValueTypeImplBase +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) +public: + wxAnyValueTypeImpl() : wxAnyValueTypeImplBase() { } + virtual ~wxAnyValueTypeImpl() { } + + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const + { + wxUnusedVar(src); + wxUnusedVar(dstType); + wxUnusedVar(dst); + return false; + } +}; + +template +wxAnyValueTypeImpl* wxAnyValueTypeImpl::sm_instance = + new wxAnyValueTypeImpl(); + + +// +// 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 : public wxAnyValueTypeImpl##CLSTYPE \ +{ \ + typedef wxAnyBase##CLSTYPE##Type UseDataType; \ +public: \ + wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \ + virtual ~wxAnyValueTypeImpl() { } \ + static void SetValue(const T& value, wxAnyValueBuffer& buf) \ + { \ + *(reinterpret_cast(&buf.m_buffer[0])) = \ + static_cast(value); \ + } \ + static T GetValue(const wxAnyValueBuffer& buf) \ + { \ + return static_cast( \ + *(reinterpret_cast(&buf.m_buffer[0]))); \ + } \ +}; + + +// +// 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 +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt) +public: + wxAnyValueTypeImplInt() : + wxAnyValueTypeImplBase() { } + virtual ~wxAnyValueTypeImplInt() { } + + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const; +}; + + +class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint : + public wxAnyValueTypeImplBase +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint) +public: + wxAnyValueTypeImplUint() : + wxAnyValueTypeImplBase() { } + 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 +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString) +public: + wxAnyValueTypeImplString() : + wxAnyValueTypeImplBase() { } + 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 : public wxAnyValueTypeImplString +{ +public: + wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { } + virtual ~wxAnyValueTypeImpl() { } +}; + + +// +// Bool value type +// +template<> +class WXDLLIMPEXP_BASE wxAnyValueTypeImpl : + public wxAnyValueTypeImplBase +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) +public: + wxAnyValueTypeImpl() : + wxAnyValueTypeImplBase() { } + virtual ~wxAnyValueTypeImpl() { } + + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const; +}; + +// +// Floating point value type +// +class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble : + public wxAnyValueTypeImplBase +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble) +public: + wxAnyValueTypeImplDouble() : + wxAnyValueTypeImplBase() { } + 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) + + +// +// 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 : \ + public wxAnyValueTypeImplBase \ +{ \ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) \ +public: \ + wxAnyValueTypeImpl() : \ + wxAnyValueTypeImplBase() { } \ + 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) + + + +#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::IsSameClass(m_type) ) \ + return (value == static_cast \ + (wxAnyValueTypeImpl::GetValue(m_buffer))); \ + if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ + return (value == static_cast \ + (wxAnyValueTypeImpl::GetValue(m_buffer))); \ + return false; \ +} \ +bool operator==(TUS value) const \ +{ \ + if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ + return (value == static_cast \ + (wxAnyValueTypeImpl::GetValue(m_buffer))); \ + if ( wxAnyValueTypeImpl::IsSameClass(m_type) ) \ + return (value == static_cast \ + (wxAnyValueTypeImpl::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. +// +class wxAny +{ +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 + wxAny(const T& value) + { + m_type = wxAnyValueTypeImpl::sm_instance; + wxAnyValueTypeImpl::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 + bool CheckType(T* = NULL) + { + return m_type->CheckType(); + } + + /** + 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() 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) + { + if (this != &any) + AssignAny(any); + return *this; + } + + template + wxAny& operator=(const T &value) + { + m_type->DeleteValue(m_buffer); + m_type = wxAnyValueTypeImpl::sm_instance; + wxAnyValueTypeImpl::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::IsSameClass(m_type) ) + return false; + + return value == + static_cast + (wxAnyValueTypeImpl::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::IsSameClass(m_type) ) + return false; + + return value == + static_cast + (wxAnyValueTypeImpl::GetValue(m_buffer)); + } + + bool operator==(double value) const + { + if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) + return false; + + return value == + static_cast + (wxAnyValueTypeImpl::GetValue(m_buffer)); + } + + bool operator==(bool value) const + { + if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) + return false; + + return value == (wxAnyValueTypeImpl::GetValue(m_buffer)); + } + + //@} + + //@{ + /** + Inequality operators (implement as template). + */ + template + 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 + (such as Visual C++ 6.0). For full compiler ccompatibility + please use wxANY_AS(any, T) macro instead. + */ + // FIXME-VC6: remove this hack when VC6 is no longer supported + template + T As(T* = NULL) const + { + if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) + { + wxFAIL_MSG("Incorrect or non-convertible data type"); + } + + return static_cast(wxAnyValueTypeImpl::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 + bool GetAs(T* value) const + { + if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) + { + wxAnyValueType* otherType = + wxAnyValueTypeImpl::sm_instance; + wxAnyValueBuffer temp_buf; + + if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) + return false; + + *value = + static_cast(wxAnyValueTypeImpl::GetValue(temp_buf)); + otherType->DeleteValue(temp_buf); + + return true; + } + *value = static_cast(wxAnyValueTypeImpl::GetValue(m_buffer)); + return true; + } + +private: + // Assignment functions + void AssignAny(const wxAny& any) + { + // 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); + } + + template + void Assign(const T &value) + { + m_type->DeleteValue(m_buffer); + m_type = wxAnyValueTypeImpl::sm_instance; + wxAnyValueTypeImpl::SetValue(value, m_buffer); + } + + // Data + wxAnyValueBuffer m_buffer; + wxAnyValueType* m_type; +}; + + +// +// 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(NULL)) + + +template +inline bool wxAnyValueType::CheckType(T* reserved) +{ + wxUnusedVar(reserved); + return wxAnyValueTypeImpl::IsSameClass(this); +} + + + +#endif // wxUSE_ANY + +#endif // _WX_ANY_H_