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