]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/any.h
TODO done
[wxWidgets.git] / include / wx / any.h
index 102f75926e1597afc070560e5b1d6027dfd604dd..2e9a9af4e5c524d00256b4e2eba19b396e41a17b 100644 (file)
@@ -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.
@@ -43,9 +44,6 @@ union wxAnyValueBuffer
     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<>)
@@ -53,6 +51,7 @@ typedef void (*wxAnyClassInfo)();
 //
 class WXDLLIMPEXP_BASE wxAnyValueType
 {
+    WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType)
 public:
     /**
         Default constructor.
@@ -66,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.
     */
@@ -83,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;
@@ -120,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 \
     { \
@@ -189,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;
     }
 };
 
@@ -259,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);
     }
 
@@ -332,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); \
     } \
 };
 
@@ -476,6 +475,123 @@ 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)
+
+
+#if wxUSE_VARIANT
+
+class WXDLLIMPEXP_FWD_BASE wxAnyToVariantRegistration;
+
+// Because of header inter-dependencies, cannot include this earlier
+#include "wx/variant.h"
+
+//
+// wxVariantData* data type implementation. For cases when appropriate
+// wxAny<->wxVariant conversion code is missing.
+//
+
+class WXDLLIMPEXP_BASE wxAnyValueTypeImplVariantData :
+    public wxAnyValueTypeImplBase<wxVariantData*>
+{
+    WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
+public:
+    wxAnyValueTypeImplVariantData() :
+        wxAnyValueTypeImplBase<wxVariantData*>() { }
+    virtual ~wxAnyValueTypeImplVariantData() { }
+
+    virtual void DeleteValue(wxAnyValueBuffer& buf) const
+    {
+        wxVariantData* data = static_cast<wxVariantData*>(buf.m_ptr);
+        if ( data )
+            data->DecRef();
+    }
+
+    virtual void CopyBuffer(const wxAnyValueBuffer& src,
+                            wxAnyValueBuffer& dst) const
+    {
+        wxVariantData* data = static_cast<wxVariantData*>(src.m_ptr);
+        if ( data )
+            data->IncRef();
+        dst.m_ptr = data;
+    }
+
+    static void SetValue(wxVariantData* value,
+                         wxAnyValueBuffer& buf)
+    {
+        value->IncRef();
+        buf.m_ptr = value;
+    }
+
+    static wxVariantData* GetValue(const wxAnyValueBuffer& buf)
+    {
+        return static_cast<wxVariantData*>(buf.m_ptr);
+    }
+
+    virtual bool ConvertValue(const wxAnyValueBuffer& src,
+                              wxAnyValueType* dstType,
+                              wxAnyValueBuffer& dst) const
+    {
+        wxUnusedVar(src);
+        wxUnusedVar(dstType);
+        wxUnusedVar(dst);
+        return false;
+    }
+};
+
+template<>
+class wxAnyValueTypeImpl<wxVariantData*> :
+    public wxAnyValueTypeImplVariantData
+{
+public:
+    wxAnyValueTypeImpl() : wxAnyValueTypeImplVariantData() { }
+    virtual ~wxAnyValueTypeImpl() { }
+};
+
+#endif // wxUSE_VARIANT
+
 #ifdef __VISUALC6__
     // Re-enable useless VC6 warnings
     #pragma warning (pop)
@@ -517,6 +633,22 @@ bool operator==(TUS value) const \
 }
 
 
+#if wxUSE_VARIANT
+
+// Note that the following functions are implemented outside wxAny class
+// so that it can reside entirely in header and lack the export declaration.
+
+// Helper function used to associate wxAnyValueType with a wxVariantData.
+extern WXDLLIMPEXP_BASE void
+wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg);
+
+// This function performs main wxAny to wxVariant conversion duties.
+extern WXDLLIMPEXP_BASE bool
+wxConvertAnyToVariant(const wxAny& any, wxVariant* variant);
+
+#endif // wxUSE_VARIANT
+
+
 //
 // 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.
@@ -547,11 +679,19 @@ public:
     /**
         Various constructors.
     */
+    template<typename T>
+    wxAny(const T& value)
+    {
+        m_type = wxAnyValueTypeImpl<T>::sm_instance;
+        wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
+    }
+
     wxAny(const char* value)
     {
         m_type = wxAnyNullValueType;
         Assign(wxString(value));
     }
+
     wxAny(const wchar_t* value)
     {
         m_type = wxAnyNullValueType;
@@ -564,12 +704,14 @@ public:
         AssignAny(any);
     }
 
-    template<typename T>
-    wxAny(const T& value)
+#if wxUSE_VARIANT
+    wxAny(const wxVariant& variant)
     {
-        m_type = wxAnyValueTypeImpl<T>::sm_instance;
-        wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
+        m_type = wxAnyNullValueType;
+        AssignVariant(variant);
     }
+#endif
+
     //@}
 
     /**
@@ -623,12 +765,6 @@ public:
     /**
         Assignment operators.
     */
-    wxAny& operator=(const wxAny &any)
-    {
-        AssignAny(any);
-        return *this;
-    }
-
     template<typename T>
     wxAny& operator=(const T &value)
     {
@@ -638,6 +774,21 @@ public:
         return *this;
     }
 
+    wxAny& operator=(const wxAny &any)
+    {
+        if (this != &any)
+            AssignAny(any);
+        return *this;
+    }
+
+#if wxUSE_VARIANT
+    wxAny& operator=(const wxVariant &variant)
+    {
+        AssignVariant(variant);
+        return *this;
+    }
+#endif
+
     wxAny& operator=(const char* value)
         { Assign(wxString(value)); return *this; }
     wxAny& operator=(const wchar_t* value)
@@ -720,7 +871,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,17 +914,52 @@ public:
         return true;
     }
 
+#if wxUSE_VARIANT
+    // GetAs() wxVariant specialization
+    bool GetAs(wxVariant* value) const
+    {
+        return wxConvertAnyToVariant(*this, value);
+    }
+#endif
+
 private:
     // Assignment functions
     void AssignAny(const wxAny& any)
     {
-        if ( !any.m_type->IsSameType(m_type) )
+        // 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);
+    }
+
+#if wxUSE_VARIANT
+    void AssignVariant(const wxVariant& variant)
+    {
+        wxVariantData* data = variant.GetData();
+
+        if ( data && data->GetAsAny(this) )
+            return;
+
+        m_type->DeleteValue(m_buffer);
+
+        if ( variant.IsNull() )
+        {
+            // Init as Null
+            m_type = wxAnyNullValueType;
+        }
+        else
         {
-            m_type->DeleteValue(m_buffer);
-            m_type = any.m_type;
+            // If everything else fails, wrap the whole wxVariantData
+            m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance;
+            wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
         }
-        m_type->CopyBuffer(any.m_buffer, m_buffer);
     }
+#endif
 
     template<typename T>
     void Assign(const T &value)