]> git.saurik.com Git - wxWidgets.git/blame - src/common/any.cpp
Spell contributor name correctly.
[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
JS
154 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
155 // integer constraint yields more consistent behavior across
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 {
226 delete g_wxAnyValueTypeGlobals;
227 g_wxAnyValueTypeGlobals = NULL;
228 }
229private:
230};
231
232IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
233
0cc226ad 234#endif // wxUSE_VARIANT
39601a7f 235
39601a7f 236
39601a7f
VZ
237//-------------------------------------------------------------------------
238// Dynamic conversion member functions
239//-------------------------------------------------------------------------
240
241//
242// Define integer minimum and maximum as helpers
243#ifdef wxLongLong_t
982d7f93
VZ
244 #define UseIntMin (wxINT64_MIN)
245 #define UseIntMax (wxINT64_MAX)
246 #define UseUintMax (wxUINT64_MAX)
39601a7f 247#else
982d7f93
VZ
248 #define UseIntMin (LONG_MIN)
249 #define UseIntMax (LONG_MAX)
250 #define UseUintMax (ULONG_MAX)
39601a7f
VZ
251#endif
252
982d7f93
VZ
253namespace
254{
255
39601a7f 256const double UseIntMinF = static_cast<double>(UseIntMin);
39601a7f
VZ
257const double UseIntMaxF = static_cast<double>(UseIntMax);
258const double UseUintMaxF = static_cast<double>(UseUintMax);
39601a7f 259
982d7f93 260} // anonymous namespace
39601a7f
VZ
261
262bool 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
300bool 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
153107b4
JS
344// Convert wxString to destination wxAny value type
345bool wxAnyConvertString(const wxString& value,
346 wxAnyValueType* dstType,
347 wxAnyValueBuffer& dst)
39601a7f 348{
153107b4
JS
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) )
39601a7f
VZ
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;
153107b4
JS
385 wxString s(value);
386 s.MakeLower();
387 if ( s == wxS("true") ||
388 s == wxS("yes") ||
389 s == wxS('1') )
39601a7f 390 value2 = true;
153107b4
JS
391 else if ( s == wxS("false") ||
392 s == wxS("no") ||
393 s == wxS('0') )
39601a7f
VZ
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
406bool 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
436bool 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
466WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
467WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
39601a7f
VZ
468WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
469WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
470
153107b4
JS
471WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
472WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
473WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
474
c5fe6a5b
JS
475WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
476//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
477//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
478
39601a7f
VZ
479//-------------------------------------------------------------------------
480// wxAnyNullValueType implementation
481//-------------------------------------------------------------------------
482
483class wxAnyNullValue
484{
485private:
486 void* m_dummy;
487};
488
489template <>
490class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
491{
492 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
493public:
24985a9b 494 // Dummy implementations
39601a7f
VZ
495 virtual void DeleteValue(wxAnyValueBuffer& buf) const
496 {
24985a9b 497 wxUnusedVar(buf);
39601a7f
VZ
498 }
499
39601a7f
VZ
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
517private:
518};
519
520WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
521
522wxAnyValueType* wxAnyNullValueType =
523 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
524
525#endif // wxUSE_ANY