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
33 wxByte m_buffer
[WX_ANY_VALUE_BUFFER_SIZE
];
36 typedef void (*wxAnyClassInfo
)();
40 // wxAnyValueType is base class for value type functionality for C++ data
41 // types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
42 // will create a satisfactory wxAnyValueType implementation for a data type.
44 class WXDLLIMPEXP_BASE wxAnyValueType
55 virtual ~wxAnyValueType()
60 This function is used for internal type matching.
62 virtual wxAnyClassInfo
GetClassInfo() const = 0;
65 This function is used for internal type matching.
67 virtual bool IsSameType(const wxAnyValueType
* otherType
) const = 0;
70 This function is called every time the data in wxAny
71 buffer needs to be freed.
73 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const = 0;
76 Implement this for buffer-to-buffer copy. src.m_ptr can
77 be expected to be NULL if value type of previously stored
80 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
81 wxAnyValueBuffer
& dst
) const = 0;
84 Convert value into buffer of different type. Return false if
87 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
88 wxAnyValueType
* dstType
,
89 wxAnyValueBuffer
& dst
) const = 0;
92 Use this template function for checking if wxAnyValueType represents
93 a specific C++ data type.
95 @remarks This template function does not work on some older compilers
96 (such as Visual C++ 6.0). For full compiler ccompatibility
97 please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
100 @see wxAny::CheckType()
102 // FIXME-VC6: remove this hack when VC6 is no longer supported
103 template <typename T
>
104 bool CheckType(T
* reserved
= NULL
);
109 // This method of checking the type is compatible with VC6
110 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
111 wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
113 //valueTypePtr->CheckType(static_cast<T*>(NULL))
117 Helper macro for defining user value types.
119 NB: We really cannot compare sm_classInfo directly in IsSameClass(),
120 but instead call sm_instance->GetClassInfo(). The former technique
121 broke at least on GCC 4.2 (but worked on VC8 shared build).
123 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
124 friend class wxAny; \
126 static void sm_classInfo() {} \
128 virtual wxAnyClassInfo GetClassInfo() const \
130 return sm_classInfo; \
132 static bool IsSameClass(const wxAnyValueType* otherType) \
134 return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \
136 virtual bool IsSameType(const wxAnyValueType* otherType) const \
138 return IsSameClass(otherType); \
141 static CLS* sm_instance; \
143 static wxAnyValueType* GetInstance() \
145 return sm_instance; \
149 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
150 CLS* CLS::sm_instance = new CLS();
154 // "non dll-interface class 'xxx' used as base interface
155 #pragma warning (push)
156 #pragma warning (disable:4275)
160 Following are helper classes for the wxAnyValueTypeImplBase.
166 class wxAnyValueTypeOpsMovable
169 static void DeleteValue(wxAnyValueBuffer
& buf
)
174 static void SetValue(const T
& value
,
175 wxAnyValueBuffer
& buf
)
177 memcpy(buf
.m_buffer
, &value
, sizeof(T
));
180 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
182 return *(reinterpret_cast<const T
*>(&buf
.m_buffer
[0]));
188 class wxAnyValueTypeOpsGeneric
191 template<typename T2
>
195 DataHolder(const T2
& value
)
199 virtual ~DataHolder() { }
203 wxDECLARE_NO_COPY_CLASS(DataHolder
);
206 static void DeleteValue(wxAnyValueBuffer
& buf
)
208 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
212 static void SetValue(const T
& value
,
213 wxAnyValueBuffer
& buf
)
215 DataHolder
<T
>* holder
= new DataHolder
<T
>(value
);
219 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
221 DataHolder
<T
>* holder
= static_cast<DataHolder
<T
>*>(buf
.m_ptr
);
222 return holder
->m_value
;
226 } // namespace wxPrivate
230 Intermediate template for the generic value type implementation.
231 We can derive from this same value type for multiple actual types
232 (for instance, we can have wxAnyValueTypeImplInt for all signed
233 integer types), and also easily implement specialized templates
234 with specific dynamic type conversion.
237 class wxAnyValueTypeImplBase
: public wxAnyValueType
239 typedef typename wxIf
< wxIsMovable
<T
>::value
&&
240 sizeof(T
) <= WX_ANY_VALUE_BUFFER_SIZE
,
241 wxPrivate::wxAnyValueTypeOpsMovable
<T
>,
242 wxPrivate::wxAnyValueTypeOpsGeneric
<T
> >::value
246 wxAnyValueTypeImplBase() : wxAnyValueType() { }
247 virtual ~wxAnyValueTypeImplBase() { }
249 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
251 Ops::DeleteValue(buf
);
252 buf
.m_ptr
= NULL
; // This is important
255 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
256 wxAnyValueBuffer
& dst
) const
258 Ops::DeleteValue(dst
);
259 Ops::SetValue(Ops::GetValue(src
), dst
);
263 It is important to reimplement this in any specialized template
264 classes that inherit from wxAnyValueTypeImplBase.
266 static void SetValue(const T
& value
,
267 wxAnyValueBuffer
& buf
)
269 Ops::SetValue(value
, buf
);
273 It is important to reimplement this in any specialized template
274 classes that inherit from wxAnyValueTypeImplBase.
276 static const T
& GetValue(const wxAnyValueBuffer
& buf
)
278 return Ops::GetValue(buf
);
284 Generic value type template. Note that bulk of the implementation
285 resides in wxAnyValueTypeImplBase.
288 class wxAnyValueTypeImpl
: public wxAnyValueTypeImplBase
<T
>
290 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<T
>)
292 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase
<T
>() { }
293 virtual ~wxAnyValueTypeImpl() { }
295 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
296 wxAnyValueType
* dstType
,
297 wxAnyValueBuffer
& dst
) const
300 wxUnusedVar(dstType
);
307 wxAnyValueTypeImpl
<T
>* wxAnyValueTypeImpl
<T
>::sm_instance
=
308 new wxAnyValueTypeImpl
<T
>();
312 // Helper macro for using same base value type implementation for multiple
313 // actual C++ data types.
315 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
317 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
319 typedef wxAnyBase##CLSTYPE##Type UseDataType; \
321 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
322 virtual ~wxAnyValueTypeImpl() { } \
323 static void SetValue(const T& value, wxAnyValueBuffer& buf) \
325 *(reinterpret_cast<UseDataType*>(&buf.m_buffer[0])) = \
326 static_cast<UseDataType>(value); \
328 static T GetValue(const wxAnyValueBuffer& buf) \
330 return static_cast<T>( \
331 *(reinterpret_cast<const UseDataType*>(&buf.m_buffer[0]))); \
337 // Integer value types
341 typedef wxLongLong_t wxAnyBaseIntType
;
342 typedef wxULongLong_t wxAnyBaseUintType
;
344 typedef long wxAnyBaseIntType
;
345 typedef unsigned long wxAnyBaseUintType
;
349 class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt
:
350 public wxAnyValueTypeImplBase
<wxAnyBaseIntType
>
352 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
354 wxAnyValueTypeImplInt() :
355 wxAnyValueTypeImplBase
<wxAnyBaseIntType
>() { }
356 virtual ~wxAnyValueTypeImplInt() { }
358 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
359 wxAnyValueType
* dstType
,
360 wxAnyValueBuffer
& dst
) const;
364 class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint
:
365 public wxAnyValueTypeImplBase
<wxAnyBaseUintType
>
367 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
369 wxAnyValueTypeImplUint() :
370 wxAnyValueTypeImplBase
<wxAnyBaseUintType
>() { }
371 virtual ~wxAnyValueTypeImplUint() { }
373 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
374 wxAnyValueType
* dstType
,
375 wxAnyValueBuffer
& dst
) const;
379 WX_ANY_DEFINE_SUB_TYPE(signed long, Int
)
380 WX_ANY_DEFINE_SUB_TYPE(signed int, Int
)
381 WX_ANY_DEFINE_SUB_TYPE(signed short, Int
)
382 WX_ANY_DEFINE_SUB_TYPE(signed char, Int
)
384 WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t
, Int
)
387 WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint
)
388 WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint
)
389 WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint
)
390 WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint
)
392 WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t
, Uint
)
399 class WXDLLIMPEXP_BASE wxAnyValueTypeImplString
:
400 public wxAnyValueTypeImplBase
<wxString
>
402 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
404 wxAnyValueTypeImplString() :
405 wxAnyValueTypeImplBase
<wxString
>() { }
406 virtual ~wxAnyValueTypeImplString() { }
409 Convert value into buffer of different type. Return false if
412 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
413 wxAnyValueType
* dstType
,
414 wxAnyValueBuffer
& dst
) const;
419 class wxAnyValueTypeImpl
<wxString
> : public wxAnyValueTypeImplString
422 wxAnyValueTypeImpl() : wxAnyValueTypeImplString() { }
423 virtual ~wxAnyValueTypeImpl() { }
431 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl
<bool> :
432 public wxAnyValueTypeImplBase
<bool>
434 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
436 wxAnyValueTypeImpl() :
437 wxAnyValueTypeImplBase
<bool>() { }
438 virtual ~wxAnyValueTypeImpl() { }
440 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
441 wxAnyValueType
* dstType
,
442 wxAnyValueBuffer
& dst
) const;
446 // Floating point value type
448 class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble
:
449 public wxAnyValueTypeImplBase
<double>
451 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
453 wxAnyValueTypeImplDouble() :
454 wxAnyValueTypeImplBase
<double>() { }
455 virtual ~wxAnyValueTypeImplDouble() { }
457 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
458 wxAnyValueType
* dstType
,
459 wxAnyValueBuffer
& dst
) const;
462 // WX_ANY_DEFINE_SUB_TYPE requires this
463 typedef double wxAnyBaseDoubleType
;
465 WX_ANY_DEFINE_SUB_TYPE(float, Double
)
466 WX_ANY_DEFINE_SUB_TYPE(double, Double
)
470 // Re-enable useless VC6 warnings
471 #pragma warning (pop)
476 Let's define a discrete Null value so we don't have to really
477 ever check if wxAny.m_type pointer is NULL or not. This is an
478 optimization, mostly. Implementation of this value type is
479 "hidden" in the source file.
481 extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType
*) wxAnyNullValueType
;
485 // We need to implement custom signed/unsigned int equals operators
486 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
487 #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
488 bool operator==(TS value) const \
490 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
491 return (value == static_cast<TS> \
492 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
493 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
494 return (value == static_cast<TS> \
495 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
498 bool operator==(TUS value) const \
500 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
501 return (value == static_cast<TUS> \
502 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
503 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
504 return (value == static_cast<TUS> \
505 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
511 // The wxAny class represents a container for any type. A variant's value
512 // can be changed at run time, possibly to a different type of value.
514 // As standard, wxAny can store value of almost any type, in a fairly
515 // optimal manner even.
525 m_type
= wxAnyNullValueType
;
533 m_type
->DeleteValue(m_buffer
);
538 Various constructors.
540 wxAny(const char* value
)
542 m_type
= wxAnyNullValueType
;
543 Assign(wxString(value
));
545 wxAny(const wchar_t* value
)
547 m_type
= wxAnyNullValueType
;
548 Assign(wxString(value
));
551 wxAny(const wxAny
& any
)
553 m_type
= wxAnyNullValueType
;
558 wxAny(const T
& value
)
560 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
561 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
566 Use this template function for checking if this wxAny holds
567 a specific C++ data type.
569 @remarks This template function does not work on some older compilers
570 (such as Visual C++ 6.0). For full compiler ccompatibility
571 please use wxANY_CHECK_TYPE(any, T) macro instead.
573 @see wxAnyValueType::CheckType()
575 // FIXME-VC6: remove this hack when VC6 is no longer supported
576 template <typename T
>
577 bool CheckType(T
* = NULL
)
579 return m_type
->CheckType
<T
>();
583 Returns the value type as wxAnyValueType instance.
585 @remarks You cannot reliably test whether two wxAnys are of
586 same value type by simply comparing return values
587 of wxAny::GetType(). Instead use
588 wxAnyValueType::CheckType<T>() template function.
590 const wxAnyValueType
* GetType() const
596 Tests if wxAny is null (that is, whether there is data).
600 return (m_type
== wxAnyNullValueType
);
604 Makes wxAny null (that is, clears it).
608 m_type
->DeleteValue(m_buffer
);
609 m_type
= wxAnyNullValueType
;
614 Assignment operators.
616 wxAny
& operator=(const wxAny
&any
)
623 wxAny
& operator=(const T
&value
)
625 m_type
->DeleteValue(m_buffer
);
626 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
627 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
631 wxAny
& operator=(const char* value
)
632 { Assign(wxString(value
)); return *this; }
633 wxAny
& operator=(const wchar_t* value
)
634 { Assign(wxString(value
)); return *this; }
641 bool operator==(const wxString
& value
) const
643 if ( !wxAnyValueTypeImpl
<wxString
>::IsSameClass(m_type
) )
647 static_cast<wxString
>
648 (wxAnyValueTypeImpl
<wxString
>::GetValue(m_buffer
));
651 bool operator==(const char* value
) const
652 { return (*this) == wxString(value
); }
653 bool operator==(const wchar_t* value
) const
654 { return (*this) == wxString(value
); }
657 // We need to implement custom signed/unsigned int equals operators
658 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
659 WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
660 WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
661 WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
662 WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
664 WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t
, wxULongLong_t
)
667 bool operator==(float value
) const
669 if ( !wxAnyValueTypeImpl
<float>::IsSameClass(m_type
) )
674 (wxAnyValueTypeImpl
<float>::GetValue(m_buffer
));
677 bool operator==(double value
) const
679 if ( !wxAnyValueTypeImpl
<double>::IsSameClass(m_type
) )
684 (wxAnyValueTypeImpl
<double>::GetValue(m_buffer
));
687 bool operator==(bool value
) const
689 if ( !wxAnyValueTypeImpl
<bool>::IsSameClass(m_type
) )
692 return value
== (wxAnyValueTypeImpl
<bool>::GetValue(m_buffer
));
699 Inequality operators (implement as template).
702 bool operator!=(const T
& value
) const
703 { return !((*this) == value
); }
707 This template function converts wxAny into given type. No dynamic
708 conversion is performed, so if the type is incorrect an assertion
709 failure will occur in debug builds, and a bogus value is returned
712 @remarks This template function does not work on some older compilers
713 (such as Visual C++ 6.0). For full compiler ccompatibility
714 please use wxANY_AS(any, T) macro instead.
716 // FIXME-VC6: remove this hack when VC6 is no longer supported
718 T
As(T
* = NULL
) const
720 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
722 wxFAIL_MSG("Incorrect or non-convertible data type");
725 return static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
729 Template function that etrieves and converts the value of this
730 variant to the type that T* value is.
732 @return Returns @true if conversion was succesfull.
735 bool GetAs(T
* value
) const
737 if ( !wxAnyValueTypeImpl
<T
>::IsSameClass(m_type
) )
739 wxAnyValueType
* otherType
=
740 wxAnyValueTypeImpl
<T
>::sm_instance
;
741 wxAnyValueBuffer temp_buf
;
743 if ( !m_type
->ConvertValue(m_buffer
, otherType
, temp_buf
) )
747 static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(temp_buf
));
748 otherType
->DeleteValue(temp_buf
);
752 *value
= static_cast<T
>(wxAnyValueTypeImpl
<T
>::GetValue(m_buffer
));
757 // Assignment functions
758 void AssignAny(const wxAny
& any
)
760 if ( !any
.m_type
->IsSameType(m_type
) )
762 m_type
->DeleteValue(m_buffer
);
765 m_type
->CopyBuffer(any
.m_buffer
, m_buffer
);
769 void Assign(const T
&value
)
771 m_type
->DeleteValue(m_buffer
);
772 m_type
= wxAnyValueTypeImpl
<T
>::sm_instance
;
773 wxAnyValueTypeImpl
<T
>::SetValue(value
, m_buffer
);
777 wxAnyValueType
* m_type
;
778 wxAnyValueBuffer m_buffer
;
783 // This method of checking the type is compatible with VC6
784 #define wxANY_CHECK_TYPE(any, T) \
785 wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T)
789 // This method of getting the value is compatible with VC6
790 #define wxANY_AS(any, T) \
791 any.As(static_cast<T*>(NULL))
795 inline bool wxAnyValueType::CheckType(T
* reserved
)
797 wxUnusedVar(reserved
);
798 return wxAnyValueTypeImpl
<T
>::IsSameClass(this);