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. src.m_ptr can
87 be expected to be NULL if value type of previously stored
90 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
91 wxAnyValueBuffer
& dst
) const = 0;
94 Convert value into buffer of different type. Return false if
97 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
98 wxAnyValueType
* dstType
,
99 wxAnyValueBuffer
& dst
) const = 0;
102 Use this template function for checking if wxAnyValueType represents
103 a specific C++ data type.
105 @remarks This template function does not work on some older compilers
106 (such as Visual C++ 6.0). For full compiler ccompatibility
107 please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
110 @see wxAny::CheckType()
112 // FIXME-VC6: remove this hack when VC6 is no longer supported
113 template <typename T
>
114 bool CheckType(T
* reserved
= NULL
);
119 // This method of checking the type is compatible with VC6
120 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
121 wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
123 //valueTypePtr->CheckType(static_cast<T*>(NULL))
127 Helper macro for defining user value types.
129 NB: We really cannot compare sm_classInfo directly in IsSameClass(),
130 but instead call sm_instance->GetClassInfo(). The former technique
131 broke at least on GCC 4.2 (but worked on VC8 shared build).
133 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
134 friend class wxAny; \
136 static void sm_classInfo() {} \
138 virtual wxAnyClassInfo GetClassInfo() const \
140 return sm_classInfo; \
142 static bool IsSameClass(const wxAnyValueType* otherType) \
144 return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \
146 virtual bool IsSameType(const wxAnyValueType* otherType) const \
148 return IsSameClass(otherType); \
151 static CLS* sm_instance; \
153 static wxAnyValueType* GetInstance() \
155 return sm_instance; \
159 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
160 CLS* CLS::sm_instance = new CLS();
164 // "non dll-interface class 'xxx' used as base interface
165 #pragma warning (push)
166 #pragma warning (disable:4275)
170 Following are helper classes for the wxAnyValueTypeImplBase.
176 class wxAnyValueTypeOpsMovable
179 static void DeleteValue(wxAnyValueBuffer
& buf
)
184 static void SetValue(const T
& value
,
185 wxAnyValueBuffer
& buf
)
187 memcpy(buf
.m_buffer
, &value
, sizeof(T
));
190 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
192 return *(reinterpret_cast<const T
*>(&buf
.m_buffer
[0]));
198 class wxAnyValueTypeOpsGeneric
201 template<typename T2
>
205 DataHolder(const T2
& value
)
209 virtual ~DataHolder() { }
213 wxDECLARE_NO_COPY_CLASS(DataHolder
);
216 static void DeleteValue(wxAnyValueBuffer
& buf
)
218 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
222 static void SetValue(const T
& value
,
223 wxAnyValueBuffer
& buf
)
225 DataHolder
<T
>* holder
= new DataHolder
<T
>(value
);
229 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
231 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
232 return holder
->m_value
;
236 } // namespace wxPrivate
240 Intermediate template for the generic value type implementation.
241 We can derive from this same value type for multiple actual types
242 (for instance, we can have wxAnyValueTypeImplInt for all signed
243 integer types), and also easily implement specialized templates
244 with specific dynamic type conversion.
247 class wxAnyValueTypeImplBase
: public wxAnyValueType
249 typedef typename wxIf
< wxIsMovable
<T
>::value
&&
250 sizeof(T
) <= WX_ANY_VALUE_BUFFER_SIZE
,
251 wxPrivate::wxAnyValueTypeOpsMovable
<T
>,
252 wxPrivate::wxAnyValueTypeOpsGeneric
<T
> >::value
256 wxAnyValueTypeImplBase() : wxAnyValueType() { }
257 virtual ~wxAnyValueTypeImplBase() { }
259 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
261 Ops::DeleteValue(buf
);
262 buf
.m_ptr
= NULL
; // This is important
265 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
266 wxAnyValueBuffer
& dst
) const
268 Ops::DeleteValue(dst
);
269 Ops::SetValue(Ops::GetValue(src
), dst
);
273 It is important to reimplement this in any specialized template
274 classes that inherit from wxAnyValueTypeImplBase.
276 static void SetValue(const T
& value
,
277 wxAnyValueBuffer
& buf
)
279 Ops::SetValue(value
, buf
);
283 It is important to reimplement this in any specialized template
284 classes that inherit from wxAnyValueTypeImplBase.
286 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
288 return Ops::GetValue(buf
);
294 Generic value type template. Note that bulk of the implementation
295 resides in wxAnyValueTypeImplBase.
298 class wxAnyValueTypeImpl
: public wxAnyValueTypeImplBase
<T
>
300 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<T
>)
302 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase
<T
>() { }
303 virtual ~wxAnyValueTypeImpl() { }
305 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
306 wxAnyValueType
* dstType
,
307 wxAnyValueBuffer
& dst
) const
310 wxUnusedVar(dstType
);
317 wxAnyValueTypeImpl
<T
>* wxAnyValueTypeImpl
<T
>::sm_instance
=
318 new wxAnyValueTypeImpl
<T
>();
322 // Helper macro for using same base value type implementation for multiple
323 // actual C++ data types.
325 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
327 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
329 typedef wxAnyBase##CLSTYPE##Type UseDataType; \
331 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
332 virtual ~wxAnyValueTypeImpl() { } \
333 static void SetValue(const T& value, wxAnyValueBuffer& buf) \
335 *(reinterpret_cast<UseDataType*>(&buf.m_buffer[0])) = \
336 static_cast<UseDataType>(value); \
338 static T GetValue(const wxAnyValueBuffer& buf) \
340 return static_cast<T>( \
341 *(reinterpret_cast<const UseDataType*>(&buf.m_buffer[0]))); \
347 // Integer value types
351 typedef wxLongLong_t wxAnyBaseIntType
;
352 typedef wxULongLong_t wxAnyBaseUintType
;
354 typedef long wxAnyBaseIntType
;
355 typedef unsigned long wxAnyBaseUintType
;
359 class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt
:
360 public wxAnyValueTypeImplBase
<wxAnyBaseIntType
>
362 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
364 wxAnyValueTypeImplInt() :
365 wxAnyValueTypeImplBase
<wxAnyBaseIntType
>() { }
366 virtual ~wxAnyValueTypeImplInt() { }
368 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
369 wxAnyValueType
* dstType
,
370 wxAnyValueBuffer
& dst
) const;
374 class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint
:
375 public wxAnyValueTypeImplBase
<wxAnyBaseUintType
>
377 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
379 wxAnyValueTypeImplUint() :
380 wxAnyValueTypeImplBase
<wxAnyBaseUintType
>() { }
381 virtual ~wxAnyValueTypeImplUint() { }
383 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
384 wxAnyValueType
* dstType
,
385 wxAnyValueBuffer
& dst
) const;
389 WX_ANY_DEFINE_SUB_TYPE(signed long, Int
)
390 WX_ANY_DEFINE_SUB_TYPE(signed int, Int
)
391 WX_ANY_DEFINE_SUB_TYPE(signed short, Int
)
392 WX_ANY_DEFINE_SUB_TYPE(signed char, Int
)
394 WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t
, Int
)
397 WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint
)
398 WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint
)
399 WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint
)
400 WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint
)
402 WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t
, Uint
)
409 class WXDLLIMPEXP_BASE wxAnyValueTypeImplString
:
410 public wxAnyValueTypeImplBase
<wxString
>
412 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
414 wxAnyValueTypeImplString() :
415 wxAnyValueTypeImplBase
<wxString
>() { }
416 virtual ~wxAnyValueTypeImplString() { }
419 Convert value into buffer of different type. Return false if
422 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
423 wxAnyValueType
* dstType
,
424 wxAnyValueBuffer
& dst
) const;
429 class wxAnyValueTypeImpl
<wxString
> : public wxAnyValueTypeImplString
432 wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
433 virtual ~wxAnyValueTypeImpl() { }
441 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl
<bool> :
442 public wxAnyValueTypeImplBase
<bool>
444 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
446 wxAnyValueTypeImpl() :
447 wxAnyValueTypeImplBase
<bool>() { }
448 virtual ~wxAnyValueTypeImpl() { }
450 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
451 wxAnyValueType
* dstType
,
452 wxAnyValueBuffer
& dst
) const;
456 // Floating point value type
458 class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble
:
459 public wxAnyValueTypeImplBase
<double>
461 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
463 wxAnyValueTypeImplDouble() :
464 wxAnyValueTypeImplBase
<double>() { }
465 virtual ~wxAnyValueTypeImplDouble() { }
467 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
468 wxAnyValueType
* dstType
,
469 wxAnyValueBuffer
& dst
) const;
472 // WX_ANY_DEFINE_SUB_TYPE requires this
473 typedef double wxAnyBaseDoubleType
;
475 WX_ANY_DEFINE_SUB_TYPE(float, Double
)
476 WX_ANY_DEFINE_SUB_TYPE(double, Double
)
480 // Re-enable useless VC6 warnings
481 #pragma warning (pop)
486 Let's define a discrete Null value so we don't have to really
487 ever check if wxAny.m_type pointer is NULL or not. This is an
488 optimization, mostly. Implementation of this value type is
489 "hidden" in the source file.
491 extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType
*) wxAnyNullValueType
;
495 // We need to implement custom signed/unsigned int equals operators
496 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
497 #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
498 bool operator==(TS value) const \
500 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
501 return (value == static_cast<TS> \
502 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
503 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
504 return (value == static_cast<TS> \
505 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
508 bool operator==(TUS value) const \
510 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
511 return (value == static_cast<TUS> \
512 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
513 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
514 return (value == static_cast<TUS> \
515 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
521 // The wxAny class represents a container for any type. A variant's value
522 // can be changed at run time, possibly to a different type of value.
524 // As standard, wxAny can store value of almost any type, in a fairly
525 // optimal manner even.
535 m_type
= wxAnyNullValueType
;
543 m_type
->DeleteValue(m_buffer
);
548 Various constructors.
550 wxAny(const char* value
)
552 m_type
= wxAnyNullValueType
;
553 Assign(wxString(value
));
555 wxAny(const wchar_t* value
)
557 m_type
= wxAnyNullValueType
;
558 Assign(wxString(value
));
561 wxAny(const wxAny
& any
)
563 m_type
= wxAnyNullValueType
;
568 wxAny(const T
& value
)
570 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
571 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
576 Use this template function for checking if this wxAny holds
577 a specific C++ data type.
579 @remarks This template function does not work on some older compilers
580 (such as Visual C++ 6.0). For full compiler ccompatibility
581 please use wxANY_CHECK_TYPE(any, T) macro instead.
583 @see wxAnyValueType::CheckType()
585 // FIXME-VC6: remove this hack when VC6 is no longer supported
586 template <typename T
>
587 bool CheckType(T
* = NULL
)
589 return m_type
->CheckType
<T
>();
593 Returns the value type as wxAnyValueType instance.
595 @remarks You cannot reliably test whether two wxAnys are of
596 same value type by simply comparing return values
597 of wxAny::GetType(). Instead use
598 wxAnyValueType::CheckType<T>() template function.
600 const wxAnyValueType
* GetType() const
606 Tests if wxAny is null (that is, whether there is data).
610 return (m_type
== wxAnyNullValueType
);
614 Makes wxAny null (that is, clears it).
618 m_type
->DeleteValue(m_buffer
);
619 m_type
= wxAnyNullValueType
;
624 Assignment operators.
626 wxAny
& operator=(const wxAny
&any
)
633 wxAny
& operator=(const T
&value
)
635 m_type
->DeleteValue(m_buffer
);
636 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
637 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
641 wxAny
& operator=(const char* value
)
642 { Assign(wxString(value
)); return *this; }
643 wxAny
& operator=(const wchar_t* value
)
644 { Assign(wxString(value
)); return *this; }
651 bool operator==(const wxString
& value
) const
653 if ( !wxAnyValueTypeImpl
<wxString
>::IsSameClass(m_type
) )
657 static_cast<wxString
>
658 (wxAnyValueTypeImpl
<wxString
>::GetValue(m_buffer
));
661 bool operator==(const char* value
) const
662 { return (*this) == wxString(value
); }
663 bool operator==(const wchar_t* value
) const
664 { return (*this) == wxString(value
); }
667 // We need to implement custom signed/unsigned int equals operators
668 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
669 WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
670 WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
671 WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
672 WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
674 WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t
, wxULongLong_t
)
677 bool operator==(float value
) const
679 if ( !wxAnyValueTypeImpl
<float>::IsSameClass(m_type
) )
684 (wxAnyValueTypeImpl
<float>::GetValue(m_buffer
));
687 bool operator==(double value
) const
689 if ( !wxAnyValueTypeImpl
<double>::IsSameClass(m_type
) )
694 (wxAnyValueTypeImpl
<double>::GetValue(m_buffer
));
697 bool operator==(bool value
) const
699 if ( !wxAnyValueTypeImpl
<bool>::IsSameClass(m_type
) )
702 return value
== (wxAnyValueTypeImpl
<bool>::GetValue(m_buffer
));
709 Inequality operators (implement as template).
712 bool operator!=(const T
& value
) const
713 { return !((*this) == value
); }
717 This template function converts wxAny into given type. No dynamic
718 conversion is performed, so if the type is incorrect an assertion
719 failure will occur in debug builds, and a bogus value is returned
722 @remarks This template function does not work on some older compilers
723 (such as Visual C++ 6.0). For full compiler ccompatibility
724 please use wxANY_AS(any, T) macro instead.
726 // FIXME-VC6: remove this hack when VC6 is no longer supported
728 T
As(T
* = NULL
) const
730 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
732 wxFAIL_MSG("Incorrect or non-convertible data type");
735 return static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
739 Template function that etrieves and converts the value of this
740 variant to the type that T* value is.
742 @return Returns @true if conversion was succesfull.
745 bool GetAs(T
* value
) const
747 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
749 wxAnyValueType
* otherType
=
750 wxAnyValueTypeImpl
<T
>::sm_instance
;
751 wxAnyValueBuffer temp_buf
;
753 if ( !m_type
->ConvertValue(m_buffer
, otherType
, temp_buf
) )
757 static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(temp_buf
));
758 otherType
->DeleteValue(temp_buf
);
762 *value
= static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
767 // Assignment functions
768 void AssignAny(const wxAny
& any
)
770 if ( !any
.m_type
->IsSameType(m_type
) )
772 m_type
->DeleteValue(m_buffer
);
775 m_type
->CopyBuffer(any
.m_buffer
, m_buffer
);
779 void Assign(const T
&value
)
781 m_type
->DeleteValue(m_buffer
);
782 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
783 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
787 wxAnyValueBuffer m_buffer
;
788 wxAnyValueType
* m_type
;
793 // This method of checking the type is compatible with VC6
794 #define wxANY_CHECK_TYPE(any, T) \
795 wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T)
799 // This method of getting the value is compatible with VC6
800 #define wxANY_AS(any, T) \
801 any.As(static_cast<T*>(NULL))
805 inline bool wxAnyValueType::CheckType(T
* reserved
)
807 wxUnusedVar(reserved
);
808 return wxAnyValueTypeImpl
<T
>::IsSameClass(this);