Use scoped ptrs to managed wxAnyValueType instances. This fixes deallocation issues...
[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 #include "wx/hashset.h"
32
33 using namespace wxPrivate;
34
35 #if wxUSE_VARIANT
36
37 //-------------------------------------------------------------------------
38 // wxAnyValueTypeGlobals
39 //-------------------------------------------------------------------------
40
41 WX_DECLARE_HASH_MAP(wxAnyValueType*,
42 wxVariantDataFactory,
43 wxPointerHash,
44 wxPointerEqual,
45 wxAnyTypeToVariantDataFactoryMap);
46
47 //
48 // Helper class to manage global variables related to type conversion
49 // between wxAny and wxVariant.
50 //
51 class wxAnyValueTypeGlobals
52 {
53 public:
54 wxAnyValueTypeGlobals()
55 {
56 }
57 ~wxAnyValueTypeGlobals()
58 {
59 m_anyToVariant.clear();
60 }
61
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)
69 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_)
70 {
71 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
72 // but WX_DECLARE_HASH_MAP() has some trouble with it.
73 wxAnyValueType* type = const_cast<wxAnyValueType*>(type_);
74
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 }
118
119 private:
120 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
121 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
122 };
123
124 static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
125
126
127 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
128
129 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
130 {
131 if ( !g_wxAnyValueTypeGlobals )
132 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
133 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
134 }
135
136 bool 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
151 wxLongLong_t ll = 0;
152 if ( any.GetAs(&ll) )
153 {
154 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
155 // integer constraint yields more consistent behavior across
156 // builds.
157 if ( ll > wxINT32_MAX || ll < wxINT32_MIN )
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
180 wxVariantData* data = NULL;
181
182 if ( f )
183 {
184 data = f(any);
185 }
186 else
187 {
188 // Check if wxAny wrapped wxVariantData*
189 if ( !any.GetAs(&data) )
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);
195 return false;
196 }
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
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 //
213 class wxAnyValueTypeGlobalsManager : public wxModule
214 {
215 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
216 public:
217 wxAnyValueTypeGlobalsManager() : wxModule() { }
218 virtual ~wxAnyValueTypeGlobalsManager() { }
219
220 virtual bool OnInit()
221 {
222 return true;
223 }
224 virtual void OnExit()
225 {
226 delete g_wxAnyValueTypeGlobals;
227 g_wxAnyValueTypeGlobals = NULL;
228 }
229 private:
230 };
231
232 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
233
234 #endif // wxUSE_VARIANT
235
236
237 //-------------------------------------------------------------------------
238 // Dynamic conversion member functions
239 //-------------------------------------------------------------------------
240
241 //
242 // Define integer minimum and maximum as helpers
243 #ifdef wxLongLong_t
244 #define UseIntMin (wxINT64_MIN)
245 #define UseIntMax (wxINT64_MAX)
246 #define UseUintMax (wxUINT64_MAX)
247 #else
248 #define UseIntMin (LONG_MIN)
249 #define UseIntMax (LONG_MAX)
250 #define UseUintMax (ULONG_MAX)
251 #endif
252
253 namespace
254 {
255
256 const double UseIntMinF = static_cast<double>(UseIntMin);
257 const double UseIntMaxF = static_cast<double>(UseIntMax);
258 const double UseUintMaxF = static_cast<double>(UseUintMax);
259
260 } // anonymous namespace
261
262 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src,
263 wxAnyValueType* dstType,
264 wxAnyValueBuffer& dst) const
265 {
266 wxAnyBaseIntType value = GetValue(src);
267 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
268 {
269 #ifdef wxLongLong_t
270 wxLongLong ll(value);
271 wxString s = ll.ToString();
272 #else
273 wxString s = wxString::Format(wxS("%ld"), (long)value);
274 #endif
275 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
276 }
277 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
278 {
279 if ( value < 0 )
280 return false;
281 wxAnyBaseUintType ul = (wxAnyBaseUintType) value;
282 wxAnyValueTypeImplUint::SetValue(ul, dst);
283 }
284 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
285 {
286 double value2 = static_cast<double>(value);
287 wxAnyValueTypeImplDouble::SetValue(value2, dst);
288 }
289 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
290 {
291 bool value2 = value ? true : false;
292 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
293 }
294 else
295 return false;
296
297 return true;
298 }
299
300 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
301 wxAnyValueType* dstType,
302 wxAnyValueBuffer& dst) const
303 {
304 wxAnyBaseUintType value = GetValue(src);
305 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
306 {
307 #ifdef wxLongLong_t
308 wxULongLong ull(value);
309 wxString s = ull.ToString();
310 #else
311 wxString s = wxString::Format(wxS("%lu"), (long)value);
312 #endif
313 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
314 }
315 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
316 {
317 if ( value > UseIntMax )
318 return false;
319 wxAnyBaseIntType l = (wxAnyBaseIntType) value;
320 wxAnyValueTypeImplInt::SetValue(l, dst);
321 }
322 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
323 {
324 #ifndef __VISUALC6__
325 double value2 = static_cast<double>(value);
326 #else
327 // VC6 doesn't implement conversion from unsigned __int64 to double
328 wxAnyBaseIntType value0 = static_cast<wxAnyBaseIntType>(value);
329 double value2 = static_cast<double>(value0);
330 #endif
331 wxAnyValueTypeImplDouble::SetValue(value2, dst);
332 }
333 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
334 {
335 bool value2 = value ? true : false;
336 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
337 }
338 else
339 return false;
340
341 return true;
342 }
343
344 // Convert wxString to destination wxAny value type
345 bool wxAnyConvertString(const wxString& value,
346 wxAnyValueType* dstType,
347 wxAnyValueBuffer& dst)
348 {
349 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
350 {
351 wxAnyValueTypeImpl<wxString>::SetValue(value, dst);
352 }
353 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
354 {
355 wxAnyBaseIntType value2;
356 #ifdef wxLongLong_t
357 if ( !value.ToLongLong(&value2) )
358 #else
359 if ( !value.ToLong(&value2) )
360 #endif
361 return false;
362 wxAnyValueTypeImplInt::SetValue(value2, dst);
363 }
364 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
365 {
366 wxAnyBaseUintType value2;
367 #ifdef wxLongLong_t
368 if ( !value.ToULongLong(&value2) )
369 #else
370 if ( !value.ToULong(&value2) )
371 #endif
372 return false;
373 wxAnyValueTypeImplUint::SetValue(value2, dst);
374 }
375 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
376 {
377 double value2;
378 if ( !value.ToDouble(&value2) )
379 return false;
380 wxAnyValueTypeImplDouble::SetValue(value2, dst);
381 }
382 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
383 {
384 bool value2;
385 wxString s(value);
386 s.MakeLower();
387 if ( s == wxS("true") ||
388 s == wxS("yes") ||
389 s == wxS('1') )
390 value2 = true;
391 else if ( s == wxS("false") ||
392 s == wxS("no") ||
393 s == wxS('0') )
394 value2 = false;
395 else
396 return false;
397
398 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
399 }
400 else
401 return false;
402
403 return true;
404 }
405
406 bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
407 wxAnyValueType* dstType,
408 wxAnyValueBuffer& dst) const
409 {
410 bool value = GetValue(src);
411 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
412 {
413 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
414 wxAnyValueTypeImplInt::SetValue(value2, dst);
415 }
416 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
417 {
418 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
419 wxAnyValueTypeImplUint::SetValue(value2, dst);
420 }
421 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
422 {
423 wxString s;
424 if ( value )
425 s = wxS("true");
426 else
427 s = wxS("false");
428 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
429 }
430 else
431 return false;
432
433 return true;
434 }
435
436 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
437 wxAnyValueType* dstType,
438 wxAnyValueBuffer& dst) const
439 {
440 double value = GetValue(src);
441 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
442 {
443 if ( value < UseIntMinF || value > UseIntMaxF )
444 return false;
445 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
446 wxAnyValueTypeImplUint::SetValue(ul, dst);
447 }
448 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
449 {
450 if ( value < 0.0 || value > UseUintMaxF )
451 return false;
452 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
453 wxAnyValueTypeImplUint::SetValue(ul, dst);
454 }
455 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
456 {
457 wxString s = wxString::Format(wxS("%.14g"), value);
458 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
459 }
460 else
461 return false;
462
463 return true;
464 }
465
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
468 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
469 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
470
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
472 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
473 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
474
475 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
476 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
477 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
478
479 //-------------------------------------------------------------------------
480 // wxAnyNullValueType implementation
481 //-------------------------------------------------------------------------
482
483 class wxAnyNullValue
484 {
485 private:
486 void* m_dummy;
487 };
488
489 template <>
490 class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
491 {
492 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
493 public:
494 // Dummy implementations
495 virtual void DeleteValue(wxAnyValueBuffer& buf) const
496 {
497 wxUnusedVar(buf);
498 }
499
500 virtual void CopyBuffer(const wxAnyValueBuffer& src,
501 wxAnyValueBuffer& dst) const
502 {
503 wxUnusedVar(src);
504 wxUnusedVar(dst);
505 }
506
507 virtual bool ConvertValue(const wxAnyValueBuffer& src,
508 wxAnyValueType* dstType,
509 wxAnyValueBuffer& dst) const
510 {
511 wxUnusedVar(src);
512 wxUnusedVar(dstType);
513 wxUnusedVar(dst);
514 return false;
515 }
516
517 private:
518 };
519
520 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
521
522 wxAnyValueType* wxAnyNullValueType =
523 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
524
525 #endif // wxUSE_ANY