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 behavior 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 delete g_wxAnyValueTypeGlobals
;
227 g_wxAnyValueTypeGlobals
= NULL
;
232 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
234 #endif // wxUSE_VARIANT
237 //-------------------------------------------------------------------------
238 // Dynamic conversion member functions
239 //-------------------------------------------------------------------------
242 // Define integer minimum and maximum as helpers
244 #define UseIntMin (wxINT64_MIN)
245 #define UseIntMax (wxINT64_MAX)
246 #define UseUintMax (wxUINT64_MAX)
248 #define UseIntMin (LONG_MIN)
249 #define UseIntMax (LONG_MAX)
250 #define UseUintMax (ULONG_MAX)
256 const double UseIntMinF
= static_cast<double>(UseIntMin
);
257 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
258 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
260 } // anonymous namespace
262 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
263 wxAnyValueType
* dstType
,
264 wxAnyValueBuffer
& dst
) const
266 wxAnyBaseIntType value
= GetValue(src
);
267 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
270 wxLongLong
ll(value
);
271 wxString s
= ll
.ToString();
273 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
275 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
277 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
281 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
282 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
284 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
286 double value2
= static_cast<double>(value
);
287 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
289 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
291 bool value2
= value
? true : false;
292 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
300 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
301 wxAnyValueType
* dstType
,
302 wxAnyValueBuffer
& dst
) const
304 wxAnyBaseUintType value
= GetValue(src
);
305 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
308 wxULongLong
ull(value
);
309 wxString s
= ull
.ToString();
311 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
313 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
315 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
317 if ( value
> UseIntMax
)
319 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
320 wxAnyValueTypeImplInt::SetValue(l
, dst
);
322 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
325 double value2
= static_cast<double>(value
);
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
);
331 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
333 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
335 bool value2
= value
? true : false;
336 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
344 // Convert wxString to destination wxAny value type
345 bool wxAnyConvertString(const wxString
& value
,
346 wxAnyValueType
* dstType
,
347 wxAnyValueBuffer
& dst
)
349 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
351 wxAnyValueTypeImpl
<wxString
>::SetValue(value
, dst
);
353 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
355 wxAnyBaseIntType value2
;
357 if ( !value
.ToLongLong(&value2
) )
359 if ( !value
.ToLong(&value2
) )
362 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
364 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
366 wxAnyBaseUintType value2
;
368 if ( !value
.ToULongLong(&value2
) )
370 if ( !value
.ToULong(&value2
) )
373 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
375 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
378 if ( !value
.ToDouble(&value2
) )
380 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
382 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
387 if ( s
== wxS("true") ||
391 else if ( s
== wxS("false") ||
398 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
406 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
407 wxAnyValueType
* dstType
,
408 wxAnyValueBuffer
& dst
) const
410 bool value
= GetValue(src
);
411 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
413 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
414 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
416 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
418 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
419 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
421 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
428 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
436 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
437 wxAnyValueType
* dstType
,
438 wxAnyValueBuffer
& dst
) const
440 double value
= GetValue(src
);
441 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
443 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
445 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
446 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
448 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
450 if ( value
< 0.0 || value
> UseUintMaxF
)
452 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
453 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
455 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
457 wxString s
= wxString::Format(wxS("%.14g"), value
);
458 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
468 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
469 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString
)
472 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr
)
473 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr
)
475 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
476 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
477 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
479 //-------------------------------------------------------------------------
480 // wxAnyNullValueType implementation
481 //-------------------------------------------------------------------------
490 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
492 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
494 // Dummy implementations
495 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
500 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
501 wxAnyValueBuffer
& dst
) const
507 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
508 wxAnyValueType
* dstType
,
509 wxAnyValueBuffer
& dst
) const
512 wxUnusedVar(dstType
);
520 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
522 wxAnyValueType
* wxAnyNullValueType
=
523 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();