]> git.saurik.com Git - wxWidgets.git/blob - include/wx/any.h
more avoiding direct struct access
[wxWidgets.git] / include / wx / any.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/any.h
3 // Purpose: wxAny class
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: 07/05/2009
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_ANY_H_
13 #define _WX_ANY_H_
14
15 #include "wx/defs.h"
16
17 #if wxUSE_ANY
18
19 #include <new> // for placement new
20 #include "wx/string.h"
21 #include "wx/meta/if.h"
22 #include "wx/typeinfo.h"
23 #include "wx/list.h"
24
25 // Size of the wxAny value buffer.
26 enum
27 {
28 WX_ANY_VALUE_BUFFER_SIZE = 16
29 };
30
31 union wxAnyValueBuffer
32 {
33 union Alignment
34 {
35 #if wxHAS_INT64
36 wxInt64 m_int64;
37 #endif
38 long double m_longDouble;
39 void ( *m_funcPtr )(void);
40 void ( wxAnyValueBuffer::*m_mFuncPtr )(void);
41 } m_alignment;
42
43 void* m_ptr;
44 wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE];
45 };
46
47 //
48 // wxAnyValueType is base class for value type functionality for C++ data
49 // types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
50 // will create a satisfactory wxAnyValueType implementation for a data type.
51 //
52 class WXDLLIMPEXP_BASE wxAnyValueType
53 {
54 WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType)
55 public:
56 /**
57 Default constructor.
58 */
59 wxAnyValueType()
60 {
61 }
62
63 /**
64 Destructor.
65 */
66 virtual ~wxAnyValueType()
67 {
68 }
69
70 /**
71 This function is used for internal type matching.
72 */
73 virtual bool IsSameType(const wxAnyValueType* otherType) const = 0;
74
75 /**
76 This function is called every time the data in wxAny
77 buffer needs to be freed.
78 */
79 virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0;
80
81 /**
82 Implement this for buffer-to-buffer copy.
83
84 @param src
85 This is the source data buffer.
86
87 @param dst
88 This is the destination data buffer that is in either
89 uninitialized or freed state.
90 */
91 virtual void CopyBuffer(const wxAnyValueBuffer& src,
92 wxAnyValueBuffer& dst) const = 0;
93
94 /**
95 Convert value into buffer of different type. Return false if
96 not possible.
97 */
98 virtual bool ConvertValue(const wxAnyValueBuffer& src,
99 wxAnyValueType* dstType,
100 wxAnyValueBuffer& dst) const = 0;
101
102 /**
103 Use this template function for checking if wxAnyValueType represents
104 a specific C++ data type.
105
106 @remarks This template function does not work on some older compilers
107 (such as Visual C++ 6.0). For full compiler compatibility
108 please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro
109 instead.
110
111 @see wxAny::CheckType()
112 */
113 // FIXME-VC6: remove this hack when VC6 is no longer supported
114 template <typename T>
115 bool CheckType(T* reserved = NULL) const;
116
117 #if wxUSE_EXTENDED_RTTI
118 virtual const wxTypeInfo* GetTypeInfo() const = 0;
119 #endif
120 private:
121 };
122
123
124 //
125 // We need to allocate wxAnyValueType instances in heap, and need to use
126 // scoped ptr to properly deallocate them in dynamic library use cases.
127 // Here we have a minimal specialized scoped ptr implementation to deal
128 // with various compiler-specific problems with template class' static
129 // member variable of template type with explicit constructor which
130 // is initialized in global scope.
131 //
132 class wxAnyValueTypeScopedPtr
133 {
134 public:
135 wxAnyValueTypeScopedPtr(wxAnyValueType* ptr) : m_ptr(ptr) { }
136 ~wxAnyValueTypeScopedPtr() { delete m_ptr; }
137 wxAnyValueType* get() const { return m_ptr; }
138 private:
139 wxAnyValueType* m_ptr;
140 };
141
142
143 //
144 // This method of checking the type is compatible with VC6
145 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
146 wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
147
148
149 /**
150 Helper macro for defining user value types.
151
152 Even though C++ RTTI would be fully available to use, we'd have to to
153 facilitate sub-type system which allows, for instance, wxAny with
154 signed short '15' to be treated equal to wxAny with signed long long '15'.
155 Having sm_instance is important here.
156
157 NB: We really need to have wxAnyValueType instances allocated
158 in heap. They are stored as static template member variables,
159 and with them we just can't be too careful (eg. not allocating
160 them in heap broke the type identification in GCC).
161 */
162 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
163 friend class wxAny; \
164 WX_DECLARE_TYPEINFO_INLINE(CLS) \
165 public: \
166 static bool IsSameClass(const wxAnyValueType* otherType) \
167 { \
168 return wxTypeId(*sm_instance.get()) == wxTypeId(*otherType); \
169 } \
170 virtual bool IsSameType(const wxAnyValueType* otherType) const \
171 { \
172 return IsSameClass(otherType); \
173 } \
174 private: \
175 static wxAnyValueTypeScopedPtr sm_instance; \
176 public: \
177 static wxAnyValueType* GetInstance() \
178 { \
179 return sm_instance.get(); \
180 }
181
182
183 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
184 wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS());
185
186
187 #ifdef __VISUALC6__
188 // "non dll-interface class 'xxx' used as base interface
189 #pragma warning (push)
190 #pragma warning (disable:4275)
191 #endif
192
193 /**
194 Following are helper classes for the wxAnyValueTypeImplBase.
195 */
196 namespace wxPrivate
197 {
198
199 template<typename T>
200 class wxAnyValueTypeOpsInplace
201 {
202 public:
203 static void DeleteValue(wxAnyValueBuffer& buf)
204 {
205 T* value = reinterpret_cast<T*>(&buf.m_buffer[0]);
206 value->~T();
207
208 // Some compiler may given 'unused variable' warnings without this
209 wxUnusedVar(value);
210 }
211
212 static void SetValue(const T& value,
213 wxAnyValueBuffer& buf)
214 {
215 // Use placement new
216 void* const place = buf.m_buffer;
217 ::new(place) T(value);
218 }
219
220 static const T& GetValue(const wxAnyValueBuffer& buf)
221 {
222 // Breaking this code into two lines should suppress
223 // GCC's 'type-punned pointer will break strict-aliasing rules'
224 // warning.
225 const T* value = reinterpret_cast<const T*>(&buf.m_buffer[0]);
226 return *value;
227 }
228 };
229
230
231 template<typename T>
232 class wxAnyValueTypeOpsGeneric
233 {
234 public:
235 template<typename T2>
236 class DataHolder
237 {
238 public:
239 DataHolder(const T2& value)
240 {
241 m_value = value;
242 }
243 virtual ~DataHolder() { }
244
245 T2 m_value;
246 private:
247 wxDECLARE_NO_COPY_CLASS(DataHolder);
248 };
249
250 static void DeleteValue(wxAnyValueBuffer& buf)
251 {
252 DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr);
253 delete holder;
254 }
255
256 static void SetValue(const T& value,
257 wxAnyValueBuffer& buf)
258 {
259 DataHolder<T>* holder = new DataHolder<T>(value);
260 buf.m_ptr = holder;
261 }
262
263 static const T& GetValue(const wxAnyValueBuffer& buf)
264 {
265 DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr);
266 return holder->m_value;
267 }
268 };
269
270 } // namespace wxPrivate
271
272
273 /**
274 Intermediate template for the generic value type implementation.
275 We can derive from this same value type for multiple actual types
276 (for instance, we can have wxAnyValueTypeImplInt for all signed
277 integer types), and also easily implement specialized templates
278 with specific dynamic type conversion.
279 */
280 template<typename T>
281 class wxAnyValueTypeImplBase : public wxAnyValueType
282 {
283 typedef typename wxIf< sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE,
284 wxPrivate::wxAnyValueTypeOpsInplace<T>,
285 wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value
286 Ops;
287
288 public:
289 wxAnyValueTypeImplBase() : wxAnyValueType() { }
290 virtual ~wxAnyValueTypeImplBase() { }
291
292 virtual void DeleteValue(wxAnyValueBuffer& buf) const
293 {
294 Ops::DeleteValue(buf);
295 }
296
297 virtual void CopyBuffer(const wxAnyValueBuffer& src,
298 wxAnyValueBuffer& dst) const
299 {
300 Ops::SetValue(Ops::GetValue(src), dst);
301 }
302
303 /**
304 It is important to reimplement this in any specialized template
305 classes that inherit from wxAnyValueTypeImplBase.
306 */
307 static void SetValue(const T& value,
308 wxAnyValueBuffer& buf)
309 {
310 Ops::SetValue(value, buf);
311 }
312
313 /**
314 It is important to reimplement this in any specialized template
315 classes that inherit from wxAnyValueTypeImplBase.
316 */
317 static const T& GetValue(const wxAnyValueBuffer& buf)
318 {
319 return Ops::GetValue(buf);
320 }
321 #if wxUSE_EXTENDED_RTTI
322 virtual const wxTypeInfo* GetTypeInfo() const
323 {
324 return wxGetTypeInfo((T*)NULL);
325 }
326 #endif
327 };
328
329
330 /*
331 Generic value type template. Note that bulk of the implementation
332 resides in wxAnyValueTypeImplBase.
333 */
334 template<typename T>
335 class wxAnyValueTypeImpl : public wxAnyValueTypeImplBase<T>
336 {
337 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<T>)
338 public:
339 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase<T>() { }
340 virtual ~wxAnyValueTypeImpl() { }
341
342 virtual bool ConvertValue(const wxAnyValueBuffer& src,
343 wxAnyValueType* dstType,
344 wxAnyValueBuffer& dst) const
345 {
346 wxUnusedVar(src);
347 wxUnusedVar(dstType);
348 wxUnusedVar(dst);
349 return false;
350 }
351 };
352
353 template<typename T>
354 wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>();
355
356
357 //
358 // Helper macro for using same base value type implementation for multiple
359 // actual C++ data types.
360 //
361 #define _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
362 template<> \
363 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
364 { \
365 typedef wxAnyBase##CLSTYPE##Type UseDataType; \
366 public: \
367 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \
368 virtual ~wxAnyValueTypeImpl() { } \
369 static void SetValue(const T& value, wxAnyValueBuffer& buf) \
370 { \
371 void* voidPtr = reinterpret_cast<void*>(&buf.m_buffer[0]); \
372 UseDataType* dptr = reinterpret_cast<UseDataType*>(voidPtr); \
373 *dptr = static_cast<UseDataType>(value); \
374 } \
375 static T GetValue(const wxAnyValueBuffer& buf) \
376 { \
377 const void* voidPtr = \
378 reinterpret_cast<const void*>(&buf.m_buffer[0]); \
379 const UseDataType* sptr = \
380 reinterpret_cast<const UseDataType*>(voidPtr); \
381 return static_cast<T>(*sptr); \
382 }
383
384 #if wxUSE_EXTENDED_RTTI
385 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
386 _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\
387 virtual const wxTypeInfo* GetTypeInfo() const \
388 { \
389 return wxGetTypeInfo((T*)NULL); \
390 } \
391 };
392 #else
393 #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \
394 _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\
395 };
396 #endif
397
398 //
399 // Integer value types
400 //
401
402 #ifdef wxLongLong_t
403 typedef wxLongLong_t wxAnyBaseIntType;
404 typedef wxULongLong_t wxAnyBaseUintType;
405 #else
406 typedef long wxAnyBaseIntType;
407 typedef unsigned long wxAnyBaseUintType;
408 #endif
409
410
411 class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt :
412 public wxAnyValueTypeImplBase<wxAnyBaseIntType>
413 {
414 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
415 public:
416 wxAnyValueTypeImplInt() :
417 wxAnyValueTypeImplBase<wxAnyBaseIntType>() { }
418 virtual ~wxAnyValueTypeImplInt() { }
419
420 virtual bool ConvertValue(const wxAnyValueBuffer& src,
421 wxAnyValueType* dstType,
422 wxAnyValueBuffer& dst) const;
423 };
424
425
426 class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint :
427 public wxAnyValueTypeImplBase<wxAnyBaseUintType>
428 {
429 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
430 public:
431 wxAnyValueTypeImplUint() :
432 wxAnyValueTypeImplBase<wxAnyBaseUintType>() { }
433 virtual ~wxAnyValueTypeImplUint() { }
434
435 virtual bool ConvertValue(const wxAnyValueBuffer& src,
436 wxAnyValueType* dstType,
437 wxAnyValueBuffer& dst) const;
438 };
439
440
441 WX_ANY_DEFINE_SUB_TYPE(signed long, Int)
442 WX_ANY_DEFINE_SUB_TYPE(signed int, Int)
443 WX_ANY_DEFINE_SUB_TYPE(signed short, Int)
444 WX_ANY_DEFINE_SUB_TYPE(signed char, Int)
445 #ifdef wxLongLong_t
446 WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t, Int)
447 #endif
448
449 WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint)
450 WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint)
451 WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint)
452 WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint)
453 #ifdef wxLongLong_t
454 WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t, Uint)
455 #endif
456
457
458 //
459 // This macro is used in header, but then in source file we must have:
460 // WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME)
461 //
462 #define _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, GV) \
463 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl##TYPENAME : \
464 public wxAnyValueTypeImplBase<T> \
465 { \
466 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME) \
467 public: \
468 wxAnyValueTypeImpl##TYPENAME() : \
469 wxAnyValueTypeImplBase<T>() { } \
470 virtual ~wxAnyValueTypeImpl##TYPENAME() { } \
471 virtual bool ConvertValue(const wxAnyValueBuffer& src, \
472 wxAnyValueType* dstType, \
473 wxAnyValueBuffer& dst) const \
474 { \
475 GV value = GetValue(src); \
476 return CONVFUNC(value, dstType, dst); \
477 } \
478 }; \
479 template<> \
480 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##TYPENAME \
481 { \
482 public: \
483 wxAnyValueTypeImpl() : wxAnyValueTypeImpl##TYPENAME() { } \
484 virtual ~wxAnyValueTypeImpl() { } \
485 };
486
487 #define WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \
488 _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \
489
490 #define WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(T, TYPENAME, CONVFUNC) \
491 _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, \
492 CONVFUNC, const T&) \
493
494 //
495 // String value type
496 //
497
498 // Convert wxString to destination wxAny value type
499 extern WXDLLIMPEXP_BASE bool wxAnyConvertString(const wxString& value,
500 wxAnyValueType* dstType,
501 wxAnyValueBuffer& dst);
502
503 WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(wxString, wxString, wxAnyConvertString)
504 WX_ANY_DEFINE_CONVERTIBLE_TYPE(const char*, ConstCharPtr,
505 wxAnyConvertString, wxString)
506 WX_ANY_DEFINE_CONVERTIBLE_TYPE(const wchar_t*, ConstWchar_tPtr,
507 wxAnyConvertString, wxString)
508
509 //
510 // Bool value type
511 //
512 template<>
513 class WXDLLIMPEXP_BASE wxAnyValueTypeImpl<bool> :
514 public wxAnyValueTypeImplBase<bool>
515 {
516 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
517 public:
518 wxAnyValueTypeImpl() :
519 wxAnyValueTypeImplBase<bool>() { }
520 virtual ~wxAnyValueTypeImpl() { }
521
522 virtual bool ConvertValue(const wxAnyValueBuffer& src,
523 wxAnyValueType* dstType,
524 wxAnyValueBuffer& dst) const;
525 };
526
527 //
528 // Floating point value type
529 //
530 class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble :
531 public wxAnyValueTypeImplBase<double>
532 {
533 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
534 public:
535 wxAnyValueTypeImplDouble() :
536 wxAnyValueTypeImplBase<double>() { }
537 virtual ~wxAnyValueTypeImplDouble() { }
538
539 virtual bool ConvertValue(const wxAnyValueBuffer& src,
540 wxAnyValueType* dstType,
541 wxAnyValueBuffer& dst) const;
542 };
543
544 // WX_ANY_DEFINE_SUB_TYPE requires this
545 typedef double wxAnyBaseDoubleType;
546
547 WX_ANY_DEFINE_SUB_TYPE(float, Double)
548 WX_ANY_DEFINE_SUB_TYPE(double, Double)
549
550
551 //
552 // Defines a dummy wxAnyValueTypeImpl<> with given export
553 // declaration. This is needed if a class is used with
554 // wxAny in both user shared library and application.
555 //
556 #define wxDECLARE_ANY_TYPE(CLS, DECL) \
557 template<> \
558 class DECL wxAnyValueTypeImpl<CLS> : \
559 public wxAnyValueTypeImplBase<CLS> \
560 { \
561 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<CLS>) \
562 public: \
563 wxAnyValueTypeImpl() : \
564 wxAnyValueTypeImplBase<CLS>() { } \
565 virtual ~wxAnyValueTypeImpl() { } \
566 \
567 virtual bool ConvertValue(const wxAnyValueBuffer& src, \
568 wxAnyValueType* dstType, \
569 wxAnyValueBuffer& dst) const \
570 { \
571 wxUnusedVar(src); \
572 wxUnusedVar(dstType); \
573 wxUnusedVar(dst); \
574 return false; \
575 } \
576 };
577
578
579 // Make sure some of wx's own types get the right wxAnyValueType export
580 // (this is needed only for types that are referred to from wxBase.
581 // currently we may not use any of these types from there, but let's
582 // use the macro on at least one to make sure it compiles since we can't
583 // really test it properly in unit tests since a separate DLL would
584 // be needed).
585 #if wxUSE_DATETIME
586 #include "wx/datetime.h"
587 wxDECLARE_ANY_TYPE(wxDateTime, WXDLLIMPEXP_BASE)
588 #endif
589
590 //#include "wx/object.h"
591 //wxDECLARE_ANY_TYPE(wxObject*, WXDLLIMPEXP_BASE)
592
593 //#include "wx/arrstr.h"
594 //wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE)
595
596
597 #if wxUSE_VARIANT
598
599 class WXDLLIMPEXP_FWD_BASE wxAnyToVariantRegistration;
600
601 // Because of header inter-dependencies, cannot include this earlier
602 #include "wx/variant.h"
603
604 //
605 // wxVariantData* data type implementation. For cases when appropriate
606 // wxAny<->wxVariant conversion code is missing.
607 //
608
609 class WXDLLIMPEXP_BASE wxAnyValueTypeImplVariantData :
610 public wxAnyValueTypeImplBase<wxVariantData*>
611 {
612 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
613 public:
614 wxAnyValueTypeImplVariantData() :
615 wxAnyValueTypeImplBase<wxVariantData*>() { }
616 virtual ~wxAnyValueTypeImplVariantData() { }
617
618 virtual void DeleteValue(wxAnyValueBuffer& buf) const
619 {
620 wxVariantData* data = static_cast<wxVariantData*>(buf.m_ptr);
621 if ( data )
622 data->DecRef();
623 }
624
625 virtual void CopyBuffer(const wxAnyValueBuffer& src,
626 wxAnyValueBuffer& dst) const
627 {
628 wxVariantData* data = static_cast<wxVariantData*>(src.m_ptr);
629 if ( data )
630 data->IncRef();
631 dst.m_ptr = data;
632 }
633
634 static void SetValue(wxVariantData* value,
635 wxAnyValueBuffer& buf)
636 {
637 value->IncRef();
638 buf.m_ptr = value;
639 }
640
641 static wxVariantData* GetValue(const wxAnyValueBuffer& buf)
642 {
643 return static_cast<wxVariantData*>(buf.m_ptr);
644 }
645
646 virtual bool ConvertValue(const wxAnyValueBuffer& src,
647 wxAnyValueType* dstType,
648 wxAnyValueBuffer& dst) const
649 {
650 wxUnusedVar(src);
651 wxUnusedVar(dstType);
652 wxUnusedVar(dst);
653 return false;
654 }
655 };
656
657 template<>
658 class wxAnyValueTypeImpl<wxVariantData*> :
659 public wxAnyValueTypeImplVariantData
660 {
661 public:
662 wxAnyValueTypeImpl() : wxAnyValueTypeImplVariantData() { }
663 virtual ~wxAnyValueTypeImpl() { }
664 };
665
666 #endif // wxUSE_VARIANT
667
668 #ifdef __VISUALC6__
669 // Re-enable useless VC6 warnings
670 #pragma warning (pop)
671 #endif
672
673
674 /*
675 Let's define a discrete Null value so we don't have to really
676 ever check if wxAny.m_type pointer is NULL or not. This is an
677 optimization, mostly. Implementation of this value type is
678 "hidden" in the source file.
679 */
680 extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType*) wxAnyNullValueType;
681
682
683 //
684 // We need to implement custom signed/unsigned int equals operators
685 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
686 #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \
687 bool operator==(TS value) const \
688 { \
689 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
690 return (value == static_cast<TS> \
691 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
692 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
693 return (value == static_cast<TS> \
694 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
695 return false; \
696 } \
697 bool operator==(TUS value) const \
698 { \
699 if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \
700 return (value == static_cast<TUS> \
701 (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \
702 if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \
703 return (value == static_cast<TUS> \
704 (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \
705 return false; \
706 }
707
708
709 #if wxUSE_VARIANT
710
711 // Note that the following functions are implemented outside wxAny class
712 // so that it can reside entirely in header and lack the export declaration.
713
714 // Helper function used to associate wxAnyValueType with a wxVariantData.
715 extern WXDLLIMPEXP_BASE void
716 wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg);
717
718 // This function performs main wxAny to wxVariant conversion duties.
719 extern WXDLLIMPEXP_BASE bool
720 wxConvertAnyToVariant(const wxAny& any, wxVariant* variant);
721
722 #endif // wxUSE_VARIANT
723
724
725 //
726 // The wxAny class represents a container for any type. A variant's value
727 // can be changed at run time, possibly to a different type of value.
728 //
729 // As standard, wxAny can store value of almost any type, in a fairly
730 // optimal manner even.
731 //
732 class wxAny
733 {
734 public:
735 /**
736 Default constructor.
737 */
738 wxAny()
739 {
740 m_type = wxAnyNullValueType;
741 }
742
743 /**
744 Destructor.
745 */
746 ~wxAny()
747 {
748 m_type->DeleteValue(m_buffer);
749 }
750
751 //@{
752 /**
753 Various constructors.
754 */
755 template<typename T>
756 wxAny(const T& value)
757 {
758 m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
759 wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
760 }
761
762 // These two constructors are needed to deal with string literals
763 wxAny(const char* value)
764 {
765 m_type = wxAnyValueTypeImpl<const char*>::sm_instance.get();
766 wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer);
767 }
768 wxAny(const wchar_t* value)
769 {
770 m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance.get();
771 wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer);
772 }
773
774 wxAny(const wxAny& any)
775 {
776 m_type = wxAnyNullValueType;
777 AssignAny(any);
778 }
779
780 #if wxUSE_VARIANT
781 wxAny(const wxVariant& variant)
782 {
783 m_type = wxAnyNullValueType;
784 AssignVariant(variant);
785 }
786 #endif
787
788 //@}
789
790 /**
791 Use this template function for checking if this wxAny holds
792 a specific C++ data type.
793
794 @remarks This template function does not work on some older compilers
795 (such as Visual C++ 6.0). For full compiler ccompatibility
796 please use wxANY_CHECK_TYPE(any, T) macro instead.
797
798 @see wxAnyValueType::CheckType()
799 */
800 // FIXME-VC6: remove this hack when VC6 is no longer supported
801 template <typename T>
802 bool CheckType(T* = NULL) const
803 {
804 return m_type->CheckType<T>();
805 }
806
807 /**
808 Returns the value type as wxAnyValueType instance.
809
810 @remarks You cannot reliably test whether two wxAnys are of
811 same value type by simply comparing return values
812 of wxAny::GetType(). Instead, use wxAny::HasSameType().
813
814 @see HasSameType()
815 */
816 const wxAnyValueType* GetType() const
817 {
818 return m_type;
819 }
820
821 /**
822 Returns @true if this and another wxAny have the same
823 value type.
824 */
825 bool HasSameType(const wxAny& other) const
826 {
827 return GetType()->IsSameType(other.GetType());
828 }
829
830 /**
831 Tests if wxAny is null (that is, whether there is no data).
832 */
833 bool IsNull() const
834 {
835 return (m_type == wxAnyNullValueType);
836 }
837
838 /**
839 Makes wxAny null (that is, clears it).
840 */
841 void MakeNull()
842 {
843 m_type->DeleteValue(m_buffer);
844 m_type = wxAnyNullValueType;
845 }
846
847 //@{
848 /**
849 Assignment operators.
850 */
851 template<typename T>
852 wxAny& operator=(const T &value)
853 {
854 m_type->DeleteValue(m_buffer);
855 m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
856 wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
857 return *this;
858 }
859
860 wxAny& operator=(const wxAny &any)
861 {
862 if (this != &any)
863 AssignAny(any);
864 return *this;
865 }
866
867 #if wxUSE_VARIANT
868 wxAny& operator=(const wxVariant &variant)
869 {
870 AssignVariant(variant);
871 return *this;
872 }
873 #endif
874
875 // These two operators are needed to deal with string literals
876 wxAny& operator=(const char* value)
877 {
878 Assign(value);
879 return *this;
880 }
881 wxAny& operator=(const wchar_t* value)
882 {
883 Assign(value);
884 return *this;
885 }
886
887 //@{
888 /**
889 Equality operators.
890 */
891 bool operator==(const wxString& value) const
892 {
893 wxString value2;
894 if ( !GetAs(&value2) )
895 return false;
896 return value == value2;
897 }
898
899 bool operator==(const char* value) const
900 { return (*this) == wxString(value); }
901 bool operator==(const wchar_t* value) const
902 { return (*this) == wxString(value); }
903
904 //
905 // We need to implement custom signed/unsigned int equals operators
906 // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work.
907 WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char)
908 WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short)
909 WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int)
910 WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long)
911 #ifdef wxLongLong_t
912 WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t, wxULongLong_t)
913 #endif
914
915 bool operator==(float value) const
916 {
917 if ( !wxAnyValueTypeImpl<float>::IsSameClass(m_type) )
918 return false;
919
920 return value ==
921 static_cast<float>
922 (wxAnyValueTypeImpl<float>::GetValue(m_buffer));
923 }
924
925 bool operator==(double value) const
926 {
927 if ( !wxAnyValueTypeImpl<double>::IsSameClass(m_type) )
928 return false;
929
930 return value ==
931 static_cast<double>
932 (wxAnyValueTypeImpl<double>::GetValue(m_buffer));
933 }
934
935 bool operator==(bool value) const
936 {
937 if ( !wxAnyValueTypeImpl<bool>::IsSameClass(m_type) )
938 return false;
939
940 return value == (wxAnyValueTypeImpl<bool>::GetValue(m_buffer));
941 }
942
943 //@}
944
945 //@{
946 /**
947 Inequality operators (implement as template).
948 */
949 template<typename T>
950 bool operator!=(const T& value) const
951 { return !((*this) == value); }
952 //@}
953
954 /**
955 This template function converts wxAny into given type. In most cases
956 no type conversion is performed, so if the type is incorrect an
957 assertion failure will occur.
958
959 @remarks For convenience, conversion is done when T is wxString. This
960 is useful when a string literal (which are treated as
961 const char* and const wchar_t*) has been assigned to wxAny.
962
963 This template function may not work properly with Visual C++
964 6. For full compiler compatibility, please use
965 wxANY_AS(any, T) macro instead.
966 */
967 // FIXME-VC6: remove this hack when VC6 is no longer supported
968 template<typename T>
969 T As(T* = NULL) const
970 {
971 if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
972 {
973 wxFAIL_MSG("Incorrect or non-convertible data type");
974 }
975
976 return static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer));
977 }
978
979 // Allow easy conversion from 'const char *' etc. to wxString
980 // FIXME-VC6: remove this hack when VC6 is no longer supported
981 //template<>
982 wxString As(wxString*) const
983 {
984 wxString value;
985 if ( !GetAs(&value) )
986 {
987 wxFAIL_MSG("Incorrect or non-convertible data type");
988 }
989 return value;
990 }
991
992 #if wxUSE_EXTENDED_RTTI
993 const wxTypeInfo* GetTypeInfo() const
994 {
995 return m_type->GetTypeInfo();
996 }
997 #endif
998 /**
999 Template function that retrieves and converts the value of this
1000 variant to the type that T* value is.
1001
1002 @return Returns @true if conversion was successful.
1003 */
1004 template<typename T>
1005 bool GetAs(T* value) const
1006 {
1007 if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
1008 {
1009 wxAnyValueType* otherType =
1010 wxAnyValueTypeImpl<T>::sm_instance.get();
1011 wxAnyValueBuffer temp_buf;
1012
1013 if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) )
1014 return false;
1015
1016 *value =
1017 static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(temp_buf));
1018 otherType->DeleteValue(temp_buf);
1019
1020 return true;
1021 }
1022 *value = static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer));
1023 return true;
1024 }
1025
1026 #if wxUSE_VARIANT
1027 // GetAs() wxVariant specialization
1028 bool GetAs(wxVariant* value) const
1029 {
1030 return wxConvertAnyToVariant(*this, value);
1031 }
1032 #endif
1033
1034 private:
1035 // Assignment functions
1036 void AssignAny(const wxAny& any)
1037 {
1038 // Must delete value - CopyBuffer() never does that
1039 m_type->DeleteValue(m_buffer);
1040
1041 wxAnyValueType* newType = any.m_type;
1042
1043 if ( !newType->IsSameType(m_type) )
1044 m_type = newType;
1045
1046 newType->CopyBuffer(any.m_buffer, m_buffer);
1047 }
1048
1049 #if wxUSE_VARIANT
1050 void AssignVariant(const wxVariant& variant)
1051 {
1052 wxVariantData* data = variant.GetData();
1053
1054 if ( data && data->GetAsAny(this) )
1055 return;
1056
1057 m_type->DeleteValue(m_buffer);
1058
1059 if ( variant.IsNull() )
1060 {
1061 // Init as Null
1062 m_type = wxAnyNullValueType;
1063 }
1064 else
1065 {
1066 // If everything else fails, wrap the whole wxVariantData
1067 m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance.get();
1068 wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
1069 }
1070 }
1071 #endif
1072
1073 template<typename T>
1074 void Assign(const T &value)
1075 {
1076 m_type->DeleteValue(m_buffer);
1077 m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
1078 wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
1079 }
1080
1081 // Data
1082 wxAnyValueBuffer m_buffer;
1083 wxAnyValueType* m_type;
1084 };
1085
1086
1087 //
1088 // This method of checking the type is compatible with VC6
1089 #define wxANY_CHECK_TYPE(any, T) \
1090 wxANY_VALUE_TYPE_CHECK_TYPE((any).GetType(), T)
1091
1092
1093 //
1094 // This method of getting the value is compatible with VC6
1095 #define wxANY_AS(any, T) \
1096 (any).As(static_cast<T*>(NULL))
1097
1098
1099 template<typename T>
1100 inline bool wxAnyValueType::CheckType(T* reserved) const
1101 {
1102 wxUnusedVar(reserved);
1103 return wxAnyValueTypeImpl<T>::IsSameClass(this);
1104 }
1105
1106 WX_DECLARE_LIST_WITH_DECL(wxAny, wxAnyList, class WXDLLIMPEXP_BASE);
1107
1108 #endif // wxUSE_ANY
1109
1110 #endif // _WX_ANY_H_