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