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"
31 #include "wx/hashset.h"
33 using namespace wxPrivate
;
37 //-------------------------------------------------------------------------
38 // wxAnyValueTypeGlobals
39 //-------------------------------------------------------------------------
41 WX_DECLARE_HASH_MAP(wxAnyValueType
*,
45 wxAnyTypeToVariantDataFactoryMap
);
48 // Helper class to manage global variables related to type conversion
49 // between wxAny and wxVariant.
51 class wxAnyValueTypeGlobals
54 wxAnyValueTypeGlobals()
57 ~wxAnyValueTypeGlobals()
59 m_anyToVariant
.clear();
62 void PreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
64 m_anyToVariantRegs
.push_back(reg
);
67 // Find wxVariantData factory function for given value type,
68 // (or compatible, if possible)
69 wxVariantDataFactory
FindVariantDataFactory(const wxAnyValueType
* type_
)
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_
);
75 wxAnyTypeToVariantDataFactoryMap
& anyToVariant
= m_anyToVariant
;
76 wxAnyTypeToVariantDataFactoryMap::const_iterator it
;
77 it
= anyToVariant
.find(type
);
78 if ( it
!= anyToVariant
.end() )
81 // Not found, handle pre-registrations
82 size_t i
= m_anyToVariantRegs
.size();
86 wxAnyToVariantRegistration
* reg
= m_anyToVariantRegs
[i
];
87 wxAnyValueType
* assocType
= reg
->GetAssociatedType();
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
94 anyToVariant
[assocType
] = reg
->GetFactory();
95 m_anyToVariantRegs
.erase( m_anyToVariantRegs
.begin() + i
);
100 it
= anyToVariant
.find(type
);
101 if ( it
!= anyToVariant
.end() )
104 // Finally, attempt to find a compatible type
105 for ( it
= anyToVariant
.begin(); it
!= anyToVariant
.end(); it
++ )
107 if ( type
->IsSameType(it
->first
) )
109 wxVariantDataFactory f
= it
->second
;
110 anyToVariant
[type
] = f
;
120 wxAnyTypeToVariantDataFactoryMap m_anyToVariant
;
121 wxVector
<wxAnyToVariantRegistration
*> m_anyToVariantRegs
;
124 static wxAnyValueTypeGlobals
* g_wxAnyValueTypeGlobals
= NULL
;
127 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData
)
129 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
131 if ( !g_wxAnyValueTypeGlobals
)
132 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
133 g_wxAnyValueTypeGlobals
->PreRegisterAnyToVariant(reg
);
136 bool wxConvertAnyToVariant(const wxAny
& any
, wxVariant
* variant
)
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) )
152 if ( any
.GetAs(&ll
) )
154 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
155 // integer constraint yields more consistent behaviour across
157 if ( ll
> wxINT32_MAX
|| ll
< wxINT32_MIN
)
158 *variant
= wxLongLong(ll
);
160 *variant
= (long) wxLongLong(ll
).GetLo();
176 // Find matching factory function
177 wxVariantDataFactory f
=
178 g_wxAnyValueTypeGlobals
->FindVariantDataFactory(any
.GetType());
180 wxVariantData
* data
= NULL
;
188 // Check if wxAny wrapped wxVariantData*
189 if ( !any
.GetAs(&data
) )
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
);
198 // Wrapper's GetValue() does not increase reference
199 // count, se have to do it before the data gets passed
204 variant
->SetData(data
);
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.
213 class wxAnyValueTypeGlobalsManager
: public wxModule
215 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
217 wxAnyValueTypeGlobalsManager() : wxModule() { }
218 virtual ~wxAnyValueTypeGlobalsManager() { }
220 virtual bool OnInit()
224 virtual void OnExit()
226 wxDELETE(g_wxAnyValueTypeGlobals
);
231 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
233 #endif // wxUSE_VARIANT
236 //-------------------------------------------------------------------------
237 // Dynamic conversion member functions
238 //-------------------------------------------------------------------------
241 // Define integer minimum and maximum as helpers
243 #define UseIntMin (wxINT64_MIN)
244 #define UseIntMax (wxINT64_MAX)
245 #define UseUintMax (wxUINT64_MAX)
247 #define UseIntMin (LONG_MIN)
248 #define UseIntMax (LONG_MAX)
249 #define UseUintMax (ULONG_MAX)
255 const double UseIntMinF
= static_cast<double>(UseIntMin
);
256 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
257 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
259 } // anonymous namespace
261 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
262 wxAnyValueType
* dstType
,
263 wxAnyValueBuffer
& dst
) const
265 wxAnyBaseIntType value
= GetValue(src
);
266 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
269 wxLongLong
ll(value
);
270 wxString s
= ll
.ToString();
272 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
274 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
276 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
280 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
281 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
283 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
285 double value2
= static_cast<double>(value
);
286 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
288 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
290 bool value2
= value
? true : false;
291 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
299 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
300 wxAnyValueType
* dstType
,
301 wxAnyValueBuffer
& dst
) const
303 wxAnyBaseUintType value
= GetValue(src
);
304 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
307 wxULongLong
ull(value
);
308 wxString s
= ull
.ToString();
310 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
312 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
314 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
316 if ( value
> UseIntMax
)
318 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
319 wxAnyValueTypeImplInt::SetValue(l
, dst
);
321 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
324 double value2
= static_cast<double>(value
);
326 // VC6 doesn't implement conversion from unsigned __int64 to double
327 wxAnyBaseIntType value0
= static_cast<wxAnyBaseIntType
>(value
);
328 double value2
= static_cast<double>(value0
);
330 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
332 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
334 bool value2
= value
? true : false;
335 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
343 // Convert wxString to destination wxAny value type
344 bool wxAnyConvertString(const wxString
& value
,
345 wxAnyValueType
* dstType
,
346 wxAnyValueBuffer
& dst
)
348 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
350 wxAnyValueTypeImpl
<wxString
>::SetValue(value
, dst
);
352 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
354 wxAnyBaseIntType value2
;
356 if ( !value
.ToLongLong(&value2
) )
358 if ( !value
.ToLong(&value2
) )
361 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
363 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
365 wxAnyBaseUintType value2
;
367 if ( !value
.ToULongLong(&value2
) )
369 if ( !value
.ToULong(&value2
) )
372 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
374 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
377 if ( !value
.ToCDouble(&value2
) )
379 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
381 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
386 if ( s
== wxS("true") ||
390 else if ( s
== wxS("false") ||
397 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
405 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
406 wxAnyValueType
* dstType
,
407 wxAnyValueBuffer
& dst
) const
409 bool value
= GetValue(src
);
410 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
412 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
413 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
415 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
417 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
418 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
420 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
427 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
435 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
436 wxAnyValueType
* dstType
,
437 wxAnyValueBuffer
& dst
) const
439 double value
= GetValue(src
);
440 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
442 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
444 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
445 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
447 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
449 if ( value
< 0.0 || value
> UseUintMaxF
)
451 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
452 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
454 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
456 wxString s
= wxString::FromCDouble(value
, 14);
457 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
465 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
468 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
470 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString
)
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr
)
472 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr
)
475 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
476 #endif // wxUSE_DATETIME
478 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
479 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
481 //-------------------------------------------------------------------------
482 // wxAnyNullValueType implementation
483 //-------------------------------------------------------------------------
492 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
494 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
496 // Dummy implementations
497 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
502 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
503 wxAnyValueBuffer
& dst
) const
509 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
510 wxAnyValueType
* dstType
,
511 wxAnyValueBuffer
& dst
) const
514 wxUnusedVar(dstType
);
519 #if wxUSE_EXTENDED_RTTI
520 virtual const wxTypeInfo
* GetTypeInfo() const
522 wxFAIL_MSG("Null Type Info not available");
530 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
532 wxAnyValueType
* wxAnyNullValueType
=
533 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();
535 #include "wx/listimpl.cpp"
536 WX_DEFINE_LIST(wxAnyList
)