From c8058a09e5147657342e02e50cf471d7b751abc1 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Fri, 19 Oct 2007 15:01:54 +0000
Subject: [PATCH] Added wxVariantData::Clone and wxVariant::Unshare

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49246 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt          |  6 +++++
 docs/latex/wx/variant.tex | 27 +++++++++++++++++++++--
 include/wx/variant.h      | 14 +++++++++++-
 src/common/variant.cpp    | 46 ++++++++++++++++++++++++++++++++-------
 4 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index bc46d45cb3..74998a35ca 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -111,6 +111,10 @@ Changes in behaviour which may result in compilation errors
 
 - Removed global GetLine() function from wx/protocol/protocol.h, use
   wxProtocol::ReadLine() instead.
+  
+- wxVariant no longer derives from wxObject. wxVariantData also no longer
+  derives from wxObject; instead of using wxDynamicCast with wxVariantData you
+  can use the macro wxDynamicCastVariantData with the same arguments.
 
 
 Deprecated methods and their replacements
@@ -156,6 +160,8 @@ All:
 - Documentation now includes the wx library in which each class is defined.
 - wxrc --gettext now generates references to source .xrc files (Heikki
   Linnakangas).
+- wxVariant::Unshare allows exclusive allocation of data that must be shared,
+  if the wxVariantData::Clone function is implemented.
 
 All (Unix):
 
diff --git a/docs/latex/wx/variant.tex b/docs/latex/wx/variant.tex
index 8343da9923..db82e17c9e 100644
--- a/docs/latex/wx/variant.tex
+++ b/docs/latex/wx/variant.tex
@@ -74,7 +74,14 @@ IMPLEMENT_VARIANT_OBJECT(wxBitmap)
 
 Note that as of wxWidgets 2.9.0, wxVariantData no longer inherits from wxObject
 and wxVariant no longer uses the type-unsafe wxList class for list
-operations but the type-safe wxVariantList class.
+operations but the type-safe wxVariantList class. Also, wxVariantData now
+supports the Clone function for implementing the \helpref{wxVariant::Unshare}{wxvariantunshare} function.
+Clone is implemented automatically by IMPLEMENT\_VARIANT\_OBJECT.
+
+Since wxVariantData no longer derives from wxObject, any code that tests the type
+of the data using wxDynamicCast will require adjustment. You can use the macro
+wxDynamicCastVariantData with the same arguments as wxDynamicCast, to use C++ RTTI
+type information instead of wxWidgets RTTI.
 
 \wxheading{Derived from}
 
@@ -364,6 +371,15 @@ is of type list, but the number of elements in the list is zero.
 
 Sets the internal variant data, deleting the existing data if there is any.
 
+\membersection{wxVariant::Unshare}\label{wxvariantunshare}
+
+\func{bool}{Unshare}{\void}
+
+Makes sure that any data associated with this variant is not shared with other
+variants. For this to work, \helpref{wxVariantData::Clone}{wxvariantdataclone} must
+be implemented for the data types you are working with. Clone is implemented
+for all the default data types.
+
 \membersection{wxVariant::operator $=$}\label{wxvariantassignment}
 
 \func{void}{operator $=$}{\param{const wxVariant\& }{value}}
@@ -544,6 +560,14 @@ No base class
 
 Default constructor.
 
+\membersection{wxVariantData::Clone}\label{wxvariantdataclone}
+
+\constfunc{wxVariantData*}{Clone}{\void}
+
+This function can be overridden to clone the data.
+Implement Clone if you wish \helpref{wxVariant::Unshare}{wxvariantunshare} to work
+for your data. This function is implemented for all built-in data types.
+
 \membersection{wxVariantData::DecRef}\label{wxvariantdatadecref}
 
 \func{void}{DecRef}{\void}
@@ -555,7 +579,6 @@ Note that destructor of wxVariantData is protected, so delete
 cannot be used as normal. Instead, \helpref{DecRef}{wxvariantdatadecref} should be called.
 
 
-
 \membersection{wxVariantData::Eq}\label{wxvariantdataeq}
 
 \constfunc{bool}{Eq}{\param{wxVariantData\&}{ data}}
diff --git a/include/wx/variant.h b/include/wx/variant.h
index dffe0a0190..31fbbc8acb 100644
--- a/include/wx/variant.h
+++ b/include/wx/variant.h
@@ -81,6 +81,10 @@ public:
     // If it based on wxObject return the ClassInfo.
     virtual wxClassInfo* GetValueClassInfo() { return NULL; }
 
+    // Implement this to make wxVariant::AllocExcusive work. Returns
+    // a copy of the data.
+    virtual wxVariantData* Clone() const { return NULL; }
+
     void IncRef() { m_count++; }
     void DecRef()
     {
@@ -104,7 +108,7 @@ private:
  * wxVariant can store any kind of data, but has some basic types
  * built in.
  */
- 
+
 class WXDLLIMPEXP_FWD_BASE wxVariant;
 
 WX_DECLARE_LIST_WITH_DECL(wxVariant, wxVariantList, class WXDLLIMPEXP_BASE);
@@ -146,6 +150,9 @@ public:
     // destroy a reference
     void UnRef();
 
+    // ensure that the data is exclusive to this variant, and not shared
+    bool Unshare();
+
     // Make NULL (i.e. delete the data)
     void MakeNull();
 
@@ -365,6 +372,8 @@ public:\
 \
     virtual wxString GetType() const; \
     virtual wxClassInfo* GetValueClassInfo(); \
+\
+    virtual wxVariantData* Clone() const { return new classname##VariantData(m_value); } \
 \
 protected:\
     classname m_value; \
@@ -436,6 +445,9 @@ bool classname##VariantData::Eq(wxVariantData& data) const \
     ((classname*)(var.IsValueKindOf(&classname::ms_classInfo) ?\
                   var.GetWxObjectPtr() : NULL));
 
+// Replacement for using wxDynamicCast on a wxVariantData object
+#define wxDynamicCastVariantData(data, classname) dynamic_cast<classname*>(data)
+
 extern wxVariant WXDLLIMPEXP_BASE wxNullVariant;
 
 #endif // wxUSE_VARIANT
diff --git a/src/common/variant.cpp b/src/common/variant.cpp
index 8f3344671f..5120dc5554 100644
--- a/src/common/variant.cpp
+++ b/src/common/variant.cpp
@@ -130,7 +130,6 @@ bool wxVariant::operator!= (const wxVariant& variant) const
     return (!(*this == variant));
 }
 
-
 wxString wxVariant::MakeString() const
 {
     if (!IsNull())
@@ -177,6 +176,30 @@ void wxVariant::UnRef()
     }
 }
 
