]> git.saurik.com Git - wxWidgets.git/commitdiff
Allow wxAny to contain 'const char*' or 'const wchar_t*'. This was previously not...
authorJaakko Salli <jaakko.salli@dnainternet.net>
Thu, 22 Apr 2010 13:51:38 +0000 (13:51 +0000)
committerJaakko Salli <jaakko.salli@dnainternet.net>
Thu, 22 Apr 2010 13:51:38 +0000 (13:51 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64106 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/any.h
include/wx/variant.h
interface/wx/any.h
src/common/any.cpp
src/common/variant.cpp
tests/any/anytest.cpp

index 2e9a9af4e5c524d00256b4e2eba19b396e41a17b..64930ef66b9718501aaef13b64b2027cb30f4ac4 100644 (file)
@@ -403,35 +403,55 @@ WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t, Uint)
 
 
 //
-// String value type
+// This macro is used in header, but then in source file we must have:
+// WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME)
 //
-class WXDLLIMPEXP_BASE wxAnyValueTypeImplString :
-    public wxAnyValueTypeImplBase<wxString>
-{
-    WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
-public:
-    wxAnyValueTypeImplString() :
-        wxAnyValueTypeImplBase<wxString>() { }
-    virtual ~wxAnyValueTypeImplString() { }
+#define _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, GV) \
+class WXDLLIMPEXP_BASE wxAnyValueTypeImpl##TYPENAME : \
+    public wxAnyValueTypeImplBase<T> \
+{ \
+    WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME) \
+public: \
+    wxAnyValueTypeImpl##TYPENAME() : \
+        wxAnyValueTypeImplBase<T>() { } \
+    virtual ~wxAnyValueTypeImpl##TYPENAME() { } \
+    virtual bool ConvertValue(const wxAnyValueBuffer& src, \
+                              wxAnyValueType* dstType, \
+                              wxAnyValueBuffer& dst) const \
+    { \
+        GV value = GetValue(src); \
+        return CONVFUNC(value, dstType, dst); \
+    } \
+}; \
+template<> \
+class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##TYPENAME \
+{ \
+public: \
+    wxAnyValueTypeImpl() : wxAnyValueTypeImpl##TYPENAME() { } \
+    virtual ~wxAnyValueTypeImpl() { } \
+};
 
-    /**
-        Convert value into buffer of different type. Return false if
-        not possible.
-    */
-    virtual bool ConvertValue(const wxAnyValueBuffer& src,
-                              wxAnyValueType* dstType,
-                              wxAnyValueBuffer& dst) const;
+#define WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \
+_WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \
 
-};
+#define WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(T, TYPENAME, CONVFUNC) \
+_WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, \
+                                CONVFUNC, const T&) \
 
-template<>
-class wxAnyValueTypeImpl<wxString> : public wxAnyValueTypeImplString
-{
-public:
-    wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
-    virtual ~wxAnyValueTypeImpl() { }
-};
+//
+// String value type
+//
 
+// Convert wxString to destination wxAny value type
+extern WXDLLIMPEXP_BASE bool wxAnyConvertString(const wxString& value,
+                                                wxAnyValueType* dstType,
+                                                wxAnyValueBuffer& dst);
+
+WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(wxString, wxString, wxAnyConvertString)
+WX_ANY_DEFINE_CONVERTIBLE_TYPE(const char*, ConstCharPtr,
+                               wxAnyConvertString, wxString)
+WX_ANY_DEFINE_CONVERTIBLE_TYPE(const wchar_t*, ConstWchar_tPtr,
+                               wxAnyConvertString, wxString)
 
 //
 // Bool value type
@@ -686,16 +706,16 @@ public:
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
     }
 
+    // These two constructors are needed to deal with string literals
     wxAny(const char* value)
     {
-        m_type = wxAnyNullValueType;
-        Assign(wxString(value));
+        m_type = wxAnyValueTypeImpl<const char*>::sm_instance;
+        wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer);
     }
-
     wxAny(const wchar_t* value)
     {
-        m_type = wxAnyNullValueType;
-        Assign(wxString(value));
+        m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance;
+        wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer);
     }
 
     wxAny(const wxAny& any)
@@ -789,11 +809,17 @@ public:
     }
 #endif
 
+    // These two operators are needed to deal with string literals
     wxAny& operator=(const char* value)
-        { Assign(wxString(value)); return *this; }
+    {
+        Assign(value);
+        return *this;
+    }
     wxAny& operator=(const wchar_t* value)
