1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxAny class
4 // Author: Jaakko Salli
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
19 #include "wx/string.h"
20 #include "wx/meta/movable.h"
21 #include "wx/meta/if.h"
24 // Size of the wxAny value buffer.
27 WX_ANY_VALUE_BUFFER_SIZE
= 16
30 union wxAnyValueBuffer
37 long double m_longDouble
;
38 void ( *m_funcPtr
)(void);
39 void ( wxAnyValueBuffer::*m_mFuncPtr
)(void);
43 wxByte m_buffer
[WX_ANY_VALUE_BUFFER_SIZE
];
46 typedef void (*wxAnyClassInfo
)();
50 // wxAnyValueType is base class for value type functionality for C++ data
51 // types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
52 // will create a satisfactory wxAnyValueType implementation for a data type.
54 class WXDLLIMPEXP_BASE wxAnyValueType
65 virtual ~wxAnyValueType()
70 This function is used for internal type matching.
72 virtual wxAnyClassInfo
GetClassInfo() const = 0;
75 This function is used for internal type matching.
77 virtual bool IsSameType(const wxAnyValueType
* otherType
) const = 0;
80 This function is called every time the data in wxAny
81 buffer needs to be freed.
83 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const = 0;
86 Implement this for buffer-to-buffer copy.
89 This is the source data buffer.
92 This is the destination data buffer that is in either
93 uninitialized or freed state.
95 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
96 wxAnyValueBuffer
& dst
) const = 0;
99 Convert value into buffer of different type. Return false if
102 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
103 wxAnyValueType
* dstType
,
104 wxAnyValueBuffer
& dst
) const = 0;
107 Use this template function for checking if wxAnyValueType represents
108 a specific C++ data type.
110 @remarks This template function does not work on some older compilers
111 (such as Visual C++ 6.0). For full compiler ccompatibility
112 please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
115 @see wxAny::CheckType()
117 // FIXME-VC6: remove this hack when VC6 is no longer supported
118 template <typename T
>
119 bool CheckType(T
* reserved
= NULL
);
124 // This method of checking the type is compatible with VC6
125 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
126 wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
128 //valueTypePtr->CheckType(static_cast<T*>(NULL))
132 Helper macro for defining user value types.
134 NB: We really cannot compare sm_classInfo directly in IsSameClass(),
135 but instead call sm_instance->GetClassInfo(). The former technique
136 broke at least on GCC 4.2 (but worked on VC8 shared build).
138 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
139 friend class wxAny; \
141 static void sm_classInfo() {} \
143 virtual wxAnyClassInfo GetClassInfo() const \
145 return sm_classInfo; \
147 static bool IsSameClass(const wxAnyValueType* otherType) \
149 return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \
151 virtual bool IsSameType(const wxAnyValueType* otherType) const \
153 return IsSameClass(otherType); \
156 static CLS* sm_instance; \
158 static wxAnyValueType* GetInstance() \
160 return sm_instance; \
164 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
165 CLS* CLS::sm_instance = new CLS();
169 // "non dll-interface class 'xxx' used as base interface
170 #pragma warning (push)
171 #pragma warning (disable:4275)
175 Following are helper classes for the wxAnyValueTypeImplBase.
181 class wxAnyValueTypeOpsMovable
184 static void DeleteValue(wxAnyValueBuffer
& buf
)
189 static void SetValue(const T
& value
,
190 wxAnyValueBuffer
& buf
)
192 memcpy(buf
.m_buffer
, &value
, sizeof(T
));
195 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
197 return *(reinterpret_cast<const T
*>(&buf
.m_buffer
[0]));
203 class wxAnyValueTypeOpsGeneric
206 template<typename T2
>
210 DataHolder(const T2
& value
)
214 virtual ~DataHolder() { }
218 wxDECLARE_NO_COPY_CLASS(DataHolder
);
221 static void DeleteValue(wxAnyValueBuffer
& buf
)
223 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
227 static void SetValue(const T
& value
,
228 wxAnyValueBuffer
& buf
)
230 DataHolder
<T
>* holder
= new DataHolder
<T
>(value
);
234 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
236 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
237 return holder
->m_value
;
241 } // namespace wxPrivate
245 Intermediate template for the generic value type implementation.
246 We can derive from this same value type for multiple actual types
247 (for instance, we can have wxAnyValueTypeImplInt for all signed
248 integer types), and also easily implement specialized templates
249 with specific dynamic type conversion.
252 class wxAnyValueTypeImplBase
: public wxAnyValueType
254 typedef typename wxIf
< wxIsMovable
<T
>::value
&&
255 sizeof(T
) <= WX_ANY_VALUE_BUFFER_SIZE
,
256 wxPrivate::wxAnyValueTypeOpsMovable
<T
>,
257 wxPrivate::wxAnyValueTypeOpsGeneric
<T
> >::value
261 wxAnyValueTypeImplBase() : wxAnyValueType() { }
262 virtual ~wxAnyValueTypeImplBase() { }
264 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
266 Ops::DeleteValue(buf
);
269 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
270 wxAnyValueBuffer
& dst
) const
272 Ops::SetValue(Ops::GetValue(src
), dst
);
276 It is important to reimplement this in any specialized template
277 classes that inherit from wxAnyValueTypeImplBase.
279 static void SetValue(const T
& value
,
280 wxAnyValueBuffer
& buf
)
282 Ops::SetValue(value
, buf
);
286 It is important to reimplement this in any specialized template
287 classes that inherit from wxAnyValueTypeImplBase.
289 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
291 return Ops::GetValue(buf
);
297 Generic value type template. Note that bulk of the implementation
298 resides in wxAnyValueTypeImplBase.
301 class wxAnyValueTypeImpl
: public wxAnyValueTypeImplBase
<T
>
303 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<T
>)
305 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase
<T
>() { }
306 virtual ~wxAnyValueTypeImpl() { }
308 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
309 wxAnyValueType
* dstType
,
310 wxAnyValueBuffer
& dst
) const
313 wxUnusedVar(dstType
);
320 wxAnyValueTypeImpl
<T
>* wxAnyValueTypeImpl
<T
>::sm_instance
=
321 new wxAnyValueTypeImpl
<T
>();
325 // Helper macro for using same base value type implementation for multiple
326 // actual C++ data types.
328 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
330 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
332 typedef wxAnyBase##CLSTYPE##Type UseDataType; \
334 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
335 virtual ~wxAnyValueTypeImpl() { } \
336 static void SetValue(const T& value, wxAnyValueBuffer& buf) \
338 *(reinterpret_cast<UseDataType*>(&buf.m_buffer[0])) = \
339 static_cast<UseDataType>(value); \
341 static T GetValue(const wxAnyValueBuffer& buf) \
343 return static_cast<T>( \
344 *(reinterpret_cast<const UseDataType*>(&buf.m_buffer[0]))); \
350 // Integer value types
354 typedef wxLongLong_t wxAnyBaseIntType
;
355 typedef wxULongLong_t wxAnyBaseUintType
;
357 typedef long wxAnyBaseIntType
;
358 typedef unsigned long wxAnyBaseUintType
;
362 class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt
:
363 public wxAnyValueTypeImplBase
<wxAnyBaseIntType
>
365 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
367 wxAnyValueTypeImplInt() :
368 wxAnyValueTypeImplBase
<wxAnyBaseIntType
>() { }
369 virtual ~wxAnyValueTypeImplInt() { }
371 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
372 wxAnyValueType
* dstType
,
373 wxAnyValueBuffer
& dst
) const;
377 class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint
:
378 public wxAnyValueTypeImplBase
<wxAnyBaseUintType
>
380 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
382 wxAnyValueTypeImplUint() :
383 wxAnyValueTypeImplBase
<wxAnyBaseUintType
>() { }
384 virtual ~wxAnyValueTypeImplUint() { }
386 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
387 wxAnyValueType
* dstType
,
388 wxAnyValueBuffer
& dst
) const;
392 WX_ANY_DEFINE_SUB_TYPE(signed long, Int
)
393 WX_ANY_DEFINE_SUB_TYPE(signed int, Int
)
394 WX_ANY_DEFINE_SUB_TYPE(signed short, Int
)
395 WX_ANY_DEFINE_SUB_TYPE(signed char, Int
)
397 WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t
, Int
)
400 WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint
)
401 WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint
)
402 WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint
)
403 WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint
)
405 WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t
, Uint
)
412 class WXDLLIMPEXP_BASE wxAnyValueTypeImplString
:
413 public wxAnyValueTypeImplBase
<wxString
>
415 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
417 wxAnyValueTypeImplString() :
418 wxAnyValueTypeImplBase
<wxString
>() { }
419 virtual ~wxAnyValueTypeImplString() { }
422 Convert value into buffer of different type. Return false if
425 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
426 wxAnyValueType
* dstType
,
427 wxAnyValueBuffer
& dst
) const;
432 class wxAnyValueTypeImpl
<wxString
> : public wxAnyValueTypeImplString
435 wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
436 virtual ~wxAnyValueTypeImpl() { }
444 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl
<bool> :
445 public wxAnyValueTypeImplBase
<bool>
447 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
449 wxAnyValueTypeImpl() :
450 wxAnyValueTypeImplBase
<bool>() { }
451 virtual ~wxAnyValueTypeImpl() { }
453 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
454 wxAnyValueType
* dstType
,
455 wxAnyValueBuffer
& dst
) const;
459 // Floating point value type
461 class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble
:
462 public wxAnyValueTypeImplBase
<double>
464 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
466 wxAnyValueTypeImplDouble() :
467 wxAnyValueTypeImplBase
<double>() { }
468 virtual ~wxAnyValueTypeImplDouble() { }
470 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
471 wxAnyValueType
* dstType
,
472 wxAnyValueBuffer
& dst
) const;
475 // WX_ANY_DEFINE_SUB_TYPE requires this
476 typedef double wxAnyBaseDoubleType
;
478 WX_ANY_DEFINE_SUB_TYPE(float, Double
)
479 WX_ANY_DEFINE_SUB_TYPE(double, Double
)
483 // Defines a dummy wxAnyValueTypeImpl<> with given export
484 // declaration. This is needed if a class is used with
485 // wxAny in both user shared library and application.
487 #define wxDECLARE_ANY_TYPE(CLS, DECL) \
489 class DECL wxAnyValueTypeImpl<CLS> : \
490 public wxAnyValueTypeImplBase<CLS> \
492 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<CLS>) \
494 wxAnyValueTypeImpl() : \
495 wxAnyValueTypeImplBase<CLS>() { } \
496 virtual ~wxAnyValueTypeImpl() { } \
498 virtual bool ConvertValue(const wxAnyValueBuffer& src, \
499 wxAnyValueType* dstType, \
500 wxAnyValueBuffer& dst) const \
503 wxUnusedVar(dstType); \
510 // Make sure some of wx's own types get the right wxAnyValueType export
511 // (this is needed only for types that are referred to from wxBase.
512 // currently we may not use any of these types from there, but let's
513 // use the macro on at least one to make sure it compiles since we can't
514 // really test it properly in unittests since a separate DLL would
517 #include "wx/datetime.h"
518 wxDECLARE_ANY_TYPE(wxDateTime
, WXDLLIMPEXP_BASE
)
521 //#include "wx/object.h"
522 //wxDECLARE_ANY_TYPE(wxObject*, WXDLLIMPEXP_BASE)
524 //#include "wx/arrstr.h"
525 //wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE)
530 // Re-enable useless VC6 warnings
531 #pragma warning (pop)
536 Let's define a discrete Null value so we don't have to really
537 ever check if wxAny.m_type pointer is NULL or not. This is an
538 optimization, mostly. Implementation of this value type is
539 "hidden" in the source file.
541 extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType
*) wxAnyNullValueType
;
545 // We need to implement custom signed/unsigned int equals operators
546 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
547 #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
548 bool operator==(TS value) const \
550 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
551 return (value == static_cast<TS> \
552 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
553 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
554 return (value == static_cast<TS> \
555 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
558 bool operator==(TUS value) const \
560 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
561 return (value == static_cast<TUS> \
562 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
563 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
564 return (value == static_cast<TUS> \
565 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
571 // The wxAny class represents a container for any type. A variant's value
572 // can be changed at run time, possibly to a different type of value.
574 // As standard, wxAny can store value of almost any type, in a fairly
575 // optimal manner even.
585 m_type
= wxAnyNullValueType
;
593 m_type
->DeleteValue(m_buffer
);
598 Various constructors.
600 wxAny(const char* value
)
602 m_type
= wxAnyNullValueType
;
603 Assign(wxString(value
));
605 wxAny(const wchar_t* value
)
607 m_type
= wxAnyNullValueType
;
608 Assign(wxString(value
));
611 wxAny(const wxAny
& any
)
613 m_type
= wxAnyNullValueType
;
618 wxAny(const T
& value
)
620 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
621 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
626 Use this template function for checking if this wxAny holds
627 a specific C++ data type.
629 @remarks This template function does not work on some older compilers
630 (such as Visual C++ 6.0). For full compiler ccompatibility
631 please use wxANY_CHECK_TYPE(any, T) macro instead.
633 @see wxAnyValueType::CheckType()
635 // FIXME-VC6: remove this hack when VC6 is no longer supported
636 template <typename T
>
637 bool CheckType(T
* = NULL
)
639 return m_type
->CheckType
<T
>();
643 Returns the value type as wxAnyValueType instance.
645 @remarks You cannot reliably test whether two wxAnys are of
646 same value type by simply comparing return values
647 of wxAny::GetType(). Instead use
648 wxAnyValueType::CheckType<T>() template function.
650 const wxAnyValueType
* GetType() const
656 Tests if wxAny is null (that is, whether there is data).
660 return (m_type
== wxAnyNullValueType
);
664 Makes wxAny null (that is, clears it).
668 m_type
->DeleteValue(m_buffer
);
669 m_type
= wxAnyNullValueType
;
674 Assignment operators.
676 wxAny
& operator=(const wxAny
&any
)
683 wxAny
& operator=(const T
&value
)
685 m_type
->DeleteValue(m_buffer
);
686 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
687 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
691 wxAny
& operator=(const char* value
)
692 { Assign(wxString(value
)); return *this; }
693 wxAny
& operator=(const wchar_t* value
)
694 { Assign(wxString(value
)); return *this; }
701 bool operator==(const wxString
& value
) const
703 if ( !wxAnyValueTypeImpl
<wxString
>::IsSameClass(m_type
) )
707 static_cast<wxString
>
708 (wxAnyValueTypeImpl
<wxString
>::GetValue(m_buffer
));
711 bool operator==(const char* value
) const
712 { return (*this) == wxString(value
); }
713 bool operator==(const wchar_t* value
) const
714 { return (*this) == wxString(value
); }
717 // We need to implement custom signed/unsigned int equals operators
718 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
719 WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
720 WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
721 WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
722 WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
724 WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t
, wxULongLong_t
)
727 bool operator==(float value
) const
729 if ( !wxAnyValueTypeImpl
<float>::IsSameClass(m_type
) )
734 (wxAnyValueTypeImpl
<float>::GetValue(m_buffer
));
737 bool operator==(double value
) const
739 if ( !wxAnyValueTypeImpl
<double>::IsSameClass(m_type
) )
744 (wxAnyValueTypeImpl
<double>::GetValue(m_buffer
));
747 bool operator==(bool value
) const
749 if ( !wxAnyValueTypeImpl
<bool>::IsSameClass(m_type
) )
752 return value
== (wxAnyValueTypeImpl
<bool>::GetValue(m_buffer
));
759 Inequality operators (implement as template).
762 bool operator!=(const T
& value
) const
763 { return !((*this) == value
); }
767 This template function converts wxAny into given type. No dynamic
768 conversion is performed, so if the type is incorrect an assertion
769 failure will occur in debug builds, and a bogus value is returned
772 @remarks This template function does not work on some older compilers
773 (such as Visual C++ 6.0). For full compiler ccompatibility
774 please use wxANY_AS(any, T) macro instead.
776 // FIXME-VC6: remove this hack when VC6 is no longer supported
778 T
As(T
* = NULL
) const
780 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
782 wxFAIL_MSG("Incorrect or non-convertible data type");
785 return static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
789 Template function that etrieves and converts the value of this
790 variant to the type that T* value is.
792 @return Returns @true if conversion was succesfull.
795 bool GetAs(T
* value
) const
797 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
799 wxAnyValueType
* otherType
=
800 wxAnyValueTypeImpl
<T
>::sm_instance
;
801 wxAnyValueBuffer temp_buf
;
803 if ( !m_type
->ConvertValue(m_buffer
, otherType
, temp_buf
) )
807 static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(temp_buf
));
808 otherType
->DeleteValue(temp_buf
);
812 *value
= static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
817 // Assignment functions
818 void AssignAny(const wxAny
& any
)
820 // Must delete value - CopyBuffer() never does that
821 m_type
->DeleteValue(m_buffer
);
823 wxAnyValueType
* newType
= any
.m_type
;
825 if ( !newType
->IsSameType(m_type
) )
828 newType
->CopyBuffer(any
.m_buffer
, m_buffer
);
832 void Assign(const T
&value
)
834 m_type
->DeleteValue(m_buffer
);
835 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
836 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
840 wxAnyValueBuffer m_buffer
;
841 wxAnyValueType
* m_type
;
846 // This method of checking the type is compatible with VC6
847 #define wxANY_CHECK_TYPE(any, T) \
848 wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T)
852 // This method of getting the value is compatible with VC6
853 #define wxANY_AS(any, T) \
854 any.As(static_cast<T*>(NULL))
858 inline bool wxAnyValueType::CheckType(T
* reserved
)
860 wxUnusedVar(reserved
);
861 return wxAnyValueTypeImpl
<T
>::IsSameClass(this);