1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/any.cpp
3 // Purpose: wxAny class, container for any type
4 // Author: Jaakko Salli
7 // Copyright: (c) wxWidgets team
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
27 #include "wx/vector.h"
28 #include "wx/module.h"
29 #include "wx/hashmap.h"
30 #include "wx/hashset.h"
32 using namespace wxPrivate
;
36 //-------------------------------------------------------------------------
37 // wxAnyValueTypeGlobals
38 //-------------------------------------------------------------------------
40 WX_DECLARE_HASH_MAP(wxAnyValueType
*,
44 wxAnyTypeToVariantDataFactoryMap
);
47 // Helper class to manage global variables related to type conversion
48 // between wxAny and wxVariant.
50 class wxAnyValueTypeGlobals
53 wxAnyValueTypeGlobals()
56 ~wxAnyValueTypeGlobals()
58 m_anyToVariant
.clear();
61 void PreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
63 m_anyToVariantRegs
.push_back(reg
);
66 // Find wxVariantData factory function for given value type,
67 // (or compatible, if possible)
68 wxVariantDataFactory
FindVariantDataFactory(const wxAnyValueType
* type_
)
70 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
71 // but WX_DECLARE_HASH_MAP() has some trouble with it.
72 wxAnyValueType
* type
= const_cast<wxAnyValueType
*>(type_
);
74 wxAnyTypeToVariantDataFactoryMap
& anyToVariant
= m_anyToVariant
;
75 wxAnyTypeToVariantDataFactoryMap::const_iterator it
;
76 it
= anyToVariant
.find(type
);
77 if ( it
!= anyToVariant
.end() )
80 // Not found, handle pre-registrations
81 size_t i
= m_anyToVariantRegs
.size();
85 wxAnyToVariantRegistration
* reg
= m_anyToVariantRegs
[i
];
86 wxAnyValueType
* assocType
= reg
->GetAssociatedType();
89 // Both variant data and wxAnyValueType have been
90 // now been properly initialized, so remove the
91 // pre-registration entry and move data to anyToVarian
93 anyToVariant
[assocType
] = reg
->GetFactory();
94 m_anyToVariantRegs
.erase( m_anyToVariantRegs
.begin() + i
);
99 it
= anyToVariant
.find(type
);
100 if ( it
!= anyToVariant
.end() )
103 // Finally, attempt to find a compatible type
104 for ( it
= anyToVariant
.begin(); it
!= anyToVariant
.end(); it
++ )
106 if ( type
->IsSameType(it
->first
) )
108 wxVariantDataFactory f
= it
->second
;
109 anyToVariant
[type
] = f
;
119 wxAnyTypeToVariantDataFactoryMap m_anyToVariant
;
120 wxVector
<wxAnyToVariantRegistration
*> m_anyToVariantRegs
;
123 static wxAnyValueTypeGlobals
* g_wxAnyValueTypeGlobals
= NULL
;
126 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData
)
128 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
130 if ( !g_wxAnyValueTypeGlobals
)
131 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
132 g_wxAnyValueTypeGlobals
->PreRegisterAnyToVariant(reg
);
135 bool wxConvertAnyToVariant(const wxAny
& any
, wxVariant
* variant
)
143 // (signed) integer is a special case, because there is only one type
144 // in wxAny, and two ("long" and "longlong") in wxVariant. For better
145 // backwards compatibility, convert all values that fit in "long",
146 // and others to "longlong".
147 if ( wxANY_CHECK_TYPE(any
, signed int) )
151 if ( any
.GetAs(&ll
) )
153 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
154 // integer constraint yields more consistent behaviour across
156 if ( ll
> wxINT32_MAX
|| ll
< wxINT32_MIN
)
157 *variant
= wxLongLong(ll
);
159 *variant
= (long) wxLongLong(ll
).GetLo();
175 // Find matching factory function
176 wxVariantDataFactory f
=
177 g_wxAnyValueTypeGlobals
->FindVariantDataFactory(any
.GetType());
179 wxVariantData
* data
= NULL
;
187 // Check if wxAny wrapped wxVariantData*
188 if ( !any
.GetAs(&data
) )
190 // Ok, one last chance: while unlikely, it is possible that the
191 // wxAny actually contains wxVariant.
192 if ( wxANY_CHECK_TYPE(any
, wxVariant
) )
193 *variant
= wxANY_AS(any
, wxVariant
);
197 // Wrapper's GetValue() does not increase reference
198 // count, se have to do it before the data gets passed
203 variant
->SetData(data
);
208 // This class is to make sure that wxAnyValueType instances
209 // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
210 // because wxModule itself is instantiated too late.
212 class wxAnyValueTypeGlobalsManager
: public wxModule
214 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
216 wxAnyValueTypeGlobalsManager() : wxModule() { }
217 virtual ~wxAnyValueTypeGlobalsManager() { }
219 virtual bool OnInit()
223 virtual void OnExit()
225 wxDELETE(g_wxAnyValueTypeGlobals
);
230 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
232 #endif // wxUSE_VARIANT
235 //-------------------------------------------------------------------------
236 // Dynamic conversion member functions
237 //-------------------------------------------------------------------------
240 // Define integer minimum and maximum as helpers
242 #define UseIntMin (wxINT64_MIN)
243 #define UseIntMax (wxINT64_MAX)
244 #define UseUintMax (wxUINT64_MAX)
246 #define UseIntMin (LONG_MIN)
247 #define UseIntMax (LONG_MAX)
248 #define UseUintMax (ULONG_MAX)
254 const double UseIntMinF
= static_cast<double>(UseIntMin
);
255 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
256 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
258 } // anonymous namespace
260 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
261 wxAnyValueType
* dstType
,
262 wxAnyValueBuffer
& dst
) const
264 wxAnyBaseIntType value
= GetValue(src
);
265 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
268 wxLongLong
ll(value
);
269 wxString s
= ll
.ToString();
271 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
273 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
275 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
279 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
280 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
282 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
284 double value2
= static_cast<double>(value
);
285 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
287 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
289 bool value2
= value
? true : false;
290 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
298 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
299 wxAnyValueType
* dstType
,
300 wxAnyValueBuffer
& dst
) const
302 wxAnyBaseUintType value
= GetValue(src
);
303 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
306 wxULongLong
ull(value
);
307 wxString s
= ull
.ToString();
309 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
311 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
313 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
315 if ( value
> UseIntMax
)
317 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
318 wxAnyValueTypeImplInt::SetValue(l
, dst
);
320 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
323 double value2
= static_cast<double>(value
);
325 // VC6 doesn't implement conversion from unsigned __int64 to double
326 wxAnyBaseIntType value0
= static_cast<wxAnyBaseIntType
>(value
);
327 double value2
= static_cast<double>(value0
);
329 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
331 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
333 bool value2
= value
? true : false;
334 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
342 // Convert wxString to destination wxAny value type
343 bool wxAnyConvertString(const wxString
& value
,
344 wxAnyValueType
* dstType
,
345 wxAnyValueBuffer
& dst
)
347 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
349 wxAnyValueTypeImpl
<wxString
>::SetValue(value
, dst
);
351 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
353 wxAnyBaseIntType value2
;
355 if ( !value
.ToLongLong(&value2
) )
357 if ( !value
.ToLong(&value2
) )
360 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
362 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
364 wxAnyBaseUintType value2
;
366 if ( !value
.ToULongLong(&value2
) )
368 if ( !value
.ToULong(&value2
) )
371 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
373 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
376 if ( !value
.ToCDouble(&value2
) )
378 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
380 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
385 if ( s
== wxS("true") ||
389 else if ( s
== wxS("false") ||
396 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
404 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
405 wxAnyValueType
* dstType
,
406 wxAnyValueBuffer
& dst
) const
408 bool value
= GetValue(src
);
409 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
411 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
412 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
414 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
416 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
417 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
419 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
426 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
434 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
435 wxAnyValueType
* dstType
,
436 wxAnyValueBuffer
& dst
) const
438 double value
= GetValue(src
);
439 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
441 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
443 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
444 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
446 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
448 if ( value
< 0.0 || value
> UseUintMaxF
)
450 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
451 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
453 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
455 wxString s
= wxString::FromCDouble(value
, 14);
456 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
464 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
465 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
469 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString
)
470 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr
)
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr
)
474 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
475 #endif // wxUSE_DATETIME
477 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
478 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
480 //-------------------------------------------------------------------------
481 // wxAnyNullValueType implementation
482 //-------------------------------------------------------------------------
487 // this field is unused, but can't be private to avoid Clang's
488 // "Private field 'm_dummy' is not used" warning
493 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
495 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
497 // Dummy implementations
498 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
503 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
504 wxAnyValueBuffer
& dst
) const
510 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
511 wxAnyValueType
* dstType
,
512 wxAnyValueBuffer
& dst
) const
515 wxUnusedVar(dstType
);
520 #if wxUSE_EXTENDED_RTTI
521 virtual const wxTypeInfo
* GetTypeInfo() const
523 wxFAIL_MSG("Null Type Info not available");
531 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
533 wxAnyValueType
* wxAnyNullValueType
=
534 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();
536 #include "wx/listimpl.cpp"
537 WX_DEFINE_LIST(wxAnyList
)