]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/any.cpp
Fix another off-by-1 bug in wxMBConv::ToWChar().
[wxWidgets.git] / src / common / any.cpp
... / ...
CommitLineData
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
31using namespace wxPrivate;
32
33//-------------------------------------------------------------------------
34// wxAnyValueTypeGlobals
35//-------------------------------------------------------------------------
36
37//
38// Helper class to manage wxAnyValueType instances and other
39// related global variables.
40//
41// NB: We really need to have wxAnyValueType instances allocated
42// in heap. They are stored as static template member variables,
43// and with them we just can't be too careful (eg. not allocating
44// them in heap broke the type identification in GCC).
45//
46class wxAnyValueTypeGlobals
47{
48public:
49 wxAnyValueTypeGlobals()
50 {
51 }
52 ~wxAnyValueTypeGlobals()
53 {
54 for ( size_t i=0; i<m_valueTypes.size(); i++ )
55 delete m_valueTypes[i];
56 }
57
58 void RegisterValueType(wxAnyValueType* valueType)
59 {
60 m_valueTypes.push_back(valueType);
61 }
62
63private:
64 wxVector<wxAnyValueType*> m_valueTypes;
65};
66
67static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
68
69//
70// This class is to make sure that wxAnyValueType instances
71// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
72// because wxModule itself is instantiated too late.
73//
74class wxAnyValueTypeGlobalsManager : public wxModule
75{
76 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
77public:
78 wxAnyValueTypeGlobalsManager() : wxModule() { }
79 virtual ~wxAnyValueTypeGlobalsManager() { }
80
81 virtual bool OnInit()
82 {
83 return true;
84 }
85 virtual void OnExit()
86 {
87 delete g_wxAnyValueTypeGlobals;
88 g_wxAnyValueTypeGlobals = NULL;
89 }
90private:
91};
92
93IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
94
95
96//-------------------------------------------------------------------------
97// wxAnyValueType
98//-------------------------------------------------------------------------
99
100wxAnyValueType::wxAnyValueType()
101{
102 if ( !g_wxAnyValueTypeGlobals )
103 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
104
105 g_wxAnyValueTypeGlobals->RegisterValueType(this);
106}
107
108//-------------------------------------------------------------------------
109// Dynamic conversion member functions
110//-------------------------------------------------------------------------
111
112//
113// Define integer minimum and maximum as helpers
114#ifdef wxLongLong_t
115const wxAnyBaseIntType UseIntMin = wxINT64_MIN;
116const wxAnyBaseUintType UseIntMax = wxINT64_MAX;
117const wxAnyBaseUintType UseUintMax = wxUINT64_MAX;
118#else
119const wxAnyBaseIntType UseIntMin = LONG_MIN;
120const wxAnyBaseUintType UseUintMax = ULONG_MAX;
121const wxAnyBaseUintType UseIntMax = LONG_MAX;
122#endif
123
124const double UseIntMinF = static_cast<double>(UseIntMin);
125#ifndef __VISUALC6__
126const double UseIntMaxF = static_cast<double>(UseIntMax);
127const double UseUintMaxF = static_cast<double>(UseUintMax);
128#else
129// VC6 doesn't implement conversion from unsigned __int64 to double
130const wxAnyBaseIntType UseIntMax0 = static_cast<wxAnyBaseIntType>(UseIntMax);
131const wxAnyBaseIntType UseUintMax0 = static_cast<wxAnyBaseIntType>(UseUintMax);
132const double UseIntMaxF = static_cast<double>(UseIntMax0);
133const double UseUintMaxF = static_cast<double>(UseUintMax0);
134#endif
135
136
137bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src,
138 wxAnyValueType* dstType,
139 wxAnyValueBuffer& dst) const
140{
141 wxAnyBaseIntType value = GetValue(src);
142 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
143 {
144#ifdef wxLongLong_t
145 wxLongLong ll(value);
146 wxString s = ll.ToString();
147#else
148 wxString s = wxString::Format(wxS("%ld"), (long)value);
149#endif
150 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
151 }
152 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
153 {
154 if ( value < 0 )
155 return false;
156 wxAnyBaseUintType ul = (wxAnyBaseUintType) value;
157 wxAnyValueTypeImplUint::SetValue(ul, dst);
158 }
159 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
160 {
161 double value2 = static_cast<double>(value);
162 wxAnyValueTypeImplDouble::SetValue(value2, dst);
163 }
164 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
165 {
166 bool value2 = value ? true : false;
167 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
168 }
169 else
170 return false;
171
172 return true;
173}
174
175bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
176 wxAnyValueType* dstType,
177 wxAnyValueBuffer& dst) const
178{
179 wxAnyBaseUintType value = GetValue(src);
180 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
181 {
182#ifdef wxLongLong_t
183 wxULongLong ull(value);
184 wxString s = ull.ToString();
185#else
186 wxString s = wxString::Format(wxS("%lu"), (long)value);
187#endif
188 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
189 }
190 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
191 {
192 if ( value > UseIntMax )
193 return false;
194 wxAnyBaseIntType l = (wxAnyBaseIntType) value;
195 wxAnyValueTypeImplInt::SetValue(l, dst);
196 }
197 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
198 {
199#ifndef __VISUALC6__
200 double value2 = static_cast<double>(value);
201#else
202 // VC6 doesn't implement conversion from unsigned __int64 to double
203 wxAnyBaseIntType value0 = static_cast<wxAnyBaseIntType>(value);
204 double value2 = static_cast<double>(value0);
205#endif
206 wxAnyValueTypeImplDouble::SetValue(value2, dst);
207 }
208 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
209 {
210 bool value2 = value ? true : false;
211 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
212 }
213 else
214 return false;
215
216 return true;
217}
218
219bool wxAnyValueTypeImplString::ConvertValue(const wxAnyValueBuffer& src,
220 wxAnyValueType* dstType,
221 wxAnyValueBuffer& dst) const
222{
223 wxString value = GetValue(src);
224 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
225 {
226 wxAnyBaseIntType value2;
227#ifdef wxLongLong_t
228 if ( !value.ToLongLong(&value2) )
229#else
230 if ( !value.ToLong(&value2) )
231#endif
232 return false;
233 wxAnyValueTypeImplInt::SetValue(value2, dst);
234 }
235 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
236 {
237 wxAnyBaseUintType value2;
238#ifdef wxLongLong_t
239 if ( !value.ToULongLong(&value2) )
240#else
241 if ( !value.ToULong(&value2) )
242#endif
243 return false;
244 wxAnyValueTypeImplUint::SetValue(value2, dst);
245 }
246 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
247 {
248 double value2;
249 if ( !value.ToDouble(&value2) )
250 return false;
251 wxAnyValueTypeImplDouble::SetValue(value2, dst);
252 }
253 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
254 {
255 bool value2;
256 value.MakeLower();
257 if ( value == wxS("true") ||
258 value == wxS("yes") ||
259 value == wxS('1') )
260 value2 = true;
261 else if ( value == wxS("false") ||
262 value == wxS("no") ||
263 value == wxS('0') )
264 value2 = false;
265 else
266 return false;
267
268 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
269 }
270 else
271 return false;
272
273 return true;
274}
275
276bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
277 wxAnyValueType* dstType,
278 wxAnyValueBuffer& dst) const
279{
280 bool value = GetValue(src);
281 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
282 {
283 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
284 wxAnyValueTypeImplInt::SetValue(value2, dst);
285 }
286 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
287 {
288 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
289 wxAnyValueTypeImplUint::SetValue(value2, dst);
290 }
291 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
292 {
293 wxString s;
294 if ( value )
295 s = wxS("true");
296 else
297 s = wxS("false");
298 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
299 }
300 else
301 return false;
302
303 return true;
304}
305
306bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
307 wxAnyValueType* dstType,
308 wxAnyValueBuffer& dst) const
309{
310 double value = GetValue(src);
311 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
312 {
313 if ( value < UseIntMinF || value > UseIntMaxF )
314 return false;
315 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
316 wxAnyValueTypeImplUint::SetValue(ul, dst);
317 }
318 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
319 {
320 if ( value < 0.0 || value > UseUintMaxF )
321 return false;
322 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
323 wxAnyValueTypeImplUint::SetValue(ul, dst);
324 }
325 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
326 {
327 wxString s = wxString::Format(wxS("%.14g"), value);
328 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
329 }
330 else
331 return false;
332
333 return true;
334}
335
336WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
337WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
338WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplString)
339WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
340WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
341
342//-------------------------------------------------------------------------
343// wxAnyNullValueType implementation
344//-------------------------------------------------------------------------
345
346class wxAnyNullValue
347{
348private:
349 void* m_dummy;
350};
351
352template <>
353class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
354{
355 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
356public:
357 virtual void DeleteValue(wxAnyValueBuffer& buf) const
358 {
359 buf.m_ptr = NULL; // This is important
360 }
361
362 // Dummy implementations
363 virtual void CopyBuffer(const wxAnyValueBuffer& src,
364 wxAnyValueBuffer& dst) const
365 {
366 wxUnusedVar(src);
367 wxUnusedVar(dst);
368 }
369
370 virtual bool ConvertValue(const wxAnyValueBuffer& src,
371 wxAnyValueType* dstType,
372 wxAnyValueBuffer& dst) const
373 {
374 wxUnusedVar(src);
375 wxUnusedVar(dstType);
376 wxUnusedVar(dst);
377 return false;
378 }
379
380private:
381};
382
383WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
384
385wxAnyValueType* wxAnyNullValueType =
386 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
387
388#endif // wxUSE_ANY