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