]> git.saurik.com Git - wxWidgets.git/blame - src/common/any.cpp
Use '+' in accelerators, not '-'.
[wxWidgets.git] / src / common / any.cpp
CommitLineData
39601a7f
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/any.cpp
3// Purpose: wxAny class, container for any type
4// Author: Jaakko Salli
5// Modified by:
6// Created: 07/05/2009
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#include "wx/any.h"
20
21#if wxUSE_ANY
22
23#ifndef WX_PRECOMP
24 #include "wx/math.h"
25 #include "wx/crt.h"
26#endif
27
28#include "wx/vector.h"
29#include "wx/module.h"
0bf14ab8 30#include "wx/hashmap.h"
39601a7f
VZ
31
32using namespace wxPrivate;
33
34//-------------------------------------------------------------------------
35// wxAnyValueTypeGlobals
36//-------------------------------------------------------------------------
37
0bf14ab8
JS
38#if wxUSE_VARIANT
39
40WX_DECLARE_HASH_MAP(wxAnyValueType*,
41 wxVariantDataFactory,
42 wxPointerHash,
43 wxPointerEqual,
44 wxAnyTypeToVariantDataFactoryMap);
45
46#endif
47
39601a7f 48//
0bf14ab8
JS
49// Helper class to manage wxAnyValueType instances and and other
50// related global variables (such as wxAny<->wxVariant type association).
39601a7f
VZ
51//
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).
56//
57class wxAnyValueTypeGlobals
58{
59public:
60 wxAnyValueTypeGlobals()
61 {
62 }
63 ~wxAnyValueTypeGlobals()
64 {
0bf14ab8
JS
65 #if wxUSE_VARIANT
66 m_anyToVariant.clear();
67 #endif
39601a7f
VZ
68 for ( size_t i=0; i<m_valueTypes.size(); i++ )
69 delete m_valueTypes[i];
70 }
71
72 void RegisterValueType(wxAnyValueType* valueType)
73 {
74 m_valueTypes.push_back(valueType);
75 }
76
0bf14ab8
JS
77#if wxUSE_VARIANT
78 void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
79 {
80 m_anyToVariantRegs.push_back(reg);
81 }
82
83 // Find wxVariantData factory function for given value type,
84 // (or compatible, if possible)
549d99f0 85 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_)
0bf14ab8 86 {
549d99f0 87 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
dabf03b4
JS
88 // but WX_DECLARE_HASH_MAP() has some trouble with it.
89 wxAnyValueType* type = const_cast<wxAnyValueType*>(type_);
549d99f0 90
0bf14ab8
JS
91 wxAnyTypeToVariantDataFactoryMap& anyToVariant = m_anyToVariant;
92 wxAnyTypeToVariantDataFactoryMap::const_iterator it;
93 it = anyToVariant.find(type);
94 if ( it != anyToVariant.end() )
95 return it->second;
96
97 // Not found, handle pre-registrations
98 size_t i = m_anyToVariantRegs.size();
99 while ( i > 0 )
100 {
101 i--;
102 wxAnyToVariantRegistration* reg = m_anyToVariantRegs[i];
103 wxAnyValueType* assocType = reg->GetAssociatedType();
104 if ( assocType )
105 {
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
109 // map.
110 anyToVariant[assocType] = reg->GetFactory();
111 m_anyToVariantRegs.erase( m_anyToVariantRegs.begin() + i );
112 }
113 }
114
115 // Then try again
116 it = anyToVariant.find(type);
117 if ( it != anyToVariant.end() )
118 return it->second;
119
120 // Finally, attempt to find a compatible type
121 for ( it = anyToVariant.begin(); it != anyToVariant.end(); it++ )
122 {
123 if ( type->IsSameType(it->first) )
124 {
125 wxVariantDataFactory f = it->second;
126 anyToVariant[type] = f;
127 return f;
128 }
129 }
130
131 // Nothing found
132 return NULL;
133 }
134#endif
135
39601a7f 136private:
0bf14ab8
JS
137 wxVector<wxAnyValueType*> m_valueTypes;
138#if wxUSE_VARIANT
139 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
140 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
141#endif
39601a7f
VZ
142};
143
144static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
145
0bf14ab8
JS
146#if wxUSE_VARIANT
147
148WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
149
150void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
151{
152 if ( !g_wxAnyValueTypeGlobals )
153 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
154 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
155}
156
157bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant)
158{
159 if ( any.IsNull() )
160 {
161 variant->MakeNull();
162 return true;
163 }
164
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) )
170 {
171#ifdef wxLongLong_t
5afecf60 172 wxLongLong_t ll = 0;
0bf14ab8
JS
173 if ( any.GetAs(&ll) )
174 {
4403de76
JS
175 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
176 // integer constraint yields more consistent behavior across
177 // builds.
2dcd173e 178 if ( ll > wxINT32_MAX || ll < wxINT32_MIN )
0bf14ab8
JS
179 *variant = wxLongLong(ll);
180 else
181 *variant = (long) wxLongLong(ll).GetLo();
182 }
183 else
184 {
185 return false;
186 }
187#else
188 long l;
189 if ( any.GetAs(&l) )
190 *variant = l;
191 else
192 return false;
193#endif
194 return true;
195 }
196
197 // Find matching factory function
198 wxVariantDataFactory f =
199 g_wxAnyValueTypeGlobals->FindVariantDataFactory(any.GetType());
200
5afecf60
JS
201 wxVariantData* data = NULL;
202
0bf14ab8
JS
203 if ( f )
204 {
205 data = f(any);
206 }
207 else
208 {
209 // Check if wxAny wrapped wxVariantData*
210 if ( !any.GetAs(&data) )
0aaed451
JS
211 {
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);
0bf14ab8 216 return false;
0aaed451 217 }
0bf14ab8
JS
218
219 // Wrapper's GetValue() does not increase reference
220 // count, se have to do it before the data gets passed
221 // to a new variant.
222 data->IncRef();
223 }
224
225 variant->SetData(data);
226 return true;
227}
228
229#endif // wxUSE_VARIANT
230
39601a7f
VZ
231//
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.
235//
236class wxAnyValueTypeGlobalsManager : public wxModule
237{
238 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
239public:
240 wxAnyValueTypeGlobalsManager() : wxModule() { }
241 virtual ~wxAnyValueTypeGlobalsManager() { }
242
243 virtual bool OnInit()
244 {
245 return true;
246 }
247 virtual void OnExit()
248 {
249 delete g_wxAnyValueTypeGlobals;
250 g_wxAnyValueTypeGlobals = NULL;
251 }
252private:
253};
254
255IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
256
257
258//-------------------------------------------------------------------------
259// wxAnyValueType
260//-------------------------------------------------------------------------
261
262wxAnyValueType::wxAnyValueType()
263{
264 if ( !g_wxAnyValueTypeGlobals )
265 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
266
267 g_wxAnyValueTypeGlobals->RegisterValueType(this);
268}
269
39601a7f
VZ
270//-------------------------------------------------------------------------
271// Dynamic conversion member functions
272//-------------------------------------------------------------------------
273
274//
275// Define integer minimum and maximum as helpers
276#ifdef wxLongLong_t
982d7f93
VZ
277 #define UseIntMin (wxINT64_MIN)
278 #define UseIntMax (wxINT64_MAX)
279 #define UseUintMax (wxUINT64_MAX)
39601a7f 280#else
982d7f93
VZ
281 #define UseIntMin (LONG_MIN)
282 #define UseIntMax (LONG_MAX)
283 #define UseUintMax (ULONG_MAX)
39601a7f
VZ
284#endif
285
982d7f93
VZ
286namespace
287{
288
39601a7f 289const double UseIntMinF = static_cast<double>(UseIntMin);
39601a7f
VZ
290const double UseIntMaxF = static_cast<double>(UseIntMax);
291const double UseUintMaxF = static_cast<double>(UseUintMax);
39601a7f 292
982d7f93 293} // anonymous namespace
39601a7f
VZ
294
295bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src,
296 wxAnyValueType* dstType,
297 wxAnyValueBuffer& dst) const
298{
299 wxAnyBaseIntType value = GetValue(src);
300 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
301 {
302#ifdef wxLongLong_t
303 wxLongLong ll(value);
304 wxString s = ll.ToString();
305#else
306 wxString s = wxString::Format(wxS("%ld"), (long)value);
307#endif
308 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
309 }
310 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
311 {
312 if ( value < 0 )
313 return false;
314 wxAnyBaseUintType ul = (wxAnyBaseUintType) value;
315 wxAnyValueTypeImplUint::SetValue(ul, dst);
316 }
317 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
318 {
319 double value2 = static_cast<double>(value);
320 wxAnyValueTypeImplDouble::SetValue(value2, dst);
321 }
322 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
323 {
324 bool value2 = value ? true : false;
325 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
326 }
327 else
328 return false;
329
330 return true;
331}
332
333bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
334 wxAnyValueType* dstType,
335 wxAnyValueBuffer& dst) const
336{
337 wxAnyBaseUintType value = GetValue(src);
338 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
339 {
340#ifdef wxLongLong_t
341 wxULongLong ull(value);
342 wxString s = ull.ToString();
343#else
344 wxString s = wxString::Format(wxS("%lu"), (long)value);
345#endif
346 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
347 }
348 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
349 {
350 if ( value > UseIntMax )
351 return false;
352 wxAnyBaseIntType l = (wxAnyBaseIntType) value;
353 wxAnyValueTypeImplInt::SetValue(l, dst);
354 }
355 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
356 {
357#ifndef __VISUALC6__
358 double value2 = static_cast<double>(value);
359#else
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);
363#endif
364 wxAnyValueTypeImplDouble::SetValue(value2, dst);
365 }
366 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
367 {
368 bool value2 = value ? true : false;
369 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
370 }
371 else
372 return false;
373
374 return true;
375}
376
153107b4
JS
377// Convert wxString to destination wxAny value type
378bool wxAnyConvertString(const wxString& value,
379 wxAnyValueType* dstType,
380 wxAnyValueBuffer& dst)
39601a7f 381{
153107b4
JS
382 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
383 {
384 wxAnyValueTypeImpl<wxString>::SetValue(value, dst);
385 }
386 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
39601a7f
VZ
387 {
388 wxAnyBaseIntType value2;
389#ifdef wxLongLong_t
390 if ( !value.ToLongLong(&value2) )
391#else
392 if ( !value.ToLong(&value2) )
393#endif
394 return false;
395 wxAnyValueTypeImplInt::SetValue(value2, dst);
396 }
397 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
398 {
399 wxAnyBaseUintType value2;
400#ifdef wxLongLong_t
401 if ( !value.ToULongLong(&value2) )
402#else
403 if ( !value.ToULong(&value2) )
404#endif
405 return false;
406 wxAnyValueTypeImplUint::SetValue(value2, dst);
407 }
408 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
409 {
410 double value2;
411 if ( !value.ToDouble(&value2) )
412 return false;
413 wxAnyValueTypeImplDouble::SetValue(value2, dst);
414 }
415 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
416 {
417 bool value2;
153107b4
JS
418 wxString s(value);
419 s.MakeLower();
420 if ( s == wxS("true") ||
421 s == wxS("yes") ||
422 s == wxS('1') )
39601a7f 423 value2 = true;
153107b4
JS
424 else if ( s == wxS("false") ||
425 s == wxS("no") ||
426 s == wxS('0') )
39601a7f
VZ
427 value2 = false;
428 else
429 return false;
430
431 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
432 }
433 else
434 return false;
435
436 return true;
437}
438
439bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
440 wxAnyValueType* dstType,
441 wxAnyValueBuffer& dst) const
442{
443 bool value = GetValue(src);
444 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
445 {
446 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
447 wxAnyValueTypeImplInt::SetValue(value2, dst);
448 }
449 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
450 {
451 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
452 wxAnyValueTypeImplUint::SetValue(value2, dst);
453 }
454 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
455 {
456 wxString s;
457 if ( value )
458 s = wxS("true");
459 else
460 s = wxS("false");
461 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
462 }
463 else
464 return false;
465
466 return true;
467}
468
469bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
470 wxAnyValueType* dstType,
471 wxAnyValueBuffer& dst) const
472{
473 double value = GetValue(src);
474 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
475 {
476 if ( value < UseIntMinF || value > UseIntMaxF )
477 return false;
478 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
479 wxAnyValueTypeImplUint::SetValue(ul, dst);
480 }
481 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
482 {
483 if ( value < 0.0 || value > UseUintMaxF )
484 return false;
485 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
486 wxAnyValueTypeImplUint::SetValue(ul, dst);
487 }
488 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
489 {
490 wxString s = wxString::Format(wxS("%.14g"), value);
491 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
492 }
493 else
494 return false;
495
496 return true;
497}
498
499WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
500WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
39601a7f
VZ
501WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
502WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
503
153107b4
JS
504WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
505WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
506WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
507
c5fe6a5b
JS
508WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
509//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
510//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
511
39601a7f
VZ
512//-------------------------------------------------------------------------
513// wxAnyNullValueType implementation
514//-------------------------------------------------------------------------
515
516class wxAnyNullValue
517{
518private:
519 void* m_dummy;
520};
521
522template <>
523class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
524{
525 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
526public:
24985a9b 527 // Dummy implementations
39601a7f
VZ
528 virtual void DeleteValue(wxAnyValueBuffer& buf) const
529 {
24985a9b 530 wxUnusedVar(buf);
39601a7f
VZ
531 }
532
39601a7f
VZ
533 virtual void CopyBuffer(const wxAnyValueBuffer& src,
534 wxAnyValueBuffer& dst) const
535 {
536 wxUnusedVar(src);
537 wxUnusedVar(dst);
538 }
539
540 virtual bool ConvertValue(const wxAnyValueBuffer& src,
541 wxAnyValueType* dstType,
542 wxAnyValueBuffer& dst) const
543 {
544 wxUnusedVar(src);
545 wxUnusedVar(dstType);
546 wxUnusedVar(dst);
547 return false;
548 }
549
550private:
551};
552
553WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
554
555wxAnyValueType* wxAnyNullValueType =
556 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
557
558#endif // wxUSE_ANY