]>
Commit | Line | Data |
---|---|---|
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_ |