1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/any.cpp
3 // Purpose: wxAny class, container for any type
4 // Author: Jaakko Salli
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
28 #include "wx/vector.h"
29 #include "wx/module.h"
30 #include "wx/hashmap.h"
32 using namespace wxPrivate
;
34 //-------------------------------------------------------------------------
35 // wxAnyValueTypeGlobals
36 //-------------------------------------------------------------------------
40 WX_DECLARE_HASH_MAP(wxAnyValueType
*,
44 wxAnyTypeToVariantDataFactoryMap
);
49 // Helper class to manage wxAnyValueType instances and and other
50 // related global variables (such as wxAny<->wxVariant type association).
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).
57 class wxAnyValueTypeGlobals
60 wxAnyValueTypeGlobals()
63 ~wxAnyValueTypeGlobals()
66 m_anyToVariant
.clear();
68 for ( size_t i
=0; i
<m_valueTypes
.size(); i
++ )
69 delete m_valueTypes
[i
];
72 void RegisterValueType(wxAnyValueType
* valueType
)
74 m_valueTypes
.push_back(valueType
);
78 void PreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
80 m_anyToVariantRegs
.push_back(reg
);
83 // Find wxVariantData factory function for given value type,
84 // (or compatible, if possible)
85 wxVariantDataFactory
FindVariantDataFactory(const wxAnyValueType
* type
)
87 wxAnyTypeToVariantDataFactoryMap
& anyToVariant
= m_anyToVariant
;
88 wxAnyTypeToVariantDataFactoryMap::const_iterator it
;
89 it
= anyToVariant
.find(type
);
90 if ( it
!= anyToVariant
.end() )
93 // Not found, handle pre-registrations
94 size_t i
= m_anyToVariantRegs
.size();
98 wxAnyToVariantRegistration
* reg
= m_anyToVariantRegs
[i
];
99 wxAnyValueType
* assocType
= reg
->GetAssociatedType();
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
106 anyToVariant
[assocType
] = reg
->GetFactory();
107 m_anyToVariantRegs
.erase( m_anyToVariantRegs
.begin() + i
);
112 it
= anyToVariant
.find(type
);
113 if ( it
!= anyToVariant
.end() )
116 // Finally, attempt to find a compatible type
117 for ( it
= anyToVariant
.begin(); it
!= anyToVariant
.end(); it
++ )
119 if ( type
->IsSameType(it
->first
) )
121 wxVariantDataFactory f
= it
->second
;
122 anyToVariant
[type
] = f
;
133 wxVector
<wxAnyValueType
*> m_valueTypes
;
135 wxAnyTypeToVariantDataFactoryMap m_anyToVariant
;
136 wxVector
<wxAnyToVariantRegistration
*> m_anyToVariantRegs
;
140 static wxAnyValueTypeGlobals
* g_wxAnyValueTypeGlobals
= NULL
;
144 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData
)
146 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
148 if ( !g_wxAnyValueTypeGlobals
)
149 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
150 g_wxAnyValueTypeGlobals
->PreRegisterAnyToVariant(reg
);
153 bool wxConvertAnyToVariant(const wxAny
& any
, wxVariant
* variant
)
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) )
169 if ( any
.GetAs(&ll
) )
172 *variant
= wxLongLong(ll
);
174 *variant
= (long) wxLongLong(ll
).GetLo();
190 // Find matching factory function
191 wxVariantDataFactory f
=
192 g_wxAnyValueTypeGlobals
->FindVariantDataFactory(any
.GetType());
194 wxVariantData
* data
= NULL
;
202 // Check if wxAny wrapped wxVariantData*
203 if ( !any
.GetAs(&data
) )
206 // Wrapper's GetValue() does not increase reference
207 // count, se have to do it before the data gets passed
212 variant
->SetData(data
);
216 #endif // wxUSE_VARIANT
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.
223 class wxAnyValueTypeGlobalsManager
: public wxModule
225 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
227 wxAnyValueTypeGlobalsManager() : wxModule() { }
228 virtual ~wxAnyValueTypeGlobalsManager() { }
230 virtual bool OnInit()
234 virtual void OnExit()
236 delete g_wxAnyValueTypeGlobals
;
237 g_wxAnyValueTypeGlobals
= NULL
;
242 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
245 //-------------------------------------------------------------------------
247 //-------------------------------------------------------------------------
249 wxAnyValueType::wxAnyValueType()
251 if ( !g_wxAnyValueTypeGlobals
)
252 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
254 g_wxAnyValueTypeGlobals
->RegisterValueType(this);
257 //-------------------------------------------------------------------------
258 // Dynamic conversion member functions
259 //-------------------------------------------------------------------------
262 // Define integer minimum and maximum as helpers
264 #define UseIntMin (wxINT64_MIN)
265 #define UseIntMax (wxINT64_MAX)
266 #define UseUintMax (wxUINT64_MAX)
268 #define UseIntMin (LONG_MIN)
269 #define UseIntMax (LONG_MAX)
270 #define UseUintMax (ULONG_MAX)
276 const double UseIntMinF
= static_cast<double>(UseIntMin
);
277 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
278 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
280 } // anonymous namespace
282 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
283 wxAnyValueType
* dstType
,
284 wxAnyValueBuffer
& dst
) const
286 wxAnyBaseIntType value
= GetValue(src
);
287 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
290 wxLongLong
ll(value
);
291 wxString s
= ll
.ToString();
293 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
295 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
297 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
301 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
302 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
304 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
306 double value2
= static_cast<double>(value
);
307 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
309 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
311 bool value2
= value
? true : false;
312 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
320 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
321 wxAnyValueType
* dstType
,
322 wxAnyValueBuffer
& dst
) const
324 wxAnyBaseUintType value
= GetValue(src
);
325 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
328 wxULongLong
ull(value
);
329 wxString s
= ull
.ToString();
331 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
333 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
335 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
337 if ( value
> UseIntMax
)
339 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
340 wxAnyValueTypeImplInt::SetValue(l
, dst
);
342 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
345 double value2
= static_cast<double>(value
);
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
);
351 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
353 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
355 bool value2
= value
? true : false;
356 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
364 bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer
& src
,
365 wxAnyValueType
* dstType
,
366 wxAnyValueBuffer
& dst
) const
368 wxString value
= GetValue(src
);
369 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
371 wxAnyBaseIntType value2
;
373 if ( !value
.ToLongLong(&value2
) )
375 if ( !value
.ToLong(&value2
) )
378 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
380 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
382 wxAnyBaseUintType value2
;
384 if ( !value
.ToULongLong(&value2
) )
386 if ( !value
.ToULong(&value2
) )
389 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
391 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
394 if ( !value
.ToDouble(&value2
) )
396 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
398 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
402 if ( value
== wxS("true") ||
403 value
== wxS("yes") ||
406 else if ( value
== wxS("false") ||
407 value
== wxS("no") ||
413 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
421 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
422 wxAnyValueType
* dstType
,
423 wxAnyValueBuffer
& dst
) const
425 bool value
= GetValue(src
);
426 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
428 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
429 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
431 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
433 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
434 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
436 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
443 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
451 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
452 wxAnyValueType
* dstType
,
453 wxAnyValueBuffer
& dst
) const
455 double value
= GetValue(src
);
456 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
458 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
460 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
461 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
463 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
465 if ( value
< 0.0 || value
> UseUintMaxF
)
467 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
468 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
470 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
472 wxString s
= wxString::Format(wxS("%.14g"), value
);
473 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
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
)
487 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
488 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
489 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
491 //-------------------------------------------------------------------------
492 // wxAnyNullValueType implementation
493 //-------------------------------------------------------------------------
502 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
504 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
506 // Dummy implementations
507 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
512 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
513 wxAnyValueBuffer
& dst
) const
519 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
520 wxAnyValueType
* dstType
,
521 wxAnyValueBuffer
& dst
) const
524 wxUnusedVar(dstType
);
532 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
534 wxAnyValueType
* wxAnyNullValueType
=
535 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();