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 void ( *m_funcPtr
)(void);
38 void ( wxAnyValueBuffer
::*m_mFuncPtr
)(void);
39 wxByte m_buffer
[WX_ANY_VALUE_BUFFER_SIZE
];
42 typedef void (*wxAnyClassInfo
)();
46 // wxAnyValueType is base class for value type functionality for C++ data
47 // types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
48 // will create a satisfactory wxAnyValueType implementation for a data type.
50 class WXDLLIMPEXP_BASE wxAnyValueType
61 virtual ~wxAnyValueType()
66 This function is used for internal type matching.
68 virtual wxAnyClassInfo
GetClassInfo() const = 0;
71 This function is used for internal type matching.
73 virtual bool IsSameType(const wxAnyValueType
* otherType
) const = 0;
76 This function is called every time the data in wxAny
77 buffer needs to be freed.
79 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const = 0;
82 Implement this for buffer-to-buffer copy. src.m_ptr can
83 be expected to be NULL if value type of previously stored
86 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
87 wxAnyValueBuffer
& dst
) const = 0;
90 Convert value into buffer of different type. Return false if
93 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
94 wxAnyValueType
* dstType
,
95 wxAnyValueBuffer
& dst
) const = 0;
98 Use this template function for checking if wxAnyValueType represents
99 a specific C++ data type.
101 @remarks This template function does not work on some older compilers
102 (such as Visual C++ 6.0). For full compiler ccompatibility
103 please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
106 @see wxAny::CheckType()
108 // FIXME-VC6: remove this hack when VC6 is no longer supported
109 template <typename T
>
110 bool CheckType(T
* reserved
= NULL
);
115 // This method of checking the type is compatible with VC6
116 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
117 wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
119 //valueTypePtr->CheckType(static_cast<T*>(NULL))
123 Helper macro for defining user value types.
125 NB: We really cannot compare sm_classInfo directly in IsSameClass(),
126 but instead call sm_instance->GetClassInfo(). The former technique
127 broke at least on GCC 4.2 (but worked on VC8 shared build).
129 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
130 friend class wxAny; \
132 static void sm_classInfo() {} \
134 virtual wxAnyClassInfo GetClassInfo() const \
136 return sm_classInfo; \
138 static bool IsSameClass(const wxAnyValueType* otherType) \
140 return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \
142 virtual bool IsSameType(const wxAnyValueType* otherType) const \
144 return IsSameClass(otherType); \
147 static CLS* sm_instance; \
149 static wxAnyValueType* GetInstance() \
151 return sm_instance; \
155 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
156 CLS* CLS::sm_instance = new CLS();
160 // "non dll-interface class 'xxx' used as base interface
161 #pragma warning (push)
162 #pragma warning (disable:4275)
166 Following are helper classes for the wxAnyValueTypeImplBase.
172 class wxAnyValueTypeOpsMovable
175 static void DeleteValue(wxAnyValueBuffer
& buf
)
180 static void SetValue(const T
& value
,
181 wxAnyValueBuffer
& buf
)
183 memcpy(buf
.m_buffer
, &value
, sizeof(T
));
186 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
188 return *(reinterpret_cast<const T
*>(&buf
.m_buffer
[0]));
194 class wxAnyValueTypeOpsGeneric
197 template<typename T2
>
201 DataHolder(const T2
& value
)
205 virtual ~DataHolder() { }
209 wxDECLARE_NO_COPY_CLASS(DataHolder
);
212 static void DeleteValue(wxAnyValueBuffer
& buf
)
214 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
218 static void SetValue(const T
& value
,
219 wxAnyValueBuffer
& buf
)
221 DataHolder
<T
>* holder
= new DataHolder
<T
>(value
);
225 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
227 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
228 return holder
->m_value
;
232 } // namespace wxPrivate
236 Intermediate template for the generic value type implementation.
237 We can derive from this same value type for multiple actual types
238 (for instance, we can have wxAnyValueTypeImplInt for all signed
239 integer types), and also easily implement specialized templates
240 with specific dynamic type conversion.
243 class wxAnyValueTypeImplBase
: public wxAnyValueType
245 typedef typename wxIf
< wxIsMovable
<T
>::value
&&
246 sizeof(T
) <= WX_ANY_VALUE_BUFFER_SIZE
,
247 wxPrivate
::wxAnyValueTypeOpsMovable
<T
>,
248 wxPrivate
::wxAnyValueTypeOpsGeneric
<T
> >::value
252 wxAnyValueTypeImplBase() : wxAnyValueType() { }
253 virtual ~wxAnyValueTypeImplBase() { }
255 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
257 Ops
::DeleteValue(buf
);
258 buf
.m_ptr
= NULL
; // This is important
261 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
262 wxAnyValueBuffer
& dst
) const
264 Ops
::DeleteValue(dst
);
265 Ops
::SetValue(Ops
::GetValue(src
), dst
);
269 It is important to reimplement this in any specialized template
270 classes that inherit from wxAnyValueTypeImplBase.
272 static void SetValue(const T
& value
,
273 wxAnyValueBuffer
& buf
)
275 Ops
::SetValue(value
, buf
);
279 It is important to reimplement this in any specialized template
280 classes that inherit from wxAnyValueTypeImplBase.
282 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
284 return Ops
::GetValue(buf
);
290 Generic value type template. Note that bulk of the implementation
291 resides in wxAnyValueTypeImplBase.
294 class wxAnyValueTypeImpl
: public wxAnyValueTypeImplBase
<T
>
296 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<T
>)
298 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase
<T
>() { }
299 virtual ~wxAnyValueTypeImpl() { }
301 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
302 wxAnyValueType
* dstType
,
303 wxAnyValueBuffer
& dst
) const
306 wxUnusedVar(dstType
);
313 wxAnyValueTypeImpl
<T
>* wxAnyValueTypeImpl
<T
>::sm_instance
=
314 new wxAnyValueTypeImpl
<T
>();
318 // Helper macro for using same base value type implementation for multiple
319 // actual C++ data types.
321 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
323 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
325 typedef wxAnyBase##CLSTYPE##Type UseDataType; \
327 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
328 virtual ~wxAnyValueTypeImpl() { } \
329 static void SetValue(const T& value, wxAnyValueBuffer& buf) \
331 *(reinterpret_cast<UseDataType*>(&buf.m_buffer[0])) = \
332 static_cast<UseDataType>(value); \
334 static T GetValue(const wxAnyValueBuffer& buf) \
336 return static_cast<T>( \
337 *(reinterpret_cast<const UseDataType*>(&buf.m_buffer[0]))); \
343 // Integer value types
347 typedef wxLongLong_t wxAnyBaseIntType
;
348 typedef wxULongLong_t wxAnyBaseUintType
;
350 typedef long wxAnyBaseIntType
;
351 typedef unsigned long wxAnyBaseUintType
;
355 class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt
:
356 public wxAnyValueTypeImplBase
<wxAnyBaseIntType
>
358 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
360 wxAnyValueTypeImplInt() :
361 wxAnyValueTypeImplBase
<wxAnyBaseIntType
>() { }
362 virtual ~wxAnyValueTypeImplInt() { }
364 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
365 wxAnyValueType
* dstType
,
366 wxAnyValueBuffer
& dst
) const;
370 class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint
:
371 public wxAnyValueTypeImplBase
<wxAnyBaseUintType
>
373 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
375 wxAnyValueTypeImplUint() :
376 wxAnyValueTypeImplBase
<wxAnyBaseUintType
>() { }
377 virtual ~wxAnyValueTypeImplUint() { }
379 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
380 wxAnyValueType
* dstType
,
381 wxAnyValueBuffer
& dst
) const;
385 WX_ANY_DEFINE_SUB_TYPE(signed long, Int
)
386 WX_ANY_DEFINE_SUB_TYPE(signed int, Int
)
387 WX_ANY_DEFINE_SUB_TYPE(signed short, Int
)
388 WX_ANY_DEFINE_SUB_TYPE(signed char, Int
)
390 WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t
, Int
)
393 WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint
)
394 WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint
)
395 WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint
)
396 WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint
)
398 WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t
, Uint
)
405 class WXDLLIMPEXP_BASE wxAnyValueTypeImplString
:
406 public wxAnyValueTypeImplBase
<wxString
>
408 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
410 wxAnyValueTypeImplString() :
411 wxAnyValueTypeImplBase
<wxString
>() { }
412 virtual ~wxAnyValueTypeImplString() { }
415 Convert value into buffer of different type. Return false if
418 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
419 wxAnyValueType
* dstType
,
420 wxAnyValueBuffer
& dst
) const;
425 class wxAnyValueTypeImpl
<wxString
> : public wxAnyValueTypeImplString
428 wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
429 virtual ~wxAnyValueTypeImpl() { }
437 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl
<bool> :
438 public wxAnyValueTypeImplBase
<bool>
440 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
442 wxAnyValueTypeImpl() :
443 wxAnyValueTypeImplBase
<bool>() { }
444 virtual ~wxAnyValueTypeImpl() { }
446 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
447 wxAnyValueType
* dstType
,
448 wxAnyValueBuffer
& dst
) const;
452 // Floating point value type
454 class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble
:
455 public wxAnyValueTypeImplBase
<double>
457 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
459 wxAnyValueTypeImplDouble() :
460 wxAnyValueTypeImplBase
<double>() { }
461 virtual ~wxAnyValueTypeImplDouble() { }
463 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
464 wxAnyValueType
* dstType
,
465 wxAnyValueBuffer
& dst
) const;
468 // WX_ANY_DEFINE_SUB_TYPE requires this
469 typedef double wxAnyBaseDoubleType
;
471 WX_ANY_DEFINE_SUB_TYPE(float, Double
)
472 WX_ANY_DEFINE_SUB_TYPE(double, Double
)
476 // Re-enable useless VC6 warnings
477 #pragma warning (pop)
482 Let's define a discrete Null value so we don't have to really
483 ever check if wxAny.m_type pointer is NULL or not. This is an
484 optimization, mostly. Implementation of this value type is
485 "hidden" in the source file.
487 extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType
*) wxAnyNullValueType
;
491 // We need to implement custom signed/unsigned int equals operators
492 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
493 #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
494 bool operator==(TS value) const \
496 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
497 return (value == static_cast<TS> \
498 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
499 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
500 return (value == static_cast<TS> \
501 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
504 bool operator==(TUS value) const \
506 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
507 return (value == static_cast<TUS> \
508 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
509 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
510 return (value == static_cast<TUS> \
511 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
517 // The wxAny class represents a container for any type. A variant's value
518 // can be changed at run time, possibly to a different type of value.
520 // As standard, wxAny can store value of almost any type, in a fairly
521 // optimal manner even.
531 m_type
= wxAnyNullValueType
;
539 m_type
->DeleteValue(m_buffer
);
544 Various constructors.
546 wxAny(const char* value
)
548 m_type
= wxAnyNullValueType
;
549 Assign(wxString(value
));
551 wxAny(const wchar_t* value
)
553 m_type
= wxAnyNullValueType
;
554 Assign(wxString(value
));
557 wxAny(const wxAny
& any
)
559 m_type
= wxAnyNullValueType
;
564 wxAny(const T
& value
)
566 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
567 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
572 Use this template function for checking if this wxAny holds
573 a specific C++ data type.
575 @remarks This template function does not work on some older compilers
576 (such as Visual C++ 6.0). For full compiler ccompatibility
577 please use wxANY_CHECK_TYPE(any, T) macro instead.
579 @see wxAnyValueType::CheckType()
581 // FIXME-VC6: remove this hack when VC6 is no longer supported
582 template <typename T
>
583 bool CheckType(T
* = NULL
)
585 return m_type
->CheckType
<T
>();
589 Returns the value type as wxAnyValueType instance.
591 @remarks You cannot reliably test whether two wxAnys are of
592 same value type by simply comparing return values
593 of wxAny::GetType(). Instead use
594 wxAnyValueType::CheckType<T>() template function.
596 const wxAnyValueType
* GetType() const
602 Tests if wxAny is null (that is, whether there is data).
606 return (m_type
== wxAnyNullValueType
);
610 Makes wxAny null (that is, clears it).
614 m_type
->DeleteValue(m_buffer
);
615 m_type
= wxAnyNullValueType
;
620 Assignment operators.
622 wxAny
& operator=(const wxAny
&any
)
629 wxAny
& operator=(const T
&value
)
631 m_type
->DeleteValue(m_buffer
);
632 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
633 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
637 wxAny
& operator=(const char* value
)
638 { Assign(wxString(value
)); return *this; }
639 wxAny
& operator=(const wchar_t* value
)
640 { Assign(wxString(value
)); return *this; }
647 bool operator==(const wxString
& value
) const
649 if ( !wxAnyValueTypeImpl
<wxString
>::IsSameClass(m_type
) )
653 static_cast<wxString
>
654 (wxAnyValueTypeImpl
<wxString
>::GetValue(m_buffer
));
657 bool operator==(const char* value
) const
658 { return (*this) == wxString(value
); }
659 bool operator==(const wchar_t* value
) const
660 { return (*this) == wxString(value
); }
663 // We need to implement custom signed/unsigned int equals operators
664 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
665 WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
666 WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
667 WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
668 WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
670 WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t
, wxULongLong_t
)
673 bool operator==(float value
) const
675 if ( !wxAnyValueTypeImpl
<float>::IsSameClass(m_type
) )
680 (wxAnyValueTypeImpl
<float>::GetValue(m_buffer
));
683 bool operator==(double value
) const
685 if ( !wxAnyValueTypeImpl
<double>::IsSameClass(m_type
) )
690 (wxAnyValueTypeImpl
<double>::GetValue(m_buffer
));
693 bool operator==(bool value
) const
695 if ( !wxAnyValueTypeImpl
<bool>::IsSameClass(m_type
) )
698 return value
== (wxAnyValueTypeImpl
<bool>::GetValue(m_buffer
));
705 Inequality operators (implement as template).
708 bool operator!=(const T
& value
) const
709 { return !((*this) == value
); }
713 This template function converts wxAny into given type. No dynamic
714 conversion is performed, so if the type is incorrect an assertion
715 failure will occur in debug builds, and a bogus value is returned
718 @remarks This template function does not work on some older compilers
719 (such as Visual C++ 6.0). For full compiler ccompatibility
720 please use wxANY_AS(any, T) macro instead.
722 // FIXME-VC6: remove this hack when VC6 is no longer supported
724 T
As(T
* = NULL
) const
726 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
728 wxFAIL_MSG("Incorrect or non-convertible data type");
731 return static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
735 Template function that etrieves and converts the value of this
736 variant to the type that T* value is.
738 @return Returns @true if conversion was succesfull.
741 bool GetAs(T
* value
) const
743 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
745 wxAnyValueType
* otherType
=
746 wxAnyValueTypeImpl
<T
>::sm_instance
;
747 wxAnyValueBuffer temp_buf
;
749 if ( !m_type
->ConvertValue(m_buffer
, otherType
, temp_buf
) )
753 static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(temp_buf
));
754 otherType
->DeleteValue(temp_buf
);
758 *value
= static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
763 // Assignment functions
764 void AssignAny(const wxAny
& any
)
766 if ( !any
.m_type
->IsSameType(m_type
) )
768 m_type
->DeleteValue(m_buffer
);
771 m_type
->CopyBuffer(any
.m_buffer
, m_buffer
);
775 void Assign(const T
&value
)
777 m_type
->DeleteValue(m_buffer
);
778 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
779 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
783 wxAnyValueBuffer m_buffer
;
784 wxAnyValueType
* m_type
;
789 // This method of checking the type is compatible with VC6
790 #define wxANY_CHECK_TYPE(any, T) \
791 wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T)
795 // This method of getting the value is compatible with VC6
796 #define wxANY_AS(any, T) \
797 any.As(static_cast<T*>(NULL))
801 inline bool wxAnyValueType
::CheckType(T
* reserved
)
803 wxUnusedVar(reserved
);
804 return wxAnyValueTypeImpl
<T
>::IsSameClass(this);