wxVariant <-> wxAny conversion functionality. Includes implicit construction of wxAny...
[wxWidgets.git] / src / common / any.cpp
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"
30 #include "wx/hashmap.h"
31
32 using namespace wxPrivate;
33
34 //-------------------------------------------------------------------------
35 // wxAnyValueTypeGlobals
36 //-------------------------------------------------------------------------
37
38 #if wxUSE_VARIANT
39
40 WX_DECLARE_HASH_MAP(wxAnyValueType*,
41 wxVariantDataFactory,
42 wxPointerHash,
43 wxPointerEqual,
44 wxAnyTypeToVariantDataFactoryMap);
45
46 #endif
47
48 //
49 // Helper class to manage wxAnyValueType instances and and other
50 // related global variables (such as wxAny<->wxVariant type association).
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 //
57 class wxAnyValueTypeGlobals
58 {
59 public:
60 wxAnyValueTypeGlobals()
61 {
62 }
63 ~wxAnyValueTypeGlobals()
64 {
65 #if wxUSE_VARIANT
66 m_anyToVariant.clear();
67 #endif
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
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
132 private:
133 wxVector<wxAnyValueType*> m_valueTypes;
134 #if wxUSE_VARIANT
135 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
136 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
137 #endif
138 };
139
140 static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
141
142 #if wxUSE_VARIANT
143
144 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
145
146 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
147 {
148 if ( !g_wxAnyValueTypeGlobals )
149 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
150 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
151 }
152
153 bool 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
168 wxLongLong_t ll;
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
194 wxVariantData* data;
195
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
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 //
223 class wxAnyValueTypeGlobalsManager : public wxModule
224 {
225 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
226 public:
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 }
239 private:
240 };
241
242 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
243
244
245 //-------------------------------------------------------------------------
246 // wxAnyValueType
247 //-------------------------------------------------------------------------
248
249 wxAnyValueType::wxAnyValueType()
250 {
251 if ( !g_wxAnyValueTypeGlobals )
252 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
253
254 g_wxAnyValueTypeGlobals->RegisterValueType(this);
255 }
256
257 //-------------------------------------------------------------------------
258 // Dynamic conversion member functions
259 //-------------------------------------------------------------------------
260
261 //
262 // Define integer minimum and maximum as helpers
263 #ifdef wxLongLong_t
264 #define UseIntMin (wxINT64_MIN)
265 #define UseIntMax (wxINT64_MAX)
266 #define UseUintMax (wxUINT64_MAX)
267 #else
268 #define UseIntMin (LONG_MIN)
269 #define UseIntMax (LONG_MAX)
270 #define UseUintMax (ULONG_MAX)
271 #endif
272
273 namespace
274 {
275
276 const double UseIntMinF = static_cast<double>(UseIntMin);
277 const double UseIntMaxF = static_cast<double>(UseIntMax);
278 const double UseUintMaxF = static_cast<double>(UseUintMax);
279
280 } // anonymous namespace
281
282 bool 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
320 bool 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
364 bool 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
421 bool 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
451 bool 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
481 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
482 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
483 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
484 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
485 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
486
487 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
488 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
489 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
490
491 //-------------------------------------------------------------------------
492 // wxAnyNullValueType implementation
493 //-------------------------------------------------------------------------
494
495 class wxAnyNullValue
496 {
497 private:
498 void* m_dummy;
499 };
500
501 template <>
502 class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
503 {
504 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
505 public:
506 // Dummy implementations
507 virtual void DeleteValue(wxAnyValueBuffer& buf) const
508 {
509 wxUnusedVar(buf);
510 }
511
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
529 private:
530 };
531
532 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
533
534 wxAnyValueType* wxAnyNullValueType =
535 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
536
537 #endif // wxUSE_ANY