]> git.saurik.com Git - wxWidgets.git/blob - src/common/any.cpp
Add wxTranslations::GetTranslatedString().
[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 // 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"
29 #include "wx/hashmap.h"
30 #include "wx/hashset.h"
31
32 using namespace wxPrivate;
33
34 #if wxUSE_VARIANT
35
36 //-------------------------------------------------------------------------
37 // wxAnyValueTypeGlobals
38 //-------------------------------------------------------------------------
39
40 WX_DECLARE_HASH_MAP(wxAnyValueType*,
41 wxVariantDataFactory,
42 wxPointerHash,
43 wxPointerEqual,
44 wxAnyTypeToVariantDataFactoryMap);
45
46 //
47 // Helper class to manage global variables related to type conversion
48 // between wxAny and wxVariant.
49 //
50 class wxAnyValueTypeGlobals
51 {
52 public:
53 wxAnyValueTypeGlobals()
54 {
55 }
56 ~wxAnyValueTypeGlobals()
57 {
58 m_anyToVariant.clear();
59 }
60
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)
68 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_)
69 {
70 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
71 // but WX_DECLARE_HASH_MAP() has some trouble with it.
72 wxAnyValueType* type = const_cast<wxAnyValueType*>(type_);
73
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 }
117
118 private:
119 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
120 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
121 };
122
123 static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
124
125
126 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
127
128 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
129 {
130 if ( !g_wxAnyValueTypeGlobals )
131 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
132 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
133 }
134
135 bool 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
150 wxLongLong_t ll = 0;
151 if ( any.GetAs(&ll) )
152 {
153 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
154 // integer constraint yields more consistent behaviour across
155 // builds.
156 if ( ll > wxINT32_MAX || ll < wxINT32_MIN )
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
179 wxVariantData* data = NULL;
180
181 if ( f )
182 {
183 data = f(any);
184 }
185 else
186 {
187 // Check if wxAny wrapped wxVariantData*
188 if ( !any.GetAs(&data) )
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);
194 return false;
195 }
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
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 //
212 class wxAnyValueTypeGlobalsManager : public wxModule
213 {
214 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
215 public:
216 wxAnyValueTypeGlobalsManager() : wxModule() { }
217 virtual ~wxAnyValueTypeGlobalsManager() { }
218
219 virtual bool OnInit()
220 {
221 return true;
222 }
223 virtual void OnExit()
224 {
225 wxDELETE(g_wxAnyValueTypeGlobals);
226 }
227 private:
228 };
229
230 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
231
232 #endif // wxUSE_VARIANT
233
234
235 //-------------------------------------------------------------------------
236 // Dynamic conversion member functions
237 //-------------------------------------------------------------------------
238
239 //
240 // Define integer minimum and maximum as helpers
241 #ifdef wxLongLong_t
242 #define UseIntMin (wxINT64_MIN)
243 #define UseIntMax (wxINT64_MAX)
244 #define UseUintMax (wxUINT64_MAX)
245 #else
246 #define UseIntMin (LONG_MIN)
247 #define UseIntMax (LONG_MAX)
248 #define UseUintMax (ULONG_MAX)
249 #endif
250
251 namespace
252 {
253
254 const double UseIntMinF = static_cast<double>(UseIntMin);
255 const double UseIntMaxF = static_cast<double>(UseIntMax);
256 const double UseUintMaxF = static_cast<double>(UseUintMax);
257
258 } // anonymous namespace
259
260 bool 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
298 bool 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
342 // Convert wxString to destination wxAny value type
343 bool wxAnyConvertString(const wxString& value,
344 wxAnyValueType* dstType,
345 wxAnyValueBuffer& dst)
346 {
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) )
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;
376 if ( !value.ToCDouble(&value2) )
377 return false;
378 wxAnyValueTypeImplDouble::SetValue(value2, dst);
379 }
380 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
381 {
382 bool value2;
383 wxString s(value);
384 s.MakeLower();
385 if ( s == wxS("true") ||
386 s == wxS("yes") ||
387 s == wxS('1') )
388 value2 = true;
389 else if ( s == wxS("false") ||
390 s == wxS("no") ||
391 s == wxS('0') )
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
404 bool 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
434 bool 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 {
455 wxString s = wxString::FromCDouble(value, 14);
456 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
457 }
458 else
459 return false;
460
461 return true;
462 }
463
464 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
465 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
468
469 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
470 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
472
473 #if wxUSE_DATETIME
474 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
475 #endif // wxUSE_DATETIME
476
477 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
478 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
479
480 //-------------------------------------------------------------------------
481 // wxAnyNullValueType implementation
482 //-------------------------------------------------------------------------
483
484 class wxAnyNullValue
485 {
486 protected:
487 // this field is unused, but can't be private to avoid Clang's
488 // "Private field 'm_dummy' is not used" warning
489 void* m_dummy;
490 };
491
492 template <>
493 class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
494 {
495 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
496 public:
497 // Dummy implementations
498 virtual void DeleteValue(wxAnyValueBuffer& buf) const
499 {
500 wxUnusedVar(buf);
501 }
502
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
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
528 private:
529 };
530
531 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
532
533 wxAnyValueType* wxAnyNullValueType =
534 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
535
536 #include "wx/listimpl.cpp"
537 WX_DEFINE_LIST(wxAnyList)
538
539 #endif // wxUSE_ANY