+bool wxVariant::Unshare()
+{
+    if ( m_data && m_data->GetRefCount() > 1 )
+    {
+        // note that ref is not going to be destroyed in this case...
+        const wxVariantData* ref = m_data;
+        UnRef();
+
+        // ... so we can still access it
+        m_data = ref->Clone();
+
+        wxASSERT_MSG( (m_data && m_data->GetRefCount() == 1),
+                  _T("wxVariant::AllocExclusive() failed.") );
+
+        if (!m_data || m_data->GetRefCount() != 1)
+            return false;
+        else
+            return true;
+    }
+    //else: data is null or ref count is 1, so we are exclusive owners of m_refData anyhow
+    else
+        return true;
+}
+
 
 // Returns a string representing the type of the variant,
 // e.g. "string", "bool", "list", "double", "long"
@@ -227,6 +250,8 @@ public:
     virtual bool Write(wxOutputStream &str) const;
 #endif // wxUSE_STREAMS
 
+    wxVariantData* Clone() const { return new wxVariantDataLong(m_value); }
+
     virtual wxString GetType() const { return wxT("long"); }
 
 protected:
@@ -377,6 +402,7 @@ public:
 #endif // wxUSE_STREAMS
     virtual wxString GetType() const { return wxT("double"); }
 
+    wxVariantData* Clone() const { return new wxVariantDoubleData(m_value); }
 protected:
     double m_value;
 };
@@ -514,6 +540,7 @@ public:
 #endif // wxUSE_STREAMS
     virtual wxString GetType() const { return wxT("bool"); }
 
+    wxVariantData* Clone() const { return new wxVariantDataBool(m_value); }
 protected:
     bool m_value;
 };
@@ -651,6 +678,7 @@ public:
     virtual bool Write(wxOutputStream& str) const;
 #endif // wxUSE_STREAMS
     virtual wxString GetType() const { return wxT("char"); }
+    wxVariantData* Clone() const { return new wxVariantDataChar(m_value); }
 
 protected:
     wxUniChar m_value;
@@ -802,6 +830,7 @@ public:
     virtual bool Write(wxOutputStream& str) const;
 #endif // wxUSE_STREAMS
     virtual wxString GetType() const { return wxT("string"); }
+    wxVariantData* Clone() const { return new wxVariantDataString(m_value); }
 
 protected:
     wxString m_value;
@@ -955,10 +984,10 @@ public:
 #endif
     virtual bool Read(wxString& str);
     virtual wxString GetType() const ;
-    virtual wxVariantData* Clone() { return new wxVariantDataWxObjectPtr; }
+    virtual wxVariantData* Clone() const { return new wxVariantDataWxObjectPtr(m_value); }
 
     virtual wxClassInfo* GetValueClassInfo();
-    
+
 protected:
     wxObject* m_value;
 };
@@ -975,13 +1004,13 @@ bool wxVariantDataWxObjectPtr::Eq(wxVariantData& data) const
 wxString wxVariantDataWxObjectPtr::GetType() const
 {
     wxString returnVal(wxT("wxObject*"));
-    
+
     if (m_value)
     {
         returnVal = m_value->GetClassInfo()->GetClassName();
         returnVal += wxT("*");
     }
-    
+
     return returnVal;
 }
 
@@ -1076,7 +1105,7 @@ public:
 #endif
     virtual bool Read(wxString& str);
     virtual wxString GetType() const { return wxT("void*"); }
-    virtual wxVariantData* Clone() { return new wxVariantDataVoidPtr; }
+    virtual wxVariantData* Clone() const { return new wxVariantDataVoidPtr(m_value); }
 
 protected:
     void* m_value;
@@ -1193,7 +1222,7 @@ public:
 #endif
     virtual bool Read(wxString& str);
     virtual wxString GetType() const { return wxT("datetime"); }
-    virtual wxVariantData* Clone() { return new wxVariantDataDateTime; }
+    virtual wxVariantData* Clone() const { return new wxVariantDataDateTime(m_value); }
 
 protected:
     wxDateTime m_value;
@@ -1357,7 +1386,7 @@ public:
 #endif
     virtual bool Read(wxString& str);
     virtual wxString GetType() const { return wxT("arrstring"); }
-    virtual wxVariantData* Clone() { return new wxVariantDataArrayString; }
+    virtual wxVariantData* Clone() const { return new wxVariantDataArrayString(m_value); }
 
 protected:
     wxArrayString m_value;
@@ -1484,6 +1513,7 @@ public:
 
     void Clear();
 
+    wxVariantData* Clone() const { return new wxVariantDataList(m_value); }
 protected:
     wxVariantList  m_value;
 };
-- 
2.50.0

