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