]> git.saurik.com Git - wxWidgets.git/blob - src/common/any.cpp
currently avoid problems when releasing the capture during drag on osx_cocoa
[wxWidgets.git] / src / common / any.cpp
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"
30 #include "wx/hashmap.h"
31
32 using namespace wxPrivate;
33
34 //-------------------------------------------------------------------------
35 // wxAnyValueTypeGlobals
36 //-------------------------------------------------------------------------
37
38 #if wxUSE_VARIANT
39
40 WX_DECLARE_HASH_MAP(wxAnyValueType*,
41 wxVariantDataFactory,
42 wxPointerHash,
43 wxPointerEqual,
44 wxAnyTypeToVariantDataFactoryMap);
45
46 #endif
47
48 //
49 // Helper class to manage wxAnyValueType instances and and other
50 // related global variables (such as wxAny<->wxVariant type association).
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 //
57 class wxAnyValueTypeGlobals
58 {
59 public:
60 wxAnyValueTypeGlobals()
61 {
62 }
63 ~wxAnyValueTypeGlobals()
64 {
65 #if wxUSE_VARIANT
66 m_anyToVariant.clear();
67 #endif
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
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)
85 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_)
86 {
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_);
90
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
136 private:
137 wxVector<wxAnyValueType*> m_valueTypes;
138 #if wxUSE_VARIANT
139 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
140 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
141 #endif
142 };
143
144 static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
145
146 #if wxUSE_VARIANT
147
148 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
149
150 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
151 {
152 if ( !g_wxAnyValueTypeGlobals )
153 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
154 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
155 }
156
157 bool 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
172 wxLongLong_t ll = 0;
173 if ( any.GetAs(&ll) )
174 {
175 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
176 // integer constraint yields more consistent behavior across
177 // builds.
178 if ( ll > wxINT32_MAX || ll < wxINT32_MIN )
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
201 wxVariantData* data = NULL;
202
203 if ( f )
204 {
205 data = f(any);
206 }
207 else
208 {
209 // Check if wxAny wrapped wxVariantData*
210 if ( !any.GetAs(&data) )
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);
216 return false;
217 }
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
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 //
236 class wxAnyValueTypeGlobalsManager : public wxModule
237 {
238 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
239 public:
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 }
252 private:
253 };
254
255 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
256
257
258 //-------------------------------------------------------------------------
259 // wxAnyValueType
260 //-------------------------------------------------------------------------
261
262 wxAnyValueType::wxAnyValueType()
263 {
264 if ( !g_wxAnyValueTypeGlobals )
265 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
266
267 g_wxAnyValueTypeGlobals->RegisterValueType(this);
268 }
269
270 //-------------------------------------------------------------------------
271 // Dynamic conversion member functions
272 //-------------------------------------------------------------------------
273
274 //
275 // Define integer minimum and maximum as helpers
276 #ifdef wxLongLong_t
277 #define UseIntMin (wxINT64_MIN)
278 #define UseIntMax (wxINT64_MAX)
279 #define UseUintMax (wxUINT64_MAX)
280 #else
281 #define UseIntMin (LONG_MIN)
282 #define UseIntMax (LONG_MAX)
283 #define UseUintMax (ULONG_MAX)
284 #endif
285
286 namespace
287 {
288
289 const double UseIntMinF = static_cast<double>(UseIntMin);
290 const double UseIntMaxF = static_cast<double>(UseIntMax);
291 const double UseUintMaxF = static_cast<double>(UseUintMax);
292
293 } // anonymous namespace
294
295 bool 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
333 bool 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
377 bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src,
378 wxAnyValueType* dstType,
379 wxAnyValueBuffer& dst) const
380 {
381 wxString value = GetValue(src);
382 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
383 {
384 wxAnyBaseIntType value2;
385 #ifdef wxLongLong_t
386 if ( !value.ToLongLong(&value2) )
387 #else
388 if ( !value.ToLong(&value2) )
389 #endif
390 return false;
391 wxAnyValueTypeImplInt::SetValue(value2, dst);
392 }
393 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
394 {
395 wxAnyBaseUintType value2;
396 #ifdef wxLongLong_t
397 if ( !value.ToULongLong(&value2) )
398 #else
399 if ( !value.ToULong(&value2) )
400 #endif
401 return false;
402 wxAnyValueTypeImplUint::SetValue(value2, dst);
403 }
404 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
405 {
406 double value2;
407 if ( !value.ToDouble(&value2) )
408 return false;
409 wxAnyValueTypeImplDouble::SetValue(value2, dst);
410 }
411 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
412 {
413 bool value2;
414 value.MakeLower();
415 if ( value == wxS("true") ||
416 value == wxS("yes") ||
417 value == wxS('1') )
418 value2 = true;
419 else if ( value == wxS("false") ||
420 value == wxS("no") ||
421 value == wxS('0') )
422 value2 = false;
423 else
424 return false;
425
426 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
427 }
428 else
429 return false;
430
431 return true;
432 }
433
434 bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
435 wxAnyValueType* dstType,
436 wxAnyValueBuffer& dst) const
437 {
438 bool value = GetValue(src);
439 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
440 {
441 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
442 wxAnyValueTypeImplInt::SetValue(value2, dst);
443 }
444 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
445 {
446 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
447 wxAnyValueTypeImplUint::SetValue(value2, dst);
448 }
449 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
450 {
451 wxString s;
452 if ( value )
453 s = wxS("true");
454 else
455 s = wxS("false");
456 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
457 }
458 else
459 return false;
460
461 return true;
462 }
463
464 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
465 wxAnyValueType* dstType,
466 wxAnyValueBuffer& dst) const
467 {
468 double value = GetValue(src);
469 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
470 {
471 if ( value < UseIntMinF || value > UseIntMaxF )
472 return false;
473 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
474 wxAnyValueTypeImplUint::SetValue(ul, dst);
475 }
476 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
477 {
478 if ( value < 0.0 || value > UseUintMaxF )
479 return false;
480 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
481 wxAnyValueTypeImplUint::SetValue(ul, dst);
482 }
483 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
484 {
485 wxString s = wxString::Format(wxS("%.14g"), value);
486 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
487 }
488 else
489 return false;
490
491 return true;
492 }
493
494 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
495 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
496 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
497 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
498 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
499
500 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
501 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
502 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
503
504 //-------------------------------------------------------------------------
505 // wxAnyNullValueType implementation
506 //-------------------------------------------------------------------------
507
508 class wxAnyNullValue
509 {
510 private:
511 void* m_dummy;
512 };
513
514 template <>
515 class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
516 {
517 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
518 public:
519 // Dummy implementations
520 virtual void DeleteValue(wxAnyValueBuffer& buf) const
521 {
522 wxUnusedVar(buf);
523 }
524
525 virtual void CopyBuffer(const wxAnyValueBuffer& src,
526 wxAnyValueBuffer& dst) const
527 {
528 wxUnusedVar(src);
529 wxUnusedVar(dst);
530 }
531
532 virtual bool ConvertValue(const wxAnyValueBuffer& src,
533 wxAnyValueType* dstType,
534 wxAnyValueBuffer& dst) const
535 {
536 wxUnusedVar(src);
537 wxUnusedVar(dstType);
538 wxUnusedVar(dst);
539 return false;
540 }
541
542 private:
543 };
544
545 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
546
547 wxAnyValueType* wxAnyNullValueType =
548 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
549
550 #endif // wxUSE_ANY