]> git.saurik.com Git - wxWidgets.git/blame - src/common/any.cpp
Correctly use wxANY_AS() instead of wxAny::As<>(), for VC6 compatibility
[wxWidgets.git] / src / common / any.cpp
CommitLineData
39601a7f
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/any.cpp
3// Purpose: wxAny class, container for any type
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// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#include "wx/any.h"
20
21#if wxUSE_ANY
22
23#ifndef WX_PRECOMP
24 #include "wx/math.h"
25 #include "wx/crt.h"
26#endif
27
28#include "wx/vector.h"
29#include "wx/module.h"
0bf14ab8 30#include "wx/hashmap.h"
39601a7f
VZ
31
32using namespace wxPrivate;
33
34//-------------------------------------------------------------------------
35// wxAnyValueTypeGlobals
36//-------------------------------------------------------------------------
37
0bf14ab8
JS
38#if wxUSE_VARIANT
39
40WX_DECLARE_HASH_MAP(wxAnyValueType*,
41 wxVariantDataFactory,
42 wxPointerHash,
43 wxPointerEqual,
44 wxAnyTypeToVariantDataFactoryMap);
45
46#endif
47
39601a7f 48//
0bf14ab8
JS
49// Helper class to manage wxAnyValueType instances and and other
50// related global variables (such as wxAny<->wxVariant type association).
39601a7f
VZ
51//
52// NB: We really need to have wxAnyValueType instances allocated
53// in heap. They are stored as static template member variables,
54// and with them we just can't be too careful (eg. not allocating
55// them in heap broke the type identification in GCC).
56//
57class wxAnyValueTypeGlobals
58{
59public:
60 wxAnyValueTypeGlobals()
61 {
62 }
63 ~wxAnyValueTypeGlobals()
64 {
0bf14ab8
JS
65 #if wxUSE_VARIANT
66 m_anyToVariant.clear();
67 #endif
39601a7f
VZ
68 for ( size_t i=0; i<m_valueTypes.size(); i++ )
69 delete m_valueTypes[i];
70 }
71
72 void RegisterValueType(wxAnyValueType* valueType)
73 {
74 m_valueTypes.push_back(valueType);
75 }
76
0bf14ab8
JS
77#if wxUSE_VARIANT
78 void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
79 {
80 m_anyToVariantRegs.push_back(reg);
81 }
82
83 // Find wxVariantData factory function for given value type,
84 // (or compatible, if possible)
85 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type)
86 {
87 wxAnyTypeToVariantDataFactoryMap& anyToVariant = m_anyToVariant;
88 wxAnyTypeToVariantDataFactoryMap::const_iterator it;
89 it = anyToVariant.find(type);
90 if ( it != anyToVariant.end() )
91 return it->second;
92
93 // Not found, handle pre-registrations
94 size_t i = m_anyToVariantRegs.size();
95 while ( i > 0 )
96 {
97 i--;
98 wxAnyToVariantRegistration* reg = m_anyToVariantRegs[i];
99 wxAnyValueType* assocType = reg->GetAssociatedType();
100 if ( assocType )
101 {
102 // Both variant data and wxAnyValueType have been
103 // now been properly initialized, so remove the
104 // pre-registration entry and move data to anyToVarian
105 // map.
106 anyToVariant[assocType] = reg->GetFactory();
107 m_anyToVariantRegs.erase( m_anyToVariantRegs.begin() + i );
108 }
109 }
110
111 // Then try again
112 it = anyToVariant.find(type);
113 if ( it != anyToVariant.end() )
114 return it->second;
115
116 // Finally, attempt to find a compatible type
117 for ( it = anyToVariant.begin(); it != anyToVariant.end(); it++ )
118 {
119 if ( type->IsSameType(it->first) )
120 {
121 wxVariantDataFactory f = it->second;
122 anyToVariant[type] = f;
123 return f;
124 }
125 }
126
127 // Nothing found
128 return NULL;
129 }
130#endif
131
39601a7f 132private:
0bf14ab8
JS
133 wxVector<wxAnyValueType*> m_valueTypes;
134#if wxUSE_VARIANT
135 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
136 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
137#endif
39601a7f
VZ
138};
139
140static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
141
0bf14ab8
JS
142#if wxUSE_VARIANT
143
144WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
145
146void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
147{
148 if ( !g_wxAnyValueTypeGlobals )
149 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
150 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
151}
152
153bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant)
154{
155 if ( any.IsNull() )
156 {
157 variant->MakeNull();
158 return true;
159 }
160
161 // (signed) integer is a special case, because there is only one type
162 // in wxAny, and two ("long" and "longlong") in wxVariant. For better
163 // backwards compatibility, convert all values that fit in "long",
164 // and others to "longlong".
165 if ( wxANY_CHECK_TYPE(any, signed int) )
166 {
167#ifdef wxLongLong_t
5afecf60 168 wxLongLong_t ll = 0;
0bf14ab8
JS
169 if ( any.GetAs(&ll) )
170 {
171 if ( ll > LONG_MAX )
172 *variant = wxLongLong(ll);
173 else
174 *variant = (long) wxLongLong(ll).GetLo();
175 }
176 else
177 {
178 return false;
179 }
180#else
181 long l;
182 if ( any.GetAs(&l) )
183 *variant = l;
184 else
185 return false;
186#endif
187 return true;
188 }
189
190 // Find matching factory function
191 wxVariantDataFactory f =
192 g_wxAnyValueTypeGlobals->FindVariantDataFactory(any.GetType());
193
5afecf60
JS
194 wxVariantData* data = NULL;
195
0bf14ab8
JS
196 if ( f )
197 {
198 data = f(any);
199 }
200 else
201 {
202 // Check if wxAny wrapped wxVariantData*
203 if ( !any.GetAs(&data) )
204 return false;
205
206 // Wrapper's GetValue() does not increase reference
207 // count, se have to do it before the data gets passed
208 // to a new variant.
209 data->IncRef();
210 }
211
212 variant->SetData(data);
213 return true;
214}
215
216#endif // wxUSE_VARIANT
217
39601a7f
VZ
218//
219// This class is to make sure that wxAnyValueType instances
220// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
221// because wxModule itself is instantiated too late.
222//
223class wxAnyValueTypeGlobalsManager : public wxModule
224{
225 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
226public:
227 wxAnyValueTypeGlobalsManager() : wxModule() { }
228 virtual ~wxAnyValueTypeGlobalsManager() { }
229
230 virtual bool OnInit()
231 {
232 return true;
233 }
234 virtual void OnExit()
235 {
236 delete g_wxAnyValueTypeGlobals;
237 g_wxAnyValueTypeGlobals = NULL;
238 }
239private:
240};
241
242IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
243
244
245//-------------------------------------------------------------------------
246// wxAnyValueType
247//-------------------------------------------------------------------------
248
249wxAnyValueType::wxAnyValueType()
250{
251 if ( !g_wxAnyValueTypeGlobals )
252 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
253
254 g_wxAnyValueTypeGlobals->RegisterValueType(this);
255}
256
39601a7f
VZ
257//-------------------------------------------------------------------------
258// Dynamic conversion member functions
259//-------------------------------------------------------------------------
260
261//
262// Define integer minimum and maximum as helpers
263#ifdef wxLongLong_t
982d7f93
VZ
264 #define UseIntMin (wxINT64_MIN)
265 #define UseIntMax (wxINT64_MAX)
266 #define UseUintMax (wxUINT64_MAX)
39601a7f 267#else
982d7f93
VZ
268 #define UseIntMin (LONG_MIN)
269 #define UseIntMax (LONG_MAX)
270 #define UseUintMax (ULONG_MAX)
39601a7f
VZ
271#endif
272
982d7f93
VZ
273namespace
274{
275
39601a7f 276const double UseIntMinF = static_cast<double>(UseIntMin);
39601a7f
VZ
277const double UseIntMaxF = static_cast<double>(UseIntMax);
278const double UseUintMaxF = static_cast<double>(UseUintMax);
39601a7f 279
982d7f93 280} // anonymous namespace
39601a7f
VZ
281
282bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src,
283 wxAnyValueType* dstType,
284 wxAnyValueBuffer& dst) const
285{
286 wxAnyBaseIntType value = GetValue(src);
287 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
288 {
289#ifdef wxLongLong_t
290 wxLongLong ll(value);
291 wxString s = ll.ToString();
292#else
293 wxString s = wxString::Format(wxS("%ld"), (long)value);
294#endif
295 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
296 }
297 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
298 {
299 if ( value < 0 )
300 return false;
301 wxAnyBaseUintType ul = (wxAnyBaseUintType) value;
302 wxAnyValueTypeImplUint::SetValue(ul, dst);
303 }
304 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
305 {
306 double value2 = static_cast<double>(value);
307 wxAnyValueTypeImplDouble::SetValue(value2, dst);
308 }
309 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
310 {
311 bool value2 = value ? true : false;
312 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
313 }
314 else
315 return false;
316
317 return true;
318}
319
320bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
321 wxAnyValueType* dstType,
322 wxAnyValueBuffer& dst) const
323{
324 wxAnyBaseUintType value = GetValue(src);
325 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
326 {
327#ifdef wxLongLong_t
328 wxULongLong ull(value);
329 wxString s = ull.ToString();
330#else
331 wxString s = wxString::Format(wxS("%lu"), (long)value);
332#endif
333 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
334 }
335 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
336 {
337 if ( value > UseIntMax )
338 return false;
339 wxAnyBaseIntType l = (wxAnyBaseIntType) value;
340 wxAnyValueTypeImplInt::SetValue(l, dst);
341 }
342 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
343 {
344#ifndef __VISUALC6__
345 double value2 = static_cast<double>(value);
346#else
347 // VC6 doesn't implement conversion from unsigned __int64 to double
348 wxAnyBaseIntType value0 = static_cast<wxAnyBaseIntType>(value);
349 double value2 = static_cast<double>(value0);
350#endif
351 wxAnyValueTypeImplDouble::SetValue(value2, dst);
352 }
353 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
354 {
355 bool value2 = value ? true : false;
356 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
357 }
358 else
359 return false;
360
361 return true;
362}
363
364bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src,
365 wxAnyValueType* dstType,
366 wxAnyValueBuffer& dst) const
367{
368 wxString value = GetValue(src);
369 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
370 {
371 wxAnyBaseIntType value2;
372#ifdef wxLongLong_t
373 if ( !value.ToLongLong(&value2) )
374#else
375 if ( !value.ToLong(&value2) )
376#endif
377 return false;
378 wxAnyValueTypeImplInt::SetValue(value2, dst);
379 }
380 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
381 {
382 wxAnyBaseUintType value2;
383#ifdef wxLongLong_t
384 if ( !value.ToULongLong(&value2) )
385#else
386 if ( !value.ToULong(&value2) )
387#endif
388 return false;
389 wxAnyValueTypeImplUint::SetValue(value2, dst);
390 }
391 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
392 {
393 double value2;
394 if ( !value.ToDouble(&value2) )
395 return false;
396 wxAnyValueTypeImplDouble::SetValue(value2, dst);
397 }
398 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
399 {
400 bool value2;
401 value.MakeLower();
402 if ( value == wxS("true") ||
403 value == wxS("yes") ||
404 value == wxS('1') )
405 value2 = true;
406 else if ( value == wxS("false") ||
407 value == wxS("no") ||
408 value == wxS('0') )
409 value2 = false;
410 else
411 return false;
412
413 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
414 }
415 else
416 return false;
417
418 return true;
419}
420
421bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
422 wxAnyValueType* dstType,
423 wxAnyValueBuffer& dst) const
424{
425 bool value = GetValue(src);
426 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
427 {
428 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
429 wxAnyValueTypeImplInt::SetValue(value2, dst);
430 }
431 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
432 {
433 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
434 wxAnyValueTypeImplUint::SetValue(value2, dst);
435 }
436 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
437 {
438 wxString s;
439 if ( value )
440 s = wxS("true");
441 else
442 s = wxS("false");
443 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
444 }
445 else
446 return false;
447
448 return true;
449}
450
451bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
452 wxAnyValueType* dstType,
453 wxAnyValueBuffer& dst) const
454{
455 double value = GetValue(src);
456 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
457 {
458 if ( value < UseIntMinF || value > UseIntMaxF )
459 return false;
460 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
461 wxAnyValueTypeImplUint::SetValue(ul, dst);
462 }
463 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
464 {
465 if ( value < 0.0 || value > UseUintMaxF )
466 return false;
467 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
468 wxAnyValueTypeImplUint::SetValue(ul, dst);
469 }
470 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
471 {
472 wxString s = wxString::Format(wxS("%.14g"), value);
473 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
474 }
475 else
476 return false;
477
478 return true;
479}
480
481WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
482WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
483WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
484WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
485WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
486
c5fe6a5b
JS
487WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
488//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
489//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
490
39601a7f
VZ
491//-------------------------------------------------------------------------
492// wxAnyNullValueType implementation
493//-------------------------------------------------------------------------
494
495class wxAnyNullValue
496{
497private:
498 void* m_dummy;
499};
500
501template <>
502class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
503{
504 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
505public:
24985a9b 506 // Dummy implementations
39601a7f
VZ
507 virtual void DeleteValue(wxAnyValueBuffer& buf) const
508 {
24985a9b 509 wxUnusedVar(buf);
39601a7f
VZ
510 }
511
39601a7f
VZ
512 virtual void CopyBuffer(const wxAnyValueBuffer& src,
513 wxAnyValueBuffer& dst) const
514 {
515 wxUnusedVar(src);
516 wxUnusedVar(dst);
517 }
518
519 virtual bool ConvertValue(const wxAnyValueBuffer& src,
520 wxAnyValueType* dstType,
521 wxAnyValueBuffer& dst) const
522 {
523 wxUnusedVar(src);
524 wxUnusedVar(dstType);
525 wxUnusedVar(dst);
526 return false;
527 }
528
529private:
530};
531
532WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
533
534wxAnyValueType* wxAnyNullValueType =
535 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
536
537#endif // wxUSE_ANY