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
) )
176 *variant
= wxLongLong(ll
);
178 *variant
= (long) wxLongLong(ll
).GetLo();
194 // Find matching factory function
195 wxVariantDataFactory f
=
196 g_wxAnyValueTypeGlobals
->FindVariantDataFactory(any
.GetType());
198 wxVariantData
* data
= NULL
;
206 // Check if wxAny wrapped wxVariantData*
207 if ( !any
.GetAs(&data
) )
209 // Ok, one last chance: while unlikely, it is possible that the
210 // wxAny actually contains wxVariant.
211 if ( wxANY_CHECK_TYPE(any
, wxVariant
) )
212 *variant
= wxANY_AS(any
, wxVariant
);
216 // Wrapper's GetValue() does not increase reference
217 // count, se have to do it before the data gets passed
222 variant
->SetData(data
);
226 #endif // wxUSE_VARIANT
229 // This class is to make sure that wxAnyValueType instances
230 // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
231 // because wxModule itself is instantiated too late.
233 class wxAnyValueTypeGlobalsManager
: public wxModule
235 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
)
237 wxAnyValueTypeGlobalsManager() : wxModule() { }
238 virtual ~wxAnyValueTypeGlobalsManager() { }
240 virtual bool OnInit()
244 virtual void OnExit()
246 delete g_wxAnyValueTypeGlobals
;
247 g_wxAnyValueTypeGlobals
= NULL
;
252 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager
, wxModule
)
255 //-------------------------------------------------------------------------
257 //-------------------------------------------------------------------------
259 wxAnyValueType::wxAnyValueType()
261 if ( !g_wxAnyValueTypeGlobals
)
262 g_wxAnyValueTypeGlobals
= new wxAnyValueTypeGlobals();
264 g_wxAnyValueTypeGlobals
->RegisterValueType(this);
267 //-------------------------------------------------------------------------
268 // Dynamic conversion member functions
269 //-------------------------------------------------------------------------
272 // Define integer minimum and maximum as helpers
274 #define UseIntMin (wxINT64_MIN)
275 #define UseIntMax (wxINT64_MAX)
276 #define UseUintMax (wxUINT64_MAX)
278 #define UseIntMin (LONG_MIN)
279 #define UseIntMax (LONG_MAX)
280 #define UseUintMax (ULONG_MAX)
286 const double UseIntMinF
= static_cast<double>(UseIntMin
);
287 const double UseIntMaxF
= static_cast<double>(UseIntMax
);
288 const double UseUintMaxF
= static_cast<double>(UseUintMax
);
290 } // anonymous namespace
292 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer
& src
,
293 wxAnyValueType
* dstType
,
294 wxAnyValueBuffer
& dst
) const
296 wxAnyBaseIntType value
= GetValue(src
);
297 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
300 wxLongLong
ll(value
);
301 wxString s
= ll
.ToString();
303 wxString s
= wxString::Format(wxS("%ld"), (long)value
);
305 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
307 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
311 wxAnyBaseUintType ul
= (wxAnyBaseUintType
) value
;
312 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
314 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
316 double value2
= static_cast<double>(value
);
317 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
319 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
321 bool value2
= value
? true : false;
322 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
330 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer
& src
,
331 wxAnyValueType
* dstType
,
332 wxAnyValueBuffer
& dst
) const
334 wxAnyBaseUintType value
= GetValue(src
);
335 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
338 wxULongLong
ull(value
);
339 wxString s
= ull
.ToString();
341 wxString s
= wxString::Format(wxS("%lu"), (long)value
);
343 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
345 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
347 if ( value
> UseIntMax
)
349 wxAnyBaseIntType l
= (wxAnyBaseIntType
) value
;
350 wxAnyValueTypeImplInt::SetValue(l
, dst
);
352 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
355 double value2
= static_cast<double>(value
);
357 // VC6 doesn't implement conversion from unsigned __int64 to double
358 wxAnyBaseIntType value0
= static_cast<wxAnyBaseIntType
>(value
);
359 double value2
= static_cast<double>(value0
);
361 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
363 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
365 bool value2
= value
? true : false;
366 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
374 bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer
& src
,
375 wxAnyValueType
* dstType
,
376 wxAnyValueBuffer
& dst
) const
378 wxString value
= GetValue(src
);
379 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
381 wxAnyBaseIntType value2
;
383 if ( !value
.ToLongLong(&value2
) )
385 if ( !value
.ToLong(&value2
) )
388 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
390 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
392 wxAnyBaseUintType value2
;
394 if ( !value
.ToULongLong(&value2
) )
396 if ( !value
.ToULong(&value2
) )
399 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
401 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
404 if ( !value
.ToDouble(&value2
) )
406 wxAnyValueTypeImplDouble::SetValue(value2
, dst
);
408 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
412 if ( value
== wxS("true") ||
413 value
== wxS("yes") ||
416 else if ( value
== wxS("false") ||
417 value
== wxS("no") ||
423 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
431 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
432 wxAnyValueType
* dstType
,
433 wxAnyValueBuffer
& dst
) const
435 bool value
= GetValue(src
);
436 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
438 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
439 wxAnyValueTypeImplInt::SetValue(value2
, dst
);
441 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
443 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
444 wxAnyValueTypeImplUint::SetValue(value2
, dst
);
446 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
453 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
461 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer
& src
,
462 wxAnyValueType
* dstType
,
463 wxAnyValueBuffer
& dst
) const
465 double value
= GetValue(src
);
466 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
468 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
470 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
471 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
473 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
475 if ( value
< 0.0 || value
> UseUintMaxF
)
477 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
478 wxAnyValueTypeImplUint::SetValue(ul
, dst
);
480 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
482 wxString s
= wxString::Format(wxS("%.14g"), value
);
483 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
491 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
492 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
493 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString
)
494 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
495 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
497 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
498 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
499 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
501 //-------------------------------------------------------------------------
502 // wxAnyNullValueType implementation
503 //-------------------------------------------------------------------------
512 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
514 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
516 // Dummy implementations
517 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
522 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
523 wxAnyValueBuffer
& dst
) const
529 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
530 wxAnyValueType
* dstType
,
531 wxAnyValueBuffer
& dst
) const
534 wxUnusedVar(dstType
);
542 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
544 wxAnyValueType
* wxAnyNullValueType
=
545 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();