X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/62d7be206678146e889a76e30537c74c0e2c0ecc..bc5c09a3aa3662137da2d781c0b101a598d2650d:/include/wx/any.h diff --git a/include/wx/any.h b/include/wx/any.h index 46d2ec61d9..4ddd7b4c1c 100644 --- a/include/wx/any.h +++ b/include/wx/any.h @@ -19,6 +19,7 @@ #include "wx/string.h" #include "wx/meta/movable.h" #include "wx/meta/if.h" +#include "wx/typeinfo.h" // Size of the wxAny value buffer. @@ -29,19 +30,20 @@ enum union wxAnyValueBuffer { + union Alignment + { + #if wxHAS_INT64 + wxInt64 m_int64; + #endif + long double m_longDouble; + void ( *m_funcPtr )(void); + void ( wxAnyValueBuffer::*m_mFuncPtr )(void); + } m_alignment; + void* m_ptr; -#if wxHAS_INT64 - wxInt64 m_int64; -#endif - double m_double; - void ( *m_funcPtr )(void); - void ( wxAnyValueBuffer::*m_mFuncPtr )(void); 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<>) @@ -49,6 +51,7 @@ typedef void (*wxAnyClassInfo)(); // class WXDLLIMPEXP_BASE wxAnyValueType { + WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType) public: /** Default constructor. @@ -62,11 +65,6 @@ public: { } - /** - This function is used for internal type matching. - */ - virtual wxAnyClassInfo GetClassInfo() const = 0; - /** This function is used for internal type matching. */ @@ -79,9 +77,14 @@ public: 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. + Implement this for buffer-to-buffer copy. + + @param src + This is the source data buffer. + + @param dst + This is the destination data buffer that is in either + uninitialized or freed state. */ virtual void CopyBuffer(const wxAnyValueBuffer& src, wxAnyValueBuffer& dst) const = 0; @@ -116,28 +119,22 @@ private: #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \ wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr) - //valueTypePtr->CheckType(static_cast<T*>(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). + Even though C++ RTTI would be fully available to use, we'd have to to + facilitate sub-type system which allows, for instance, wxAny with + signed short '15' to be treated equal to wxAny with signed long long '15'. + Having sm_instance is important here. */ #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ friend class wxAny; \ + WX_DECLARE_TYPEINFO_INLINE(CLS) \ public: \ - static void sm_classInfo() {} \ - \ - virtual wxAnyClassInfo GetClassInfo() const \ - { \ - return sm_classInfo; \ - } \ static bool IsSameClass(const wxAnyValueType* otherType) \ { \ - return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \ + return wxTypeId(*sm_instance) == wxTypeId(*otherType); \ } \ virtual bool IsSameType(const wxAnyValueType* otherType) const \ { \ @@ -185,7 +182,11 @@ public: static const T& GetValue(const wxAnyValueBuffer& buf) { - return *(reinterpret_cast<const T*>(&buf.m_buffer[0])); + // Breaking this code into two lines should supress + // GCC's 'type-punned pointer will break strict-aliasing rules' + // warning. + const T* value = reinterpret_cast<const T*>(&buf.m_buffer[0]); + return *value; } }; @@ -255,13 +256,11 @@ public: 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); } @@ -328,13 +327,17 @@ public: \ virtual ~wxAnyValueTypeImpl() { } \ static void SetValue(const T& value, wxAnyValueBuffer& buf) \ { \ - *(reinterpret_cast<UseDataType*>(&buf.m_buffer[0])) = \ - static_cast<UseDataType>(value); \ + void* voidPtr = reinterpret_cast<void*>(&buf.m_buffer[0]); \ + UseDataType* dptr = reinterpret_cast<UseDataType*>(voidPtr); \ + *dptr = static_cast<UseDataType>(value); \ } \ static T GetValue(const wxAnyValueBuffer& buf) \ { \ - return static_cast<T>( \ - *(reinterpret_cast<const UseDataType*>(&buf.m_buffer[0]))); \ + const void* voidPtr = \ + reinterpret_cast<const void*>(&buf.m_buffer[0]); \ + const UseDataType* sptr = \ + reinterpret_cast<const UseDataType*>(voidPtr); \ + return static_cast<T>(*sptr); \ } \ }; @@ -472,6 +475,53 @@ WX_ANY_DEFINE_SUB_TYPE(float, Double) WX_ANY_DEFINE_SUB_TYPE(double, Double) +// +// Defines a dummy wxAnyValueTypeImpl<> with given export +// declaration. This is needed if a class is used with +// wxAny in both user shared library and application. +// +#define wxDECLARE_ANY_TYPE(CLS, DECL) \ +template<> \ +class DECL wxAnyValueTypeImpl<CLS> : \ + public wxAnyValueTypeImplBase<CLS> \ +{ \ + WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<CLS>) \ +public: \ + wxAnyValueTypeImpl() : \ + wxAnyValueTypeImplBase<CLS>() { } \ + virtual ~wxAnyValueTypeImpl() { } \ + \ + virtual bool ConvertValue(const wxAnyValueBuffer& src, \ + wxAnyValueType* dstType, \ + wxAnyValueBuffer& dst) const \ + { \ + wxUnusedVar(src); \ + wxUnusedVar(dstType); \ + wxUnusedVar(dst); \ + return false; \ + } \ +}; + + +// Make sure some of wx's own types get the right wxAnyValueType export +// (this is needed only for types that are referred to from wxBase. +// currently we may not use any of these types from there, but let's +// use the macro on at least one to make sure it compiles since we can't +// really test it properly in unittests since a separate DLL would +// be needed). +#if wxUSE_DATETIME + #include "wx/datetime.h" + wxDECLARE_ANY_TYPE(wxDateTime, WXDLLIMPEXP_BASE) +#endif + +//#include "wx/object.h" +//wxDECLARE_ANY_TYPE(wxObject*, WXDLLIMPEXP_BASE) + +//#include "wx/arrstr.h" +//wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE) + + + #ifdef __VISUALC6__ // Re-enable useless VC6 warnings #pragma warning (pop) @@ -621,7 +671,8 @@ public: */ wxAny& operator=(const wxAny &any) { - AssignAny(any); + if (this != &any) + AssignAny(any); return *this; } @@ -716,7 +767,7 @@ public: in release ones. @remarks This template function does not work on some older compilers - (such as Visual C++ 6.0). For full compiler ccompatibility + (such as Visual C++ 6.0). For full compiler compatibility please use wxANY_AS(any, T) macro instead. */ // FIXME-VC6: remove this hack when VC6 is no longer supported @@ -763,12 +814,15 @@ private: // Assignment functions void 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); + // Must delete value - CopyBuffer() never does that + m_type->DeleteValue(m_buffer); + + wxAnyValueType* newType = any.m_type; + + if ( !newType->IsSameType(m_type) ) + m_type = newType; + + newType->CopyBuffer(any.m_buffer, m_buffer); } template<typename T>