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 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
88 // but WX_DECLARE_HASH_MAP() has some trouble with it.
89 wxAnyValueType
* type
= const_cast<wxAnyValueType
*>(type_
);
91 wxAnyTypeToVariantDataFactoryMap
& anyToVariant
= m_anyToVariant
;
92 wxAnyTypeToVariantDataFactoryMap::const_iterator it
;
93 it
= anyToVariant
.find(type
);
94 if ( it
!= anyToVariant
.end() )
97 // Not found, handle pre-registrations
98 size_t i
= m_anyToVariantRegs
.size();
102 wxAnyToVariantRegistration
* reg
= m_anyToVariantRegs
[i
];
103 wxAnyValueType
* assocType
= reg
->GetAssociatedType();
106 // Both variant data and wxAnyValueType have been
107 // now been properly initialized, so remove the
108 // pre-registration entry and move data to anyToVarian
110 anyToVariant
[assocType
] = reg
->GetFactory();
111 m_anyToVariantRegs
.erase( m_anyToVariantRegs
.begin() + i
);
116 it
= anyToVariant
.find(type
);
117 if ( it
!= anyToVariant
.end() )
120 // Finally, attempt to find a compatible type
121 for ( it
= anyToVariant
.begin(); it
!= anyToVariant
.end(); it
++ )
123 if ( type
->IsSameType(it
->first
) )
125 wxVariantDataFactory f
= it
->second
;
126 anyToVariant
[type
] = f
;
137 wxVector
<wxAnyValueType
*> m_valueTypes
;
139 wxAnyTypeToVariantDataFactoryMap m_anyToVariant
;
140 wxVector
<wxAnyToVariantRegistration
*> m_anyToVariantRegs
;
144 static wxAnyValueTypeGlobals
* g_wxAnyValueTypeGlobals
= NULL
;
148 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData
)
150 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration
* reg
)
152 if ( !g_wxAnyValueTypeGlobals
)
153 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
154 g_wxAnyValueTypeGlobals
->PreRegisterAnyToVariant(reg
);
157 bool wxConvertAnyToVariant(const wxAny
& any
, wxVariant
* variant
)
165 // (signed) integer is a special case, because there is only one type
166 // in wxAny, and two ("long" and "longlong") in wxVariant. For better
167 // backwards compatibility, convert all values that fit in "long",
168 // and others to "longlong".
169 if ( wxANY_CHECK_TYPE(any
, signed int) )
173 if ( any
.GetAs(&ll
) )
175 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
176 // integer constraint yields more consistent behavior across
178 if ( ll
> wxINT32_MAX
|| ll
< wxINT32_MIN
)
179 *variant
= wxLongLong(ll
);
181 *variant
= (long) wxLongLong(ll
).GetLo();
197 // Find matching factory function
198 wxVariantDataFactory f
=
199 g_wxAnyValueTypeGlobals
->FindVariantDataFactory(any
.GetType());
201 wxVariantData
* data
= NULL
;
209 // Check if wxAny wrapped wxVariantData*
210 if ( !any
.GetAs(&data
) )
212 // Ok, one last chance: while unlikely, it is possible that the
213 // wxAny actually contains wxVariant.
214 if ( wxANY_CHECK_TYPE(any
, wxVariant
) )
215 *variant
= wxANY_AS(any
, wxVariant
);
219 // Wrapper's GetValue() does not increase reference
220 // count, se have to do it before the data gets passed
225 variant
->SetData(data
);
229 #endif // wxUSE_VARIANT
232 // This class is to make sure that wxAnyValueType instances
233 // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
234 // because wxModule itself is instantiated too late.
236 class wxAnyValueTypeGlobalsManager
: public wxModule
238 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
240 wxAnyValueTypeGlobalsManager() : wxModule() { }
241 virtual ~wxAnyValueTypeGlobalsManager() { }
243 virtual bool OnInit()
247 virtual void OnExit()
249 delete g_wxAnyValueTypeGlobals
;
250 g_wxAnyValueTypeGlobals
= NULL
;
255 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
258 //-------------------------------------------------------------------------
260 //-------------------------------------------------------------------------
262 wxAnyValueType::wxAnyValueType()
264 if ( !g_wxAnyValueTypeGlobals
)
265 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
267 g_wxAnyValueTypeGlobals
->RegisterValueType(this);
270 //-------------------------------------------------------------------------
271 // Dynamic conversion member functions
272 //-------------------------------------------------------------------------
275 // Define integer minimum and maximum as helpers
277 #define UseIntMin (wxINT64_MIN)
278 #define UseIntMax (wxINT64_MAX)
279 #define UseUintMax (wxUINT64_MAX)
281 #define UseIntMin (LONG_MIN)
282 #define UseIntMax (LONG_MAX)
283 #define UseUintMax (ULONG_MAX)
289 const double UseIntMinF
= static_cast<double>(UseIntMin
);
290 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
291 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
293 } // anonymous namespace
295 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
296 wxAnyValueType
* dstType
,
297 wxAnyValueBuffer
& dst
) const
299 wxAnyBaseIntType value
= GetValue(src
);
300 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
303 wxLongLong
ll(value
);
304 wxString s
= ll
.ToString();
306 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
308 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
310 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
314 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
315 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
317 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
319 double value2
= static_cast<double>(value
);
320 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
322 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
324 bool value2
= value
? true : false;
325 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
333 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
334 wxAnyValueType
* dstType
,
335 wxAnyValueBuffer
& dst
) const
337 wxAnyBaseUintType value
= GetValue(src
);
338 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
341 wxULongLong
ull(value
);
342 wxString s
= ull
.ToString();
344 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
346 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
348 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
350 if ( value
> UseIntMax
)
352 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
353 wxAnyValueTypeImplInt::SetValue(l
, dst
);
355 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
358 double value2
= static_cast<double>(value
);
360 // VC6 doesn't implement conversion from unsigned __int64 to double
361 wxAnyBaseIntType value0
= static_cast<wxAnyBaseIntType
>(value
);
362 double value2
= static_cast<double>(value0
);
364 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
366 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
368 bool value2
= value
? true : false;
369 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
377 bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer
& src
,
378 wxAnyValueType
* dstType
,
379 wxAnyValueBuffer
& dst
) const
381 wxString value
= GetValue(src
);
382 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
384 wxAnyBaseIntType value2
;
386 if ( !value
.ToLongLong(&value2
) )
388 if ( !value
.ToLong(&value2
) )
391 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
393 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
395 wxAnyBaseUintType value2
;
397 if ( !value
.ToULongLong(&value2
) )
399 if ( !value
.ToULong(&value2
) )
402 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
404 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
407 if ( !value
.ToDouble(&value2
) )
409 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
411 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
415 if ( value
== wxS("true") ||
416 value
== wxS("yes") ||
419 else if ( value
== wxS("false") ||
420 value
== wxS("no") ||
426 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
434 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
435 wxAnyValueType
* dstType
,
436 wxAnyValueBuffer
& dst
) const
438 bool value
= GetValue(src
);
439 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
441 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
442 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
444 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
446 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
447 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
449 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
456 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
464 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
465 wxAnyValueType
* dstType
,
466 wxAnyValueBuffer
& dst
) const
468 double value
= GetValue(src
);
469 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
471 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
473 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
474 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
476 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
478 if ( value
< 0.0 || value
> UseUintMaxF
)
480 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
481 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
483 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
485 wxString s
= wxString::Format(wxS("%.14g"), value
);
486 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
494 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
495 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
496 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
497 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
498 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
500 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
501 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
502 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
504 //-------------------------------------------------------------------------
505 // wxAnyNullValueType implementation
506 //-------------------------------------------------------------------------
515 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
517 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
519 // Dummy implementations
520 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
525 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
526 wxAnyValueBuffer
& dst
) const
532 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
533 wxAnyValueType
* dstType
,
534 wxAnyValueBuffer
& dst
) const
537 wxUnusedVar(dstType
);
545 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
547 wxAnyValueType
* wxAnyNullValueType
=
548 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();