-        { Assign(wxString(value)); return *this; }
-    //@}
+    {
+        Assign(value);
+        return *this;
+    }
 
     //@{
     /**
@@ -801,12 +827,10 @@ public:
     */
     bool operator==(const wxString& value) const
     {
-        if ( !wxAnyValueTypeImpl<wxString>::IsSameClass(m_type) )
+        wxString value2;
+        if ( !GetAs(&value2) )
             return false;
-
-        return value ==
-            static_cast<wxString>
-                (wxAnyValueTypeImpl<wxString>::GetValue(m_buffer));
+        return value == value2;
     }
 
     bool operator==(const char* value) const
@@ -865,14 +889,17 @@ public:
     //@}
 
     /**
-        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.
+        This template function converts wxAny into given type. In most cases
+        no type conversion is performed, so if the type is incorrect an
+        assertion failure will occur.
 
-        @remarks This template function does not work on some older compilers
-                (such as Visual C++ 6.0). For full compiler compatibility
-                please use wxANY_AS(any, T) macro instead.
+        @remarks For conveniency, conversion is done when T is wxString. This
+                 is useful when a string literal (which are treated as
+                 const char* and const wchar_t*) has been assigned to wxAny.
+
+                 This template function may not work properly with Visual C++
+                 6. For full compiler compatibility, please use
+                 wxANY_AS(any, T) macro instead.
     */
     // FIXME-VC6: remove this hack when VC6 is no longer supported
     template<typename T>
@@ -886,6 +913,19 @@ public:
         return static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer));
     }
 
+    // Allow easy conversion from 'const char *' etc. to wxString
+    // FIXME-VC6: remove this hack when VC6 is no longer supported
+    //template<>
+    wxString As(wxString*) const
+    {
+        wxString value;
+        if ( !GetAs(&value) )
+        {
+            wxFAIL_MSG("Incorrect or non-convertible data type");
+        }
+        return value;
+    }
+
     /**
         Template function that etrieves and converts the value of this
         variant to the type that T* value is.
index 852be3bb6b25a6343e3f366590d718b4626f9879..671db18c6575352ca34f221e05b198e73b644313 100644 (file)
@@ -404,10 +404,13 @@ private:
 virtual bool GetAsAny(wxAny* any) const; \
 static wxVariantData* VariantDataFactory(const wxAny& any);
 
-#define REGISTER_WXANY_CONVERSION(T, CLASSNAME) \
+#define _REGISTER_WXANY_CONVERSION(T, CLASSNAME, FUNC) \
 static wxAnyToVariantRegistrationImpl<T> \
     gs_##CLASSNAME##AnyToVariantRegistration = \
-    wxAnyToVariantRegistrationImpl<T>(&CLASSNAME::VariantDataFactory);
+    wxAnyToVariantRegistrationImpl<T>(&FUNC);
+
+#define REGISTER_WXANY_CONVERSION(T, CLASSNAME) \
+_REGISTER_WXANY_CONVERSION(T, CLASSNAME, CLASSNAME::VariantDataFactory)
 
 #define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) \
 bool CLASSNAME::GetAsAny(wxAny* any) const \
index 826d2b7a1488f3ed5cb8337e0837fcc022a4c168..2a8a22c3e664b507817b0f20f964bd65359ef62e 100644 (file)
@@ -104,14 +104,17 @@ public:
     ~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.
+        This template function converts wxAny into given type. In most cases
+        no type conversion is performed, so if the type is incorrect an
+        assertion failure will occur.
 
-        @remarks This template function may not work properly with Visual C++
-                6. For full compiler compatibility, please use
-                wxANY_AS(any, T) macro instead.
+        @remarks For conveniency, conversion is done when T is wxString. This
+                 is useful when a string literal (which are treated as
+                 const char* and const wchar_t*) has been assigned to wxAny.
+
+                 This template function may not work properly with Visual C++
+                 6. For full compiler compatibility, please use
+                 wxANY_AS(any, T) macro instead.
     */
     template<typename T>
     T As() const;
index 56e315eb954d7de4874656ce59ba871e358caada..ac960455b32e90cc22f3d8b1a4dfd2f14551d360 100644 (file)
@@ -374,12 +374,16 @@ bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
     return true;
 }
 
-bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src,
-                                            wxAnyValueType* dstType,
-                                            wxAnyValueBuffer& dst) const
+// Convert wxString to destination wxAny value type
+bool wxAnyConvertString(const wxString& value,
+                        wxAnyValueType* dstType,
+                        wxAnyValueBuffer& dst)
 {
-    wxString value = GetValue(src);
-    if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
+    if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
+    {
+        wxAnyValueTypeImpl<wxString>::SetValue(value, dst);
+    }
+    else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
     {
         wxAnyBaseIntType value2;
 #ifdef wxLongLong_t
@@ -411,14 +415,15 @@ bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src,
     else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
     {
         bool value2;
-        value.MakeLower();
-        if ( value == wxS("true") ||
-             value == wxS("yes") ||
-             value == wxS('1') )
+        wxString s(value);
+        s.MakeLower();
+        if ( s == wxS("true") ||
+             s == wxS("yes") ||
+             s == wxS('1') )
             value2 = true;
-        else if ( value == wxS("false") ||
-                  value == wxS("no") ||
-                  value == wxS('0') )
+        else if ( s == wxS("false") ||
+                  s == wxS("no") ||
+                  s == wxS('0') )
             value2 = false;
         else
             return false;
@@ -493,10 +498,13 @@ bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
 
 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
-WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
 
+WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
+WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
+WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
+
 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
index 0470d2d4b373bd5f563fcce865d09580390c0b9f..1820f4b8d5ef41912126fc9a2e31fc4b0ec9b387 100644 (file)
@@ -879,6 +879,26 @@ protected:
 
 IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxString, wxVariantDataString)
 
+#if wxUSE_ANY
+// This allows converting string literal wxAnys to string variants
+wxVariantData* wxVariantDataFromConstCharPAny(const wxAny& any)
+{
+    return new wxVariantDataString(wxANY_AS(any, const char*));
+}
+
+wxVariantData* wxVariantDataFromConstWchar_tPAny(const wxAny& any)
+{
+    return new wxVariantDataString(wxANY_AS(any, const wchar_t*));
+}
+
+_REGISTER_WXANY_CONVERSION(const char*,
+                           ConstCharP,
+                           wxVariantDataFromConstCharPAny)
+_REGISTER_WXANY_CONVERSION(const wchar_t*,
+                           ConstWchar_tP,
+                           wxVariantDataFromConstWchar_tPAny)
+#endif
+
 bool wxVariantDataString::Eq(wxVariantData& data) const
 {
     wxASSERT_MSG( (data.GetType() == wxT("string")), wxT("wxVariantDataString::Eq: argument mismatch") );
index e215f489059a5bcc2bb683e9223df15f3937769c..8bdd8a23696747230a5415ceb640925a61267ab7 100644 (file)
@@ -32,6 +32,7 @@ public:
 
 private:
     CPPUNIT_TEST_SUITE( wxAnyTestCase );
+        CPPUNIT_TEST( CheckType );
         CPPUNIT_TEST( Equality );
         CPPUNIT_TEST( As );
         CPPUNIT_TEST( GetAs );
@@ -40,6 +41,7 @@ private:
         CPPUNIT_TEST( CustomTemplateSpecialization );
     CPPUNIT_TEST_SUITE_END();
 
+    void CheckType();
     void Equality();
     void As();
     void GetAs();
@@ -164,6 +166,19 @@ wxAnyTestCase::wxAnyTestCase()
     m_anyVoidPtr2 = dummyVoidPointer;
 }
 
+void wxAnyTestCase::CheckType()
+{
+    wxAny nullAny;
+    CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(nullAny, wxString));
+
+    CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyCharString2, const char*));
+    CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, wxString));
+    CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, const wchar_t*));
+    CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyWcharString2, const wchar_t*));
+    CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, wxString));
+    CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, const char*));
+}
+
 void wxAnyTestCase::Equality()
 {
     //
@@ -243,8 +258,12 @@ void wxAnyTestCase::As()
     wxString k = wxANY_AS(m_anyStringString1, wxString);
     CPPUNIT_ASSERT(k == "abc");
     wxString l = wxANY_AS(m_anyCharString1, wxString);
+    const char* cptr = wxANY_AS(m_anyCharString1, const char*);
     CPPUNIT_ASSERT(l == "abc");
+    CPPUNIT_ASSERT(cptr);
     wxString m = wxANY_AS(m_anyWcharString1, wxString);
+    const wchar_t* wcptr = wxANY_AS(m_anyWcharString1, const wchar_t*);
+    CPPUNIT_ASSERT(wcptr);
     CPPUNIT_ASSERT(m == "abc");
     bool n = wxANY_AS(m_anyBool1, bool);
     CPPUNIT_ASSERT(n);
@@ -488,6 +507,19 @@ void wxAnyTestCase::wxVariantConversions()
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetString() == "ABC");
 
+    // Must be able to build string wxVariant from wxAny built from
+    // string literal
+    any = "ABC";
+    res = any.GetAs(&variant);
+    CPPUNIT_ASSERT(res);
+    CPPUNIT_ASSERT(variant.GetType() == "string");
+    CPPUNIT_ASSERT(variant.GetString() == "ABC");
+    any = L"ABC";
+    res = any.GetAs(&variant);
+    CPPUNIT_ASSERT(res);
+    CPPUNIT_ASSERT(variant.GetType() == "string");
+    CPPUNIT_ASSERT(variant.GetString() == L"ABC");
+
     any = vDouble;
     double d = wxANY_AS(any, double);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(d, TEST_FLOAT_CONST, FEQ_DELTA);