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