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 // Convert wxString to destination wxAny value type
378 bool wxAnyConvertString(const wxString
& value
,
379 wxAnyValueType
* dstType
,
380 wxAnyValueBuffer
& dst
)
382 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
384 wxAnyValueTypeImpl
<wxString
>::SetValue(value
, dst
);
386 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
388 wxAnyBaseIntType value2
;
390 if ( !value
.ToLongLong(&value2
) )
392 if ( !value
.ToLong(&value2
) )
395 wxAnyValueTypeImplInt
::SetValue(value2
, dst
);
397 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
399 wxAnyBaseUintType value2
;
401 if ( !value
.ToULongLong(&value2
) )
403 if ( !value
.ToULong(&value2
) )
406 wxAnyValueTypeImplUint
::SetValue(value2
, dst
);
408 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, double) )
411 if ( !value
.ToDouble(&value2
) )
413 wxAnyValueTypeImplDouble
::SetValue(value2
, dst
);
415 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, bool) )
420 if ( s
== wxS("true") ||
424 else if ( s
== wxS("false") ||
431 wxAnyValueTypeImpl
<bool>::SetValue(value2
, dst
);
439 bool wxAnyValueTypeImpl
<bool>::ConvertValue(const wxAnyValueBuffer
& src
,
440 wxAnyValueType
* dstType
,
441 wxAnyValueBuffer
& dst
) const
443 bool value
= GetValue(src
);
444 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
446 wxAnyBaseIntType value2
= static_cast<wxAnyBaseIntType
>(value
);
447 wxAnyValueTypeImplInt
::SetValue(value2
, dst
);
449 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
451 wxAnyBaseIntType value2
= static_cast<wxAnyBaseUintType
>(value
);
452 wxAnyValueTypeImplUint
::SetValue(value2
, dst
);
454 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
461 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
469 bool wxAnyValueTypeImplDouble
::ConvertValue(const wxAnyValueBuffer
& src
,
470 wxAnyValueType
* dstType
,
471 wxAnyValueBuffer
& dst
) const
473 double value
= GetValue(src
);
474 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseIntType
) )
476 if ( value
< UseIntMinF
|| value
> UseIntMaxF
)
478 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
479 wxAnyValueTypeImplUint
::SetValue(ul
, dst
);
481 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxAnyBaseUintType
) )
483 if ( value
< 0.0 || value
> UseUintMaxF
)
485 wxAnyBaseUintType ul
= static_cast<wxAnyBaseUintType
>(value
);
486 wxAnyValueTypeImplUint
::SetValue(ul
, dst
);
488 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType
, wxString
) )
490 wxString s
= wxString
::Format(wxS("%.14g"), value
);
491 wxAnyValueTypeImpl
<wxString
>::SetValue(s
, dst
);
499 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt
)
500 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint
)
501 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<bool>)
502 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble
)
504 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString
)
505 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr
)
506 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr
)
508 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxDateTime
>)
509 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
510 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
512 //-------------------------------------------------------------------------
513 // wxAnyNullValueType implementation
514 //-------------------------------------------------------------------------
523 class wxAnyValueTypeImpl
<wxAnyNullValue
> : public wxAnyValueType
525 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
527 // Dummy implementations
528 virtual void DeleteValue(wxAnyValueBuffer
& buf
) const
533 virtual void CopyBuffer(const wxAnyValueBuffer
& src
,
534 wxAnyValueBuffer
& dst
) const
540 virtual bool ConvertValue(const wxAnyValueBuffer
& src
,
541 wxAnyValueType
* dstType
,
542 wxAnyValueBuffer
& dst
) const
545 wxUnusedVar(dstType
);
553 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl
<wxAnyNullValue
>)
555 wxAnyValueType
* wxAnyNullValueType
=
556 wxAnyValueTypeImpl
<wxAnyNullValue
>::GetInstance();