From: Vadim Zeitlin Date: Sat, 19 Sep 2009 15:41:08 +0000 (+0000) Subject: Set svn properties correctly for the newly added files. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/39601a7f74796aae377ad1520595f083fdafd7b6 Set svn properties correctly for the newly added files. Set svn:keyword and, most importantly, svn:eol-style, to avoid having files with DOS line endings in svn, for the new files added by r61971. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61973 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/any.h b/include/wx/any.h index 9acda4ef55..0a5b075c56 100644 --- a/include/wx/any.h +++ b/include/wx/any.h @@ -1,794 +1,794 @@ -///////////////////////////////////////////////////////////////////////////// -// 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" + + +// 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_ diff --git a/interface/wx/any.h b/interface/wx/any.h index 9dc3442018..acbd9157a2 100644 --- a/interface/wx/any.h +++ b/interface/wx/any.h @@ -1,425 +1,425 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: any.h -// Purpose: interface of wxAny -// Author: wxWidgets team -// RCS-ID: $Id$ -// Licence: wxWindows license -///////////////////////////////////////////////////////////////////////////// - - -/** - @class wxAny - - The wxAny class represents a container for any type. Its value - can be changed at run time, possibly to a different type of value. - - wxAny is successor class for wxVariant, essentially doing the same thing - in a more modern, template-based manner and with transparent support - for any user data type. - - Some pseudo-code'ish example of use with arbitrary user data: - - @code - void SomeFunction() - { - MyClass myObject; - wxAny any = myObject; - - // Do something - // ... - - // Let's do a sanity check to make sure that any still holds - // data of correct type. - if ( any.CheckType() ) - { - // Thank goodness, still a correct type. - MyClass myObject2 = any.As(); - } - else - { - // Something has gone horribly wrong! - wxFAIL(); - } - } - @endcode - - When compared to wxVariant, there are various internal implementation - differences as well. For instance, wxAny only allocates separate data - object in heap for large (ie. size in bytes more than - WX_ANY_VALUE_BUFFER_SIZE) or 'non-movable' data types. Pointers, integers, - bools etc. are fitted in the wxAny's own buffer without need for any extra - allocation. Use following code to declare your own data type as 'movable': - - @code - #include "wx/meta/movable.h" - WX_DECLARE_TYPE_MOVABLE(MyClass) - @endcode - - However, you must be aware that 'movable' means such data that can be - copied with memcpy() without corrupting program integrity. For instance, - movable objects usually cannot contain pointers or references to other - data. wxRect, wxPoint, and wxSize are good examples of movable classes. - - Note that pointers to any and all classes are already automatically - declared as movable data. - - @library{wxbase} - @category{data} - - @see wxAnyValueType, wxVariant -*/ -class wxAny -{ -public: - /** - Default constructor. It seeds the object with a null value. - */ - wxAny(); - - /** - Constructs wxAny from data. - */ - template - wxAny(const T& value); - - /** - Constructs wxAny from another wxAny. - */ - wxAny(const wxAny& any); - - /** - Destructor. - */ - ~wxAny(); - - /** - 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 may not work properly with Visual C++ - 6. For full compiler compatibility, please use - wxANY_AS(any, T) macro instead. - */ - template - T As() const; - - /** - Use this template function for checking if this wxAny holds - a specific C++ data type. - - @remarks This template function may not work properly with Visual C++ - 6. For full compiler compatibility, please use - wxANY_CHECK_TYPE(any, T) macro instead. - - @see wxAnyValueType::CheckType() - */ - template - bool CheckType(); - - /** - Template function that retrieves and converts the value of this - wxAny to the type that T* value is. - - @return Returns @true if conversion was succesfull. - */ - template - bool GetAs(T* value) const; - - /** - 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; - - /** - Tests if wxAny is null (that is, whether there is data). - */ - bool IsNull() const; - - /** - Makes wxAny null (that is, clears it). - */ - void MakeNull(); - - //@{ - /** - @name Assignment operators - */ - template - wxAny& operator=(const T &value); - wxAny& operator=(const wxAny &any); - //@} - - //@{ - /** - @name Equality operators - - @remarks Generic template-based comparison operators have not been - provided for various code consistency reasons, so for custom - data types you have do something like this: - - @code - if ( any.CheckType() && - any.As() == myObjectPtr ) - { - // Do something if any stores myObjectPtr - } - @endcode - */ - bool operator==(signed char value) const; - bool operator==(signed short value) const; - bool operator==(signed int value) const; - bool operator==(signed long value) const; - bool operator==(wxLongLong_t value) const; - bool operator==(unsigned char value) const; - bool operator==(unsigned short value) const; - bool operator==(unsigned int value) const; - bool operator==(unsigned long value) const; - bool operator==(wxULongLong_t value) const; - bool operator==(float value) const; - bool operator==(double value) const; - bool operator==(bool value) const; - bool operator==(const char* value) const; - bool operator==(const wchar_t* value) const; - bool operator==(const wxString& value) const; - //@} - - //@{ - /** - @name Inequality operators - */ - bool operator!=(signed char value) const; - bool operator!=(signed short value) const; - bool operator!=(signed int value) const; - bool operator!=(signed long value) const; - bool operator!=(wxLongLong_t value) const; - bool operator!=(unsigned char value) const; - bool operator!=(unsigned short value) const; - bool operator!=(unsigned int value) const; - bool operator!=(unsigned long value) const; - bool operator!=(wxULongLong_t value) const; - bool operator!=(float value) const; - bool operator!=(double value) const; - bool operator!=(bool value) const; - bool operator!=(const char* value) const; - bool operator!=(const wchar_t* value) const; - bool operator!=(const wxString& value) const; - //@} -}; - -/** - This is value getter macro that is more compatible with older - compilers, such as Visual C++ 6.0. -*/ -#define wxANY_AS(any, T) - - -/** - This is type checking macro that is more compatible with older - compilers, such as Visual C++ 6.0. -*/ -#define wxANY_CHECK_TYPE(any, T) - - -/** - Size of the wxAny value buffer. -*/ -enum -{ - WX_ANY_VALUE_BUFFER_SIZE = 16 -}; - -/** - Type for buffer within wxAny for holding data. -*/ -union wxAnyValueBuffer -{ - void* m_ptr; - wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; -}; - - -/** - @class wxAnyValueType - - wxAnyValueType is base class for value type functionality for C++ data - types used with wxAny. Usually the default template will create a - satisfactory wxAnyValueType implementation for a data type, but - sometimes you may need to add some customization. To do this you will need - to add specialized template of wxAnyValueTypeImpl<>. Often your only - need may be to add dynamic type conversion which would be done like - this: - - @code - 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 - { - // GetValue() is a static member function implemented - // in wxAnyValueTypeImplBase<>. - MyClass value = GetValue(src); - - // TODO: Convert value from src buffer to destination - // type and buffer. If cannot be done, return - // false. This is a simple sample. - if ( dstType->CheckType() ) - { - wxString s = value.ToString(); - wxAnyValueTypeImpl::SetValue(s, dst); - } - else - { - return false; - } - } - }; - - // - // Following must be placed somewhere in your source code - WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) - @endcode - - wxAnyValueTypeImplBase<> template, from which we inherit in the above - example, contains the bulk of the default wxAnyValueTypeImpl<> template - implementation, and as such allows you to easily add some minor - customization. - - If you need a have complete control over the type interpretation, you - will need to derive a class directly from wxAnyValueType, like this: - - @code - template <> - class wxAnyValueTypeImpl : public wxAnyValueType - { - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) - public: - virtual void DeleteValue(wxAnyValueBuffer& buf) const - { - // TODO: Free the data in buffer - // It is important to clear the buffer like this - // at the end of DeleteValue(). - buf.m_ptr = NULL; - } - - virtual void CopyBuffer(const wxAnyValueBuffer& src, - wxAnyValueBuffer& dst) const - { - // TODO: Copy value from one buffer to another. - } - - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const - { - // TODO: Convert value from src buffer to destination - // type and buffer. - } - - // - // Following static functions must be implemented - // - - static void SetValue(const T& value, - wxAnyValueBuffer& buf) - { - // TODO: Store value into buf. - } - - static const T& GetValue(const wxAnyValueBuffer& buf) - { - // TODO: Return reference to value stored in buffer. - } - }; - - // - // Following must be placed somewhere in your source code - WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) - - @endcode - - @library{wxbase} - @category{data} - - @see wxAny -*/ -class wxAnyValueType -{ -public: - /** - Default constructor. - */ - wxAnyValueType(); - - /** - Destructor. - */ - virtual ~wxAnyValueType(); - - /** - 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() - */ - template - bool CheckType(); - - /** - Convert value into buffer of different type. Return false if - not possible. - */ - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) 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; - - /** - This function is called every time the data in wxAny - buffer needs to be freed. - */ - virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0; - - /** - 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 is type checking macro that is more compatible with older - compilers, such as Visual C++ 6.0. -*/ -#define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) +///////////////////////////////////////////////////////////////////////////// +// Name: any.h +// Purpose: interface of wxAny +// Author: wxWidgets team +// RCS-ID: $Id$ +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + + +/** + @class wxAny + + The wxAny class represents a container for any type. Its value + can be changed at run time, possibly to a different type of value. + + wxAny is successor class for wxVariant, essentially doing the same thing + in a more modern, template-based manner and with transparent support + for any user data type. + + Some pseudo-code'ish example of use with arbitrary user data: + + @code + void SomeFunction() + { + MyClass myObject; + wxAny any = myObject; + + // Do something + // ... + + // Let's do a sanity check to make sure that any still holds + // data of correct type. + if ( any.CheckType() ) + { + // Thank goodness, still a correct type. + MyClass myObject2 = any.As(); + } + else + { + // Something has gone horribly wrong! + wxFAIL(); + } + } + @endcode + + When compared to wxVariant, there are various internal implementation + differences as well. For instance, wxAny only allocates separate data + object in heap for large (ie. size in bytes more than + WX_ANY_VALUE_BUFFER_SIZE) or 'non-movable' data types. Pointers, integers, + bools etc. are fitted in the wxAny's own buffer without need for any extra + allocation. Use following code to declare your own data type as 'movable': + + @code + #include "wx/meta/movable.h" + WX_DECLARE_TYPE_MOVABLE(MyClass) + @endcode + + However, you must be aware that 'movable' means such data that can be + copied with memcpy() without corrupting program integrity. For instance, + movable objects usually cannot contain pointers or references to other + data. wxRect, wxPoint, and wxSize are good examples of movable classes. + + Note that pointers to any and all classes are already automatically + declared as movable data. + + @library{wxbase} + @category{data} + + @see wxAnyValueType, wxVariant +*/ +class wxAny +{ +public: + /** + Default constructor. It seeds the object with a null value. + */ + wxAny(); + + /** + Constructs wxAny from data. + */ + template + wxAny(const T& value); + + /** + Constructs wxAny from another wxAny. + */ + wxAny(const wxAny& any); + + /** + Destructor. + */ + ~wxAny(); + + /** + 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 may not work properly with Visual C++ + 6. For full compiler compatibility, please use + wxANY_AS(any, T) macro instead. + */ + template + T As() const; + + /** + Use this template function for checking if this wxAny holds + a specific C++ data type. + + @remarks This template function may not work properly with Visual C++ + 6. For full compiler compatibility, please use + wxANY_CHECK_TYPE(any, T) macro instead. + + @see wxAnyValueType::CheckType() + */ + template + bool CheckType(); + + /** + Template function that retrieves and converts the value of this + wxAny to the type that T* value is. + + @return Returns @true if conversion was succesfull. + */ + template + bool GetAs(T* value) const; + + /** + 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; + + /** + Tests if wxAny is null (that is, whether there is data). + */ + bool IsNull() const; + + /** + Makes wxAny null (that is, clears it). + */ + void MakeNull(); + + //@{ + /** + @name Assignment operators + */ + template + wxAny& operator=(const T &value); + wxAny& operator=(const wxAny &any); + //@} + + //@{ + /** + @name Equality operators + + @remarks Generic template-based comparison operators have not been + provided for various code consistency reasons, so for custom + data types you have do something like this: + + @code + if ( any.CheckType() && + any.As() == myObjectPtr ) + { + // Do something if any stores myObjectPtr + } + @endcode + */ + bool operator==(signed char value) const; + bool operator==(signed short value) const; + bool operator==(signed int value) const; + bool operator==(signed long value) const; + bool operator==(wxLongLong_t value) const; + bool operator==(unsigned char value) const; + bool operator==(unsigned short value) const; + bool operator==(unsigned int value) const; + bool operator==(unsigned long value) const; + bool operator==(wxULongLong_t value) const; + bool operator==(float value) const; + bool operator==(double value) const; + bool operator==(bool value) const; + bool operator==(const char* value) const; + bool operator==(const wchar_t* value) const; + bool operator==(const wxString& value) const; + //@} + + //@{ + /** + @name Inequality operators + */ + bool operator!=(signed char value) const; + bool operator!=(signed short value) const; + bool operator!=(signed int value) const; + bool operator!=(signed long value) const; + bool operator!=(wxLongLong_t value) const; + bool operator!=(unsigned char value) const; + bool operator!=(unsigned short value) const; + bool operator!=(unsigned int value) const; + bool operator!=(unsigned long value) const; + bool operator!=(wxULongLong_t value) const; + bool operator!=(float value) const; + bool operator!=(double value) const; + bool operator!=(bool value) const; + bool operator!=(const char* value) const; + bool operator!=(const wchar_t* value) const; + bool operator!=(const wxString& value) const; + //@} +}; + +/** + This is value getter macro that is more compatible with older + compilers, such as Visual C++ 6.0. +*/ +#define wxANY_AS(any, T) + + +/** + This is type checking macro that is more compatible with older + compilers, such as Visual C++ 6.0. +*/ +#define wxANY_CHECK_TYPE(any, T) + + +/** + Size of the wxAny value buffer. +*/ +enum +{ + WX_ANY_VALUE_BUFFER_SIZE = 16 +}; + +/** + Type for buffer within wxAny for holding data. +*/ +union wxAnyValueBuffer +{ + void* m_ptr; + wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; +}; + + +/** + @class wxAnyValueType + + wxAnyValueType is base class for value type functionality for C++ data + types used with wxAny. Usually the default template will create a + satisfactory wxAnyValueType implementation for a data type, but + sometimes you may need to add some customization. To do this you will need + to add specialized template of wxAnyValueTypeImpl<>. Often your only + need may be to add dynamic type conversion which would be done like + this: + + @code + 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 + { + // GetValue() is a static member function implemented + // in wxAnyValueTypeImplBase<>. + MyClass value = GetValue(src); + + // TODO: Convert value from src buffer to destination + // type and buffer. If cannot be done, return + // false. This is a simple sample. + if ( dstType->CheckType() ) + { + wxString s = value.ToString(); + wxAnyValueTypeImpl::SetValue(s, dst); + } + else + { + return false; + } + } + }; + + // + // Following must be placed somewhere in your source code + WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + @endcode + + wxAnyValueTypeImplBase<> template, from which we inherit in the above + example, contains the bulk of the default wxAnyValueTypeImpl<> template + implementation, and as such allows you to easily add some minor + customization. + + If you need a have complete control over the type interpretation, you + will need to derive a class directly from wxAnyValueType, like this: + + @code + template <> + class wxAnyValueTypeImpl : public wxAnyValueType + { + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + public: + virtual void DeleteValue(wxAnyValueBuffer& buf) const + { + // TODO: Free the data in buffer + // It is important to clear the buffer like this + // at the end of DeleteValue(). + buf.m_ptr = NULL; + } + + virtual void CopyBuffer(const wxAnyValueBuffer& src, + wxAnyValueBuffer& dst) const + { + // TODO: Copy value from one buffer to another. + } + + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const + { + // TODO: Convert value from src buffer to destination + // type and buffer. + } + + // + // Following static functions must be implemented + // + + static void SetValue(const T& value, + wxAnyValueBuffer& buf) + { + // TODO: Store value into buf. + } + + static const T& GetValue(const wxAnyValueBuffer& buf) + { + // TODO: Return reference to value stored in buffer. + } + }; + + // + // Following must be placed somewhere in your source code + WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + + @endcode + + @library{wxbase} + @category{data} + + @see wxAny +*/ +class wxAnyValueType +{ +public: + /** + Default constructor. + */ + wxAnyValueType(); + + /** + Destructor. + */ + virtual ~wxAnyValueType(); + + /** + 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() + */ + template + bool CheckType(); + + /** + Convert value into buffer of different type. Return false if + not possible. + */ + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) 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; + + /** + This function is called every time the data in wxAny + buffer needs to be freed. + */ + virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0; + + /** + 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 is type checking macro that is more compatible with older + compilers, such as Visual C++ 6.0. +*/ +#define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) diff --git a/src/common/any.cpp b/src/common/any.cpp index 62f6b45d08..9923d3ef07 100644 --- a/src/common/any.cpp +++ b/src/common/any.cpp @@ -1,402 +1,402 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: src/common/any.cpp -// Purpose: wxAny class, container for any type -// Author: Jaakko Salli -// Modified by: -// Created: 07/05/2009 -// RCS-ID: $Id$ -// Copyright: (c) wxWidgets team -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ - #pragma hdrstop -#endif - -#include "wx/any.h" - -#if wxUSE_ANY - -#ifndef WX_PRECOMP - #include "wx/math.h" - #include "wx/crt.h" -#endif - -#include "wx/vector.h" -#include "wx/module.h" - -using namespace wxPrivate; - -//------------------------------------------------------------------------- -// wxAnyValueTypeGlobals -//------------------------------------------------------------------------- - -// -// Helper class to manage wxAnyValueType instances and other -// related global variables. -// -// NB: We really need to have wxAnyValueType instances allocated -// in heap. They are stored as static template member variables, -// and with them we just can't be too careful (eg. not allocating -// them in heap broke the type identification in GCC). -// -class wxAnyValueTypeGlobals -{ -public: - wxAnyValueTypeGlobals() - { - } - ~wxAnyValueTypeGlobals() - { - for ( size_t i=0; i m_valueTypes; -}; - -static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL; - -// -// This class is to make sure that wxAnyValueType instances -// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals -// because wxModule itself is instantiated too late. -// -class wxAnyValueTypeGlobalsManager : public wxModule -{ - DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager) -public: - wxAnyValueTypeGlobalsManager() : wxModule() { } - virtual ~wxAnyValueTypeGlobalsManager() { } - - virtual bool OnInit() - { - return true; - } - virtual void OnExit() - { - delete g_wxAnyValueTypeGlobals; - g_wxAnyValueTypeGlobals = NULL; - } -private: -}; - -IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule) - - -//------------------------------------------------------------------------- -// wxAnyValueType -//------------------------------------------------------------------------- - -wxAnyValueType::wxAnyValueType() -{ - if ( !g_wxAnyValueTypeGlobals ) - g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals(); - - g_wxAnyValueTypeGlobals->RegisterValueType(this); -} - -//------------------------------------------------------------------------- -// wxAny -//------------------------------------------------------------------------- - -void wxAny::AssignAny(const wxAny &any) -{ - if ( !any.m_type->IsSameType(m_type) ) - { - m_type->DeleteValue(m_buffer); - m_type = any.m_type; - } - m_type->CopyBuffer(any.m_buffer, m_buffer); -} - -//------------------------------------------------------------------------- -// Dynamic conversion member functions -//------------------------------------------------------------------------- - -// -// Define integer minimum and maximum as helpers -#ifdef wxLongLong_t -const wxAnyBaseIntType UseIntMin = wxINT64_MIN; -const wxAnyBaseUintType UseIntMax = wxINT64_MAX; -const wxAnyBaseUintType UseUintMax = wxUINT64_MAX; -#else -const wxAnyBaseIntType UseIntMin = LONG_MIN; -const wxAnyBaseUintType UseUintMax = ULONG_MAX; -const wxAnyBaseUintType UseIntMax = LONG_MAX; -#endif - -const double UseIntMinF = static_cast(UseIntMin); -#ifndef __VISUALC6__ -const double UseIntMaxF = static_cast(UseIntMax); -const double UseUintMaxF = static_cast(UseUintMax); -#else -// VC6 doesn't implement conversion from unsigned __int64 to double -const wxAnyBaseIntType UseIntMax0 = static_cast(UseIntMax); -const wxAnyBaseIntType UseUintMax0 = static_cast(UseUintMax); -const double UseIntMaxF = static_cast(UseIntMax0); -const double UseUintMaxF = static_cast(UseUintMax0); -#endif - - -bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const -{ - wxAnyBaseIntType value = GetValue(src); - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) - { -#ifdef wxLongLong_t - wxLongLong ll(value); - wxString s = ll.ToString(); -#else - wxString s = wxString::Format(wxS("%ld"), (long)value); -#endif - wxAnyValueTypeImpl::SetValue(s, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) - { - if ( value < 0 ) - return false; - wxAnyBaseUintType ul = (wxAnyBaseUintType) value; - wxAnyValueTypeImplUint::SetValue(ul, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) - { - double value2 = static_cast(value); - wxAnyValueTypeImplDouble::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) - { - bool value2 = value ? true : false; - wxAnyValueTypeImpl::SetValue(value2, dst); - } - else - return false; - - return true; -} - -bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const -{ - wxAnyBaseUintType value = GetValue(src); - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) - { -#ifdef wxLongLong_t - wxULongLong ull(value); - wxString s = ull.ToString(); -#else - wxString s = wxString::Format(wxS("%lu"), (long)value); -#endif - wxAnyValueTypeImpl::SetValue(s, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) - { - if ( value > UseIntMax ) - return false; - wxAnyBaseIntType l = (wxAnyBaseIntType) value; - wxAnyValueTypeImplInt::SetValue(l, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) - { -#ifndef __VISUALC6__ - double value2 = static_cast(value); -#else - // VC6 doesn't implement conversion from unsigned __int64 to double - wxAnyBaseIntType value0 = static_cast(value); - double value2 = static_cast(value0); -#endif - wxAnyValueTypeImplDouble::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) - { - bool value2 = value ? true : false; - wxAnyValueTypeImpl::SetValue(value2, dst); - } - else - return false; - - return true; -} - -bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const -{ - wxString value = GetValue(src); - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) - { - wxAnyBaseIntType value2; -#ifdef wxLongLong_t - if ( !value.ToLongLong(&value2) ) -#else - if ( !value.ToLong(&value2) ) -#endif - return false; - wxAnyValueTypeImplInt::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) - { - wxAnyBaseUintType value2; -#ifdef wxLongLong_t - if ( !value.ToULongLong(&value2) ) -#else - if ( !value.ToULong(&value2) ) -#endif - return false; - wxAnyValueTypeImplUint::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) - { - double value2; - if ( !value.ToDouble(&value2) ) - return false; - wxAnyValueTypeImplDouble::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) - { - bool value2; - value.MakeLower(); - if ( value == wxS("true") || - value == wxS("yes") || - value == wxS('1') ) - value2 = true; - else if ( value == wxS("false") || - value == wxS("no") || - value == wxS('0') ) - value2 = false; - else - return false; - - wxAnyValueTypeImpl::SetValue(value2, dst); - } - else - return false; - - return true; -} - -bool wxAnyValueTypeImpl::ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const -{ - bool value = GetValue(src); - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) - { - wxAnyBaseIntType value2 = static_cast(value); - wxAnyValueTypeImplInt::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) - { - wxAnyBaseIntType value2 = static_cast(value); - wxAnyValueTypeImplUint::SetValue(value2, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) - { - wxString s; - if ( value ) - s = wxS("true"); - else - s = wxS("false"); - wxAnyValueTypeImpl::SetValue(s, dst); - } - else - return false; - - return true; -} - -bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const -{ - double value = GetValue(src); - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) - { - if ( value < UseIntMinF || value > UseIntMaxF ) - return false; - wxAnyBaseUintType ul = static_cast(value); - wxAnyValueTypeImplUint::SetValue(ul, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) - { - if ( value < 0.0 || value > UseUintMaxF ) - return false; - wxAnyBaseUintType ul = static_cast(value); - wxAnyValueTypeImplUint::SetValue(ul, dst); - } - else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) - { - wxString s = wxString::Format(wxS("%.14g"), value); - wxAnyValueTypeImpl::SetValue(s, dst); - } - else - return false; - - return true; -} - -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt) -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint) -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString) -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble) - -//------------------------------------------------------------------------- -// wxAnyNullValueType implementation -//------------------------------------------------------------------------- - -class wxAnyNullValue -{ -private: - void* m_dummy; -}; - -template <> -class wxAnyValueTypeImpl : public wxAnyValueType -{ - WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) -public: - virtual void DeleteValue(wxAnyValueBuffer& buf) const - { - buf.m_ptr = NULL; // This is important - } - - // Dummy implementations - virtual void CopyBuffer(const wxAnyValueBuffer& src, - wxAnyValueBuffer& dst) const - { - wxUnusedVar(src); - wxUnusedVar(dst); - } - - virtual bool ConvertValue(const wxAnyValueBuffer& src, - wxAnyValueType* dstType, - wxAnyValueBuffer& dst) const - { - wxUnusedVar(src); - wxUnusedVar(dstType); - wxUnusedVar(dst); - return false; - } - -private: -}; - -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) - -wxAnyValueType* wxAnyNullValueType = - wxAnyValueTypeImpl::GetInstance(); - -#endif // wxUSE_ANY +///////////////////////////////////////////////////////////////////////////// +// Name: src/common/any.cpp +// Purpose: wxAny class, container for any type +// Author: Jaakko Salli +// Modified by: +// Created: 07/05/2009 +// RCS-ID: $Id$ +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/any.h" + +#if wxUSE_ANY + +#ifndef WX_PRECOMP + #include "wx/math.h" + #include "wx/crt.h" +#endif + +#include "wx/vector.h" +#include "wx/module.h" + +using namespace wxPrivate; + +//------------------------------------------------------------------------- +// wxAnyValueTypeGlobals +//------------------------------------------------------------------------- + +// +// Helper class to manage wxAnyValueType instances and other +// related global variables. +// +// NB: We really need to have wxAnyValueType instances allocated +// in heap. They are stored as static template member variables, +// and with them we just can't be too careful (eg. not allocating +// them in heap broke the type identification in GCC). +// +class wxAnyValueTypeGlobals +{ +public: + wxAnyValueTypeGlobals() + { + } + ~wxAnyValueTypeGlobals() + { + for ( size_t i=0; i m_valueTypes; +}; + +static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL; + +// +// This class is to make sure that wxAnyValueType instances +// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals +// because wxModule itself is instantiated too late. +// +class wxAnyValueTypeGlobalsManager : public wxModule +{ + DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager) +public: + wxAnyValueTypeGlobalsManager() : wxModule() { } + virtual ~wxAnyValueTypeGlobalsManager() { } + + virtual bool OnInit() + { + return true; + } + virtual void OnExit() + { + delete g_wxAnyValueTypeGlobals; + g_wxAnyValueTypeGlobals = NULL; + } +private: +}; + +IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule) + + +//------------------------------------------------------------------------- +// wxAnyValueType +//------------------------------------------------------------------------- + +wxAnyValueType::wxAnyValueType() +{ + if ( !g_wxAnyValueTypeGlobals ) + g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals(); + + g_wxAnyValueTypeGlobals->RegisterValueType(this); +} + +//------------------------------------------------------------------------- +// wxAny +//------------------------------------------------------------------------- + +void wxAny::AssignAny(const wxAny &any) +{ + if ( !any.m_type->IsSameType(m_type) ) + { + m_type->DeleteValue(m_buffer); + m_type = any.m_type; + } + m_type->CopyBuffer(any.m_buffer, m_buffer); +} + +//------------------------------------------------------------------------- +// Dynamic conversion member functions +//------------------------------------------------------------------------- + +// +// Define integer minimum and maximum as helpers +#ifdef wxLongLong_t +const wxAnyBaseIntType UseIntMin = wxINT64_MIN; +const wxAnyBaseUintType UseIntMax = wxINT64_MAX; +const wxAnyBaseUintType UseUintMax = wxUINT64_MAX; +#else +const wxAnyBaseIntType UseIntMin = LONG_MIN; +const wxAnyBaseUintType UseUintMax = ULONG_MAX; +const wxAnyBaseUintType UseIntMax = LONG_MAX; +#endif + +const double UseIntMinF = static_cast(UseIntMin); +#ifndef __VISUALC6__ +const double UseIntMaxF = static_cast(UseIntMax); +const double UseUintMaxF = static_cast(UseUintMax); +#else +// VC6 doesn't implement conversion from unsigned __int64 to double +const wxAnyBaseIntType UseIntMax0 = static_cast(UseIntMax); +const wxAnyBaseIntType UseUintMax0 = static_cast(UseUintMax); +const double UseIntMaxF = static_cast(UseIntMax0); +const double UseUintMaxF = static_cast(UseUintMax0); +#endif + + +bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const +{ + wxAnyBaseIntType value = GetValue(src); + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) + { +#ifdef wxLongLong_t + wxLongLong ll(value); + wxString s = ll.ToString(); +#else + wxString s = wxString::Format(wxS("%ld"), (long)value); +#endif + wxAnyValueTypeImpl::SetValue(s, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) + { + if ( value < 0 ) + return false; + wxAnyBaseUintType ul = (wxAnyBaseUintType) value; + wxAnyValueTypeImplUint::SetValue(ul, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) + { + double value2 = static_cast(value); + wxAnyValueTypeImplDouble::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) + { + bool value2 = value ? true : false; + wxAnyValueTypeImpl::SetValue(value2, dst); + } + else + return false; + + return true; +} + +bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const +{ + wxAnyBaseUintType value = GetValue(src); + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) + { +#ifdef wxLongLong_t + wxULongLong ull(value); + wxString s = ull.ToString(); +#else + wxString s = wxString::Format(wxS("%lu"), (long)value); +#endif + wxAnyValueTypeImpl::SetValue(s, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) + { + if ( value > UseIntMax ) + return false; + wxAnyBaseIntType l = (wxAnyBaseIntType) value; + wxAnyValueTypeImplInt::SetValue(l, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) + { +#ifndef __VISUALC6__ + double value2 = static_cast(value); +#else + // VC6 doesn't implement conversion from unsigned __int64 to double + wxAnyBaseIntType value0 = static_cast(value); + double value2 = static_cast(value0); +#endif + wxAnyValueTypeImplDouble::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) + { + bool value2 = value ? true : false; + wxAnyValueTypeImpl::SetValue(value2, dst); + } + else + return false; + + return true; +} + +bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const +{ + wxString value = GetValue(src); + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) + { + wxAnyBaseIntType value2; +#ifdef wxLongLong_t + if ( !value.ToLongLong(&value2) ) +#else + if ( !value.ToLong(&value2) ) +#endif + return false; + wxAnyValueTypeImplInt::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) + { + wxAnyBaseUintType value2; +#ifdef wxLongLong_t + if ( !value.ToULongLong(&value2) ) +#else + if ( !value.ToULong(&value2) ) +#endif + return false; + wxAnyValueTypeImplUint::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) ) + { + double value2; + if ( !value.ToDouble(&value2) ) + return false; + wxAnyValueTypeImplDouble::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) ) + { + bool value2; + value.MakeLower(); + if ( value == wxS("true") || + value == wxS("yes") || + value == wxS('1') ) + value2 = true; + else if ( value == wxS("false") || + value == wxS("no") || + value == wxS('0') ) + value2 = false; + else + return false; + + wxAnyValueTypeImpl::SetValue(value2, dst); + } + else + return false; + + return true; +} + +bool wxAnyValueTypeImpl::ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const +{ + bool value = GetValue(src); + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) + { + wxAnyBaseIntType value2 = static_cast(value); + wxAnyValueTypeImplInt::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) + { + wxAnyBaseIntType value2 = static_cast(value); + wxAnyValueTypeImplUint::SetValue(value2, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) + { + wxString s; + if ( value ) + s = wxS("true"); + else + s = wxS("false"); + wxAnyValueTypeImpl::SetValue(s, dst); + } + else + return false; + + return true; +} + +bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const +{ + double value = GetValue(src); + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) ) + { + if ( value < UseIntMinF || value > UseIntMaxF ) + return false; + wxAnyBaseUintType ul = static_cast(value); + wxAnyValueTypeImplUint::SetValue(ul, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) ) + { + if ( value < 0.0 || value > UseUintMaxF ) + return false; + wxAnyBaseUintType ul = static_cast(value); + wxAnyValueTypeImplUint::SetValue(ul, dst); + } + else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) + { + wxString s = wxString::Format(wxS("%.14g"), value); + wxAnyValueTypeImpl::SetValue(s, dst); + } + else + return false; + + return true; +} + +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt) +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint) +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString) +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble) + +//------------------------------------------------------------------------- +// wxAnyNullValueType implementation +//------------------------------------------------------------------------- + +class wxAnyNullValue +{ +private: + void* m_dummy; +}; + +template <> +class wxAnyValueTypeImpl : public wxAnyValueType +{ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl) +public: + virtual void DeleteValue(wxAnyValueBuffer& buf) const + { + buf.m_ptr = NULL; // This is important + } + + // Dummy implementations + virtual void CopyBuffer(const wxAnyValueBuffer& src, + wxAnyValueBuffer& dst) const + { + wxUnusedVar(src); + wxUnusedVar(dst); + } + + virtual bool ConvertValue(const wxAnyValueBuffer& src, + wxAnyValueType* dstType, + wxAnyValueBuffer& dst) const + { + wxUnusedVar(src); + wxUnusedVar(dstType); + wxUnusedVar(dst); + return false; + } + +private: +}; + +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + +wxAnyValueType* wxAnyNullValueType = + wxAnyValueTypeImpl::GetInstance(); + +#endif // wxUSE_ANY diff --git a/tests/any/anytest.cpp b/tests/any/anytest.cpp index 5e6252b49e..74a9d9cd05 100644 --- a/tests/any/anytest.cpp +++ b/tests/any/anytest.cpp @@ -1,433 +1,433 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: tests/any/anytest.cpp -// Purpose: Test the wxAny classes -// Author: Jaakko Salli -// RCS-ID: $Id$ -// Copyright: (c) the wxWidgets team -// Licence: wxWindows licence -/////////////////////////////////////////////////////////////////////////////// - -#include "testprec.h" - -#ifdef __BORLANDC__ -# pragma hdrstop -#endif - -#if wxUSE_ANY - -#include "wx/any.h" -#include "wx/datetime.h" - -#include - -// ---------------------------------------------------------------------------- -// test class -// ---------------------------------------------------------------------------- - -class wxAnyTestCase : public CppUnit::TestCase -{ -public: - wxAnyTestCase(); - -private: - CPPUNIT_TEST_SUITE( wxAnyTestCase ); - CPPUNIT_TEST( Equality ); - CPPUNIT_TEST( As ); - CPPUNIT_TEST( GetAs ); - CPPUNIT_TEST( Null ); - CPPUNIT_TEST( CustomTemplateSpecialization ); - CPPUNIT_TEST_SUITE_END(); - - void Equality(); - void As(); - void GetAs(); - void Null(); - void CustomTemplateSpecialization(); - - wxDateTime m_testDateTime; - - wxAny m_anySignedChar1; - wxAny m_anySignedShort1; - wxAny m_anySignedInt1; - wxAny m_anySignedLong1; - wxAny m_anySignedLongLong1; - wxAny m_anyUnsignedChar1; - wxAny m_anyUnsignedShort1; - wxAny m_anyUnsignedInt1; - wxAny m_anyUnsignedLong1; - wxAny m_anyUnsignedLongLong1; - wxAny m_anyStringString1; - wxAny m_anyCharString1; - wxAny m_anyWcharString1; - wxAny m_anyBool1; - wxAny m_anyFloatDouble1; - wxAny m_anyDoubleDouble1; - wxAny m_anyWxObjectPtr1; - wxAny m_anyVoidPtr1; - wxAny m_anyDateTime1; - - wxAny m_anySignedChar2; - wxAny m_anySignedShort2; - wxAny m_anySignedInt2; - wxAny m_anySignedLong2; - wxAny m_anySignedLongLong2; - wxAny m_anyUnsignedChar2; - wxAny m_anyUnsignedShort2; - wxAny m_anyUnsignedInt2; - wxAny m_anyUnsignedLong2; - wxAny m_anyUnsignedLongLong2; - wxAny m_anyStringString2; - wxAny m_anyCharString2; - wxAny m_anyWcharString2; - wxAny m_anyBool2; - wxAny m_anyFloatDouble2; - wxAny m_anyDoubleDouble2; - wxAny m_anyWxObjectPtr2; - wxAny m_anyVoidPtr2; - wxAny m_anyDateTime2; - - DECLARE_NO_COPY_CLASS(wxAnyTestCase) -}; - -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase ); - -// also include in it's own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" ); - -// Let's use a number with first digit after decimal dot less than 5, -// so that we don't have to worry about whether conversion from float -// to int truncates or rounds. -const double TEST_FLOAT_CONST = 123.456; - -const double FEQ_DELTA = 0.001; - -wxObject* dummyWxObjectPointer = reinterpret_cast(1234); -void* dummyVoidPointer = reinterpret_cast(1234); - - -// -// Test both 'creation' methods -wxAnyTestCase::wxAnyTestCase() - : m_anySignedChar1((signed char)15), - m_anySignedShort1((signed short)15), - m_anySignedInt1((signed int)15), - m_anySignedLong1((signed long)15), -#ifdef wxLongLong_t - m_anySignedLongLong1((wxLongLong_t)15), -#endif - m_anyUnsignedChar1((unsigned char)15), - m_anyUnsignedShort1((unsigned short)15), - m_anyUnsignedInt1((unsigned int)15), - m_anyUnsignedLong1((unsigned long)15), -#ifdef wxLongLong_t - m_anyUnsignedLongLong1((wxULongLong_t)15), -#endif - m_anyStringString1(wxString("abc")), - m_anyCharString1("abc"), - m_anyWcharString1(L"abc"), - m_anyBool1(true), - m_anyFloatDouble1((float)TEST_FLOAT_CONST), - m_anyDoubleDouble1((double)TEST_FLOAT_CONST), - m_anyWxObjectPtr1(dummyWxObjectPointer), - m_anyVoidPtr1(dummyVoidPointer), - m_anyDateTime1(wxDateTime::Now()) -{ - m_testDateTime = wxDateTime::Now(); - m_anySignedChar2 = (signed char)15; - m_anySignedShort2 = (signed short)15; - m_anySignedInt2 = (signed int)15; - m_anySignedLong2 = (signed long)15; -#ifdef wxLongLong_t - m_anySignedLongLong2 = (wxLongLong_t)15; -#endif - m_anyUnsignedChar2 = (unsigned char)15; - m_anyUnsignedShort2 = (unsigned short)15; - m_anyUnsignedInt2 = (unsigned int)15; - m_anyUnsignedLong2 = (unsigned long)15; -#ifdef wxLongLong_t - m_anyUnsignedLongLong2 = (wxULongLong_t)15; -#endif - m_anyStringString2 = wxString("abc"); - m_anyCharString2 = "abc"; - m_anyWcharString2 = L"abc"; - m_anyBool2 = true; - m_anyFloatDouble2 = (float)TEST_FLOAT_CONST; - m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST; - m_anyDateTime2 = m_testDateTime; - m_anyWxObjectPtr2 = dummyWxObjectPointer; - m_anyVoidPtr2 = dummyVoidPointer; -} - -void wxAnyTestCase::Equality() -{ - // - // Currently this should work - CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L); - CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L); - CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL); - CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL); - CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc")); - CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC")); - CPPUNIT_ASSERT(m_anyStringString1 == "abc"); - CPPUNIT_ASSERT(m_anyStringString1 != "ABC"); - CPPUNIT_ASSERT(m_anyStringString1 == L"abc"); - CPPUNIT_ASSERT(m_anyStringString1 != L"ABC"); - CPPUNIT_ASSERT(m_anyBool1 == true); - CPPUNIT_ASSERT(m_anyBool1 != false); - CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double), - wxANY_AS(m_anyDoubleDouble1, double), - FEQ_DELTA); - CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double), - TEST_FLOAT_CONST, - FEQ_DELTA); - CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr1, wxObject*) - == dummyWxObjectPointer); - CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr1, void*) == dummyVoidPointer); - - CPPUNIT_ASSERT(m_anySignedLong2 == 15); - CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc")); - CPPUNIT_ASSERT(m_anyStringString2 == "abc"); - CPPUNIT_ASSERT(m_anyStringString2 == L"abc"); - CPPUNIT_ASSERT(m_anyBool2 == true); - CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double), - wxANY_AS(m_anyDoubleDouble2, double), - FEQ_DELTA); - CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double), - TEST_FLOAT_CONST, - FEQ_DELTA); - CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr2, wxObject*) - == dummyWxObjectPointer); - CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr2, void*) == dummyVoidPointer); -} - -void wxAnyTestCase::As() -{ - // - // Test getting C++ data from wxAny without dynamic conversion - signed char a = wxANY_AS(m_anySignedChar1, signed char); - CPPUNIT_ASSERT(a == (signed int)15); - signed short b = wxANY_AS(m_anySignedShort1, signed short); - CPPUNIT_ASSERT(b == (signed int)15); - signed int c = wxANY_AS(m_anySignedInt1, signed int); - CPPUNIT_ASSERT(c == (signed int)15); - signed long d = wxANY_AS(m_anySignedLong1, signed long); - CPPUNIT_ASSERT(d == (signed int)15); -#ifdef wxLongLong_t - wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t); - CPPUNIT_ASSERT(e == (signed int)15); -#endif - unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char); - CPPUNIT_ASSERT(f == (unsigned int)15); - unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short); - CPPUNIT_ASSERT(g == (unsigned int)15); - unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int); - CPPUNIT_ASSERT(h == (unsigned int)15); - unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long); - CPPUNIT_ASSERT(i == (unsigned int)15); -#ifdef wxLongLong_t - wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t); - CPPUNIT_ASSERT(j == (unsigned int)15); -#endif - wxString k = wxANY_AS(m_anyStringString1, wxString); - CPPUNIT_ASSERT(k == "abc"); - wxString l = wxANY_AS(m_anyCharString1, wxString); - CPPUNIT_ASSERT(l == "abc"); - wxString m = wxANY_AS(m_anyWcharString1, wxString); - CPPUNIT_ASSERT(m == "abc"); - bool n = wxANY_AS(m_anyBool1, bool); - CPPUNIT_ASSERT(n); - float o = wxANY_AS(m_anyFloatDouble1, float); - CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA); - double p = wxANY_AS(m_anyDoubleDouble1, double); - CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA); - wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime); - CPPUNIT_ASSERT(q == m_testDateTime); - wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*); - CPPUNIT_ASSERT(r == dummyWxObjectPointer); - void* s = wxANY_AS(m_anyVoidPtr1, void*); - CPPUNIT_ASSERT(s == dummyVoidPointer); -} - -void wxAnyTestCase::Null() -{ - wxAny a; - CPPUNIT_ASSERT(a.IsNull()); - a = -127; - CPPUNIT_ASSERT(a == -127); - a.MakeNull(); - CPPUNIT_ASSERT(a.IsNull()); -} - -void wxAnyTestCase::GetAs() -{ - // - // Test dynamic conversion - bool res; - long l = 0; - unsigned long ul = 0; - wxString s; - // Let's test against float instead of double, since the former - // is not the native underlying type the code converts to, but - // should still work, all the same. - float f = 0.0; - bool b = false; - - // Conversions from signed long type - res = m_anySignedLong1.GetAs(&ul); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_EQUAL(ul, static_cast(15)); - res = m_anySignedLong1.GetAs(&s); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(s == "15"); - res = m_anySignedLong1.GetAs(&f); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); - res = m_anySignedLong1.GetAs(&b); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(b == true); - - // Conversions from unsigned long type - res = m_anyUnsignedLong1.GetAs(&l); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(l == static_cast(15)); - res = m_anyUnsignedLong1.GetAs(&s); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(s == "15"); - res = m_anyUnsignedLong1.GetAs(&f); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); - res = m_anyUnsignedLong1.GetAs(&b); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(b == true); - - // Conversions from default "abc" string to other types - // should not work. - CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l)); - CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul)); - CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f)); - CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b)); - - // Let's test some other conversions from string that should work. - wxAny anyString; - - anyString = "15"; - res = anyString.GetAs(&l); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(l == static_cast(15)); - res = anyString.GetAs(&ul); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_EQUAL(ul, static_cast(15)); - res = anyString.GetAs(&f); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); - anyString = "TRUE"; - res = anyString.GetAs(&b); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(b == true); - anyString = "0"; - res = anyString.GetAs(&b); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(b == false); - - // Conversions from bool type - res = m_anyBool1.GetAs(&l); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(l == static_cast(1)); - res = m_anyBool1.GetAs(&ul); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_EQUAL(ul, static_cast(1)); - res = m_anyBool1.GetAs(&s); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(s == "true"); - CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f)); - - // Conversions from floating point type - res = m_anyDoubleDouble1.GetAs(&l); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT(l == static_cast(123)); - res = m_anyDoubleDouble1.GetAs(&ul); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_EQUAL(ul, static_cast(123)); - res = m_anyDoubleDouble1.GetAs(&s); - CPPUNIT_ASSERT(res); - double d2; - res = s.ToDouble(&d2); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA); -} - -// -// Test user data type specialization of wxAnyValueTypeImpl -// - -class MyClass -{ -public: - MyClass( int someValue = 32768 ) - { - m_someValue = someValue; - } - - wxString ToString() - { - return wxString::Format("%i", m_someValue); - } - -private: - int m_someValue; -}; - - -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 - { - MyClass value = GetValue(src); - - if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) - { - wxString s = value.ToString(); - wxAnyValueTypeImpl::SetValue(s, dst); - } - else - return false; - - return true; - } -}; - -// -// Following must be placed somewhere in your source code -WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) - -void wxAnyTestCase::CustomTemplateSpecialization() -{ - // Do only a minimal CheckType() test, as dynamic type conversion already - // uses it a lot. - bool res; - MyClass myObject; - wxAny any = myObject; - - CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) ); - MyClass myObject2 = wxANY_AS(any, MyClass); - wxUnusedVar(myObject2); - - wxString str; - res = any.GetAs(&str); - CPPUNIT_ASSERT(res); - CPPUNIT_ASSERT_EQUAL(str, myObject.ToString()); -} - -#endif // wxUSE_ANY - +/////////////////////////////////////////////////////////////////////////////// +// Name: tests/any/anytest.cpp +// Purpose: Test the wxAny classes +// Author: Jaakko Salli +// RCS-ID: $Id$ +// Copyright: (c) the wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "testprec.h" + +#ifdef __BORLANDC__ +# pragma hdrstop +#endif + +#if wxUSE_ANY + +#include "wx/any.h" +#include "wx/datetime.h" + +#include + +// ---------------------------------------------------------------------------- +// test class +// ---------------------------------------------------------------------------- + +class wxAnyTestCase : public CppUnit::TestCase +{ +public: + wxAnyTestCase(); + +private: + CPPUNIT_TEST_SUITE( wxAnyTestCase ); + CPPUNIT_TEST( Equality ); + CPPUNIT_TEST( As ); + CPPUNIT_TEST( GetAs ); + CPPUNIT_TEST( Null ); + CPPUNIT_TEST( CustomTemplateSpecialization ); + CPPUNIT_TEST_SUITE_END(); + + void Equality(); + void As(); + void GetAs(); + void Null(); + void CustomTemplateSpecialization(); + + wxDateTime m_testDateTime; + + wxAny m_anySignedChar1; + wxAny m_anySignedShort1; + wxAny m_anySignedInt1; + wxAny m_anySignedLong1; + wxAny m_anySignedLongLong1; + wxAny m_anyUnsignedChar1; + wxAny m_anyUnsignedShort1; + wxAny m_anyUnsignedInt1; + wxAny m_anyUnsignedLong1; + wxAny m_anyUnsignedLongLong1; + wxAny m_anyStringString1; + wxAny m_anyCharString1; + wxAny m_anyWcharString1; + wxAny m_anyBool1; + wxAny m_anyFloatDouble1; + wxAny m_anyDoubleDouble1; + wxAny m_anyWxObjectPtr1; + wxAny m_anyVoidPtr1; + wxAny m_anyDateTime1; + + wxAny m_anySignedChar2; + wxAny m_anySignedShort2; + wxAny m_anySignedInt2; + wxAny m_anySignedLong2; + wxAny m_anySignedLongLong2; + wxAny m_anyUnsignedChar2; + wxAny m_anyUnsignedShort2; + wxAny m_anyUnsignedInt2; + wxAny m_anyUnsignedLong2; + wxAny m_anyUnsignedLongLong2; + wxAny m_anyStringString2; + wxAny m_anyCharString2; + wxAny m_anyWcharString2; + wxAny m_anyBool2; + wxAny m_anyFloatDouble2; + wxAny m_anyDoubleDouble2; + wxAny m_anyWxObjectPtr2; + wxAny m_anyVoidPtr2; + wxAny m_anyDateTime2; + + DECLARE_NO_COPY_CLASS(wxAnyTestCase) +}; + +// register in the unnamed registry so that these tests are run by default +CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase ); + +// also include in it's own registry so that these tests can be run alone +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" ); + +// Let's use a number with first digit after decimal dot less than 5, +// so that we don't have to worry about whether conversion from float +// to int truncates or rounds. +const double TEST_FLOAT_CONST = 123.456; + +const double FEQ_DELTA = 0.001; + +wxObject* dummyWxObjectPointer = reinterpret_cast(1234); +void* dummyVoidPointer = reinterpret_cast(1234); + + +// +// Test both 'creation' methods +wxAnyTestCase::wxAnyTestCase() + : m_anySignedChar1((signed char)15), + m_anySignedShort1((signed short)15), + m_anySignedInt1((signed int)15), + m_anySignedLong1((signed long)15), +#ifdef wxLongLong_t + m_anySignedLongLong1((wxLongLong_t)15), +#endif + m_anyUnsignedChar1((unsigned char)15), + m_anyUnsignedShort1((unsigned short)15), + m_anyUnsignedInt1((unsigned int)15), + m_anyUnsignedLong1((unsigned long)15), +#ifdef wxLongLong_t + m_anyUnsignedLongLong1((wxULongLong_t)15), +#endif + m_anyStringString1(wxString("abc")), + m_anyCharString1("abc"), + m_anyWcharString1(L"abc"), + m_anyBool1(true), + m_anyFloatDouble1((float)TEST_FLOAT_CONST), + m_anyDoubleDouble1((double)TEST_FLOAT_CONST), + m_anyWxObjectPtr1(dummyWxObjectPointer), + m_anyVoidPtr1(dummyVoidPointer), + m_anyDateTime1(wxDateTime::Now()) +{ + m_testDateTime = wxDateTime::Now(); + m_anySignedChar2 = (signed char)15; + m_anySignedShort2 = (signed short)15; + m_anySignedInt2 = (signed int)15; + m_anySignedLong2 = (signed long)15; +#ifdef wxLongLong_t + m_anySignedLongLong2 = (wxLongLong_t)15; +#endif + m_anyUnsignedChar2 = (unsigned char)15; + m_anyUnsignedShort2 = (unsigned short)15; + m_anyUnsignedInt2 = (unsigned int)15; + m_anyUnsignedLong2 = (unsigned long)15; +#ifdef wxLongLong_t + m_anyUnsignedLongLong2 = (wxULongLong_t)15; +#endif + m_anyStringString2 = wxString("abc"); + m_anyCharString2 = "abc"; + m_anyWcharString2 = L"abc"; + m_anyBool2 = true; + m_anyFloatDouble2 = (float)TEST_FLOAT_CONST; + m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST; + m_anyDateTime2 = m_testDateTime; + m_anyWxObjectPtr2 = dummyWxObjectPointer; + m_anyVoidPtr2 = dummyVoidPointer; +} + +void wxAnyTestCase::Equality() +{ + // + // Currently this should work + CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L); + CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L); + CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL); + CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL); + CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc")); + CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC")); + CPPUNIT_ASSERT(m_anyStringString1 == "abc"); + CPPUNIT_ASSERT(m_anyStringString1 != "ABC"); + CPPUNIT_ASSERT(m_anyStringString1 == L"abc"); + CPPUNIT_ASSERT(m_anyStringString1 != L"ABC"); + CPPUNIT_ASSERT(m_anyBool1 == true); + CPPUNIT_ASSERT(m_anyBool1 != false); + CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double), + wxANY_AS(m_anyDoubleDouble1, double), + FEQ_DELTA); + CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double), + TEST_FLOAT_CONST, + FEQ_DELTA); + CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr1, wxObject*) + == dummyWxObjectPointer); + CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr1, void*) == dummyVoidPointer); + + CPPUNIT_ASSERT(m_anySignedLong2 == 15); + CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc")); + CPPUNIT_ASSERT(m_anyStringString2 == "abc"); + CPPUNIT_ASSERT(m_anyStringString2 == L"abc"); + CPPUNIT_ASSERT(m_anyBool2 == true); + CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double), + wxANY_AS(m_anyDoubleDouble2, double), + FEQ_DELTA); + CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double), + TEST_FLOAT_CONST, + FEQ_DELTA); + CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr2, wxObject*) + == dummyWxObjectPointer); + CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr2, void*) == dummyVoidPointer); +} + +void wxAnyTestCase::As() +{ + // + // Test getting C++ data from wxAny without dynamic conversion + signed char a = wxANY_AS(m_anySignedChar1, signed char); + CPPUNIT_ASSERT(a == (signed int)15); + signed short b = wxANY_AS(m_anySignedShort1, signed short); + CPPUNIT_ASSERT(b == (signed int)15); + signed int c = wxANY_AS(m_anySignedInt1, signed int); + CPPUNIT_ASSERT(c == (signed int)15); + signed long d = wxANY_AS(m_anySignedLong1, signed long); + CPPUNIT_ASSERT(d == (signed int)15); +#ifdef wxLongLong_t + wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t); + CPPUNIT_ASSERT(e == (signed int)15); +#endif + unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char); + CPPUNIT_ASSERT(f == (unsigned int)15); + unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short); + CPPUNIT_ASSERT(g == (unsigned int)15); + unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int); + CPPUNIT_ASSERT(h == (unsigned int)15); + unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long); + CPPUNIT_ASSERT(i == (unsigned int)15); +#ifdef wxLongLong_t + wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t); + CPPUNIT_ASSERT(j == (unsigned int)15); +#endif + wxString k = wxANY_AS(m_anyStringString1, wxString); + CPPUNIT_ASSERT(k == "abc"); + wxString l = wxANY_AS(m_anyCharString1, wxString); + CPPUNIT_ASSERT(l == "abc"); + wxString m = wxANY_AS(m_anyWcharString1, wxString); + CPPUNIT_ASSERT(m == "abc"); + bool n = wxANY_AS(m_anyBool1, bool); + CPPUNIT_ASSERT(n); + float o = wxANY_AS(m_anyFloatDouble1, float); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA); + double p = wxANY_AS(m_anyDoubleDouble1, double); + CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA); + wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime); + CPPUNIT_ASSERT(q == m_testDateTime); + wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*); + CPPUNIT_ASSERT(r == dummyWxObjectPointer); + void* s = wxANY_AS(m_anyVoidPtr1, void*); + CPPUNIT_ASSERT(s == dummyVoidPointer); +} + +void wxAnyTestCase::Null() +{ + wxAny a; + CPPUNIT_ASSERT(a.IsNull()); + a = -127; + CPPUNIT_ASSERT(a == -127); + a.MakeNull(); + CPPUNIT_ASSERT(a.IsNull()); +} + +void wxAnyTestCase::GetAs() +{ + // + // Test dynamic conversion + bool res; + long l = 0; + unsigned long ul = 0; + wxString s; + // Let's test against float instead of double, since the former + // is not the native underlying type the code converts to, but + // should still work, all the same. + float f = 0.0; + bool b = false; + + // Conversions from signed long type + res = m_anySignedLong1.GetAs(&ul); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_EQUAL(ul, static_cast(15)); + res = m_anySignedLong1.GetAs(&s); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(s == "15"); + res = m_anySignedLong1.GetAs(&f); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); + res = m_anySignedLong1.GetAs(&b); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(b == true); + + // Conversions from unsigned long type + res = m_anyUnsignedLong1.GetAs(&l); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(l == static_cast(15)); + res = m_anyUnsignedLong1.GetAs(&s); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(s == "15"); + res = m_anyUnsignedLong1.GetAs(&f); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); + res = m_anyUnsignedLong1.GetAs(&b); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(b == true); + + // Conversions from default "abc" string to other types + // should not work. + CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l)); + CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul)); + CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f)); + CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b)); + + // Let's test some other conversions from string that should work. + wxAny anyString; + + anyString = "15"; + res = anyString.GetAs(&l); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(l == static_cast(15)); + res = anyString.GetAs(&ul); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_EQUAL(ul, static_cast(15)); + res = anyString.GetAs(&f); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA); + anyString = "TRUE"; + res = anyString.GetAs(&b); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(b == true); + anyString = "0"; + res = anyString.GetAs(&b); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(b == false); + + // Conversions from bool type + res = m_anyBool1.GetAs(&l); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(l == static_cast(1)); + res = m_anyBool1.GetAs(&ul); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_EQUAL(ul, static_cast(1)); + res = m_anyBool1.GetAs(&s); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(s == "true"); + CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f)); + + // Conversions from floating point type + res = m_anyDoubleDouble1.GetAs(&l); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT(l == static_cast(123)); + res = m_anyDoubleDouble1.GetAs(&ul); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_EQUAL(ul, static_cast(123)); + res = m_anyDoubleDouble1.GetAs(&s); + CPPUNIT_ASSERT(res); + double d2; + res = s.ToDouble(&d2); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA); +} + +// +// Test user data type specialization of wxAnyValueTypeImpl +// + +class MyClass +{ +public: + MyClass( int someValue = 32768 ) + { + m_someValue = someValue; + } + + wxString ToString() + { + return wxString::Format("%i", m_someValue); + } + +private: + int m_someValue; +}; + + +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 + { + MyClass value = GetValue(src); + + if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) ) + { + wxString s = value.ToString(); + wxAnyValueTypeImpl::SetValue(s, dst); + } + else + return false; + + return true; + } +}; + +// +// Following must be placed somewhere in your source code +WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + +void wxAnyTestCase::CustomTemplateSpecialization() +{ + // Do only a minimal CheckType() test, as dynamic type conversion already + // uses it a lot. + bool res; + MyClass myObject; + wxAny any = myObject; + + CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) ); + MyClass myObject2 = wxANY_AS(any, MyClass); + wxUnusedVar(myObject2); + + wxString str; + res = any.GetAs(&str); + CPPUNIT_ASSERT(res); + CPPUNIT_ASSERT_EQUAL(str, myObject.ToString()); +} + +#endif // wxUSE_ANY +