//
-// 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
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)
}
#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;
+ }
//@{
/**
*/
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
//@}
/**
- 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>
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.
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 \
~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;
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
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;
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>)
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") );
private:
CPPUNIT_TEST_SUITE( wxAnyTestCase );
+ CPPUNIT_TEST( CheckType );
CPPUNIT_TEST( Equality );
CPPUNIT_TEST( As );
CPPUNIT_TEST( GetAs );
CPPUNIT_TEST( CustomTemplateSpecialization );
CPPUNIT_TEST_SUITE_END();
+ void CheckType();
void Equality();
void As();
void GetAs();
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()
{
//
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);
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);