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
) )
205 // Ok, one last chance: while unlikely, it is possible that the
206 // wxAny actually contains wxVariant.
207 if ( wxANY_CHECK_TYPE(any
, wxVariant
) )
208 *variant
= wxANY_AS(any
, wxVariant
);
212 // Wrapper's GetValue() does not increase reference
213 // count, se have to do it before the data gets passed
218 variant
->SetData(data
);
222 #endif // wxUSE_VARIANT
225 // This class is to make sure that wxAnyValueType instances
226 // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
227 // because wxModule itself is instantiated too late.
229 class wxAnyValueTypeGlobalsManager
: public wxModule
231 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
233 wxAnyValueTypeGlobalsManager() : wxModule() { }
234 virtual ~wxAnyValueTypeGlobalsManager() { }
236 virtual bool OnInit()
240 virtual void OnExit()
242 delete g_wxAnyValueTypeGlobals
;
243 g_wxAnyValueTypeGlobals
= NULL
;
248 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
251 //-------------------------------------------------------------------------
253 //-------------------------------------------------------------------------
255 wxAnyValueType::wxAnyValueType()
257 if ( !g_wxAnyValueTypeGlobals
)
258 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
260 g_wxAnyValueTypeGlobals
->RegisterValueType(this);
263 //-------------------------------------------------------------------------
264 // Dynamic conversion member functions
265 //-------------------------------------------------------------------------
268 // Define integer minimum and maximum as helpers
270 #define UseIntMin (wxINT64_MIN)
271 #define UseIntMax (wxINT64_MAX)
272 #define UseUintMax (wxUINT64_MAX)
274 #define UseIntMin (LONG_MIN)
275 #define UseIntMax (LONG_MAX)
276 #define UseUintMax (ULONG_MAX)
282 const double UseIntMinF
= static_cast<double>(UseIntMin
);
283 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
284 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
286 } // anonymous namespace
288 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
289 wxAnyValueType
* dstType
,
290 wxAnyValueBuffer
& dst
) const
292 wxAnyBaseIntType value
= GetValue(src
);
293 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
296 wxLongLong
ll(value
);
297 wxString s
= ll
.ToString();
299 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
301 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
303 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
307 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
308 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
310 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
312 double value2
= static_cast<double>(value
);
313 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
315 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
317 bool value2
= value
? true : false;
318 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
326 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
327 wxAnyValueType
* dstType
,
328 wxAnyValueBuffer
& dst
) const
330 wxAnyBaseUintType value
= GetValue(src
);
331 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
334 wxULongLong
ull(value
);
335 wxString s
= ull
.ToString();
337 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
339 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
341 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
343 if ( value
> UseIntMax
)
345 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
346 wxAnyValueTypeImplInt::SetValue(l
, dst
);
348 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
351 double value2
= static_cast<double>(value
);
353 // VC6 doesn't implement conversion from unsigned __int64 to double
354 wxAnyBaseIntType value0
= static_cast<wxAnyBaseIntType
>(value
);
355 double value2
= static_cast<double>(value0
);
357 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
359 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
361 bool value2
= value
? true : false;
362 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
370 bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer
& src
,
371 wxAnyValueType
* dstType
,
372 wxAnyValueBuffer
& dst
) const
374 wxString value
= GetValue(src
);
375 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
377 wxAnyBaseIntType value2
;
379 if ( !value
.ToLongLong(&value2
) )
381 if ( !value
.ToLong(&value2
) )
384 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
386 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
388 wxAnyBaseUintType value2
;
390 if ( !value
.ToULongLong(&value2
) )
392 if ( !value
.ToULong(&value2
) )
395 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
397 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
400 if ( !value
.ToDouble(&value2
) )
402 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
404 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
408 if ( value
== wxS("true") ||
409 value
== wxS("yes") ||
412 else if ( value
== wxS("false") ||
413 value
== wxS("no") ||
419 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
427 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
428 wxAnyValueType
* dstType
,
429 wxAnyValueBuffer
& dst
) const
431 bool value
= GetValue(src
);
432 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
434 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
435 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
437 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
439 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
440 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
442 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
449 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
457 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
458 wxAnyValueType
* dstType
,
459 wxAnyValueBuffer
& dst
) const
461 double value
= GetValue(src
);
462 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
464 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
466 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
467 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
469 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
471 if ( value
< 0.0 || value
> UseUintMaxF
)
473 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
474 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
476 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
478 wxString s
= wxString::Format(wxS("%.14g"), value
);
479 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
487 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
488 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
489 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
490 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
491 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
493 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
494 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
495 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
497 //-------------------------------------------------------------------------
498 // wxAnyNullValueType implementation
499 //-------------------------------------------------------------------------
508 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
510 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
512 // Dummy implementations
513 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
518 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
519 wxAnyValueBuffer
& dst
) const
525 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
526 wxAnyValueType
* dstType
,
527 wxAnyValueBuffer
& dst
) const
530 wxUnusedVar(dstType
);
538 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
540 wxAnyValueType
* wxAnyNullValueType
=
541 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();