]>
Commit | Line | Data |
---|---|---|
39601a7f VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: any.h | |
3 | // Purpose: interface of wxAny | |
4 | // Author: wxWidgets team | |
5 | // RCS-ID: $Id$ | |
6 | // Licence: wxWindows license | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | ||
10 | /** | |
11 | @class wxAny | |
12 | ||
13 | The wxAny class represents a container for any type. Its value | |
14 | can be changed at run time, possibly to a different type of value. | |
15 | ||
57f21754 JS |
16 | wxAny is a backwards incompatible successor class for wxVariant, |
17 | essentially doing the same thing in a more modern, template-based manner | |
18 | and with transparent support for any user data type. | |
39601a7f VZ |
19 | |
20 | Some pseudo-code'ish example of use with arbitrary user data: | |
21 | ||
22 | @code | |
23 | void SomeFunction() | |
24 | { | |
25 | MyClass myObject; | |
26 | wxAny any = myObject; | |
27 | ||
28 | // Do something | |
29 | // ... | |
30 | ||
31 | // Let's do a sanity check to make sure that any still holds | |
32 | // data of correct type. | |
33 | if ( any.CheckType<MyClass>() ) | |
34 | { | |
35 | // Thank goodness, still a correct type. | |
36 | MyClass myObject2 = any.As<MyClass>(); | |
37 | } | |
38 | else | |
39 | { | |
40 | // Something has gone horribly wrong! | |
41 | wxFAIL(); | |
42 | } | |
43 | } | |
44 | @endcode | |
45 | ||
46 | When compared to wxVariant, there are various internal implementation | |
47 | differences as well. For instance, wxAny only allocates separate data | |
48 | object in heap for large (ie. size in bytes more than | |
49 | WX_ANY_VALUE_BUFFER_SIZE) or 'non-movable' data types. Pointers, integers, | |
50 | bools etc. are fitted in the wxAny's own buffer without need for any extra | |
51 | allocation. Use following code to declare your own data type as 'movable': | |
52 | ||
53 | @code | |
54 | #include "wx/meta/movable.h" | |
55 | WX_DECLARE_TYPE_MOVABLE(MyClass) | |
56 | @endcode | |
57 | ||
58 | However, you must be aware that 'movable' means such data that can be | |
59 | copied with memcpy() without corrupting program integrity. For instance, | |
60 | movable objects usually cannot contain pointers or references to other | |
61 | data. wxRect, wxPoint, and wxSize are good examples of movable classes. | |
62 | ||
63 | Note that pointers to any and all classes are already automatically | |
64 | declared as movable data. | |
65 | ||
c5fe6a5b JS |
66 | @warning Caveat with shared libraries (DLLs): If you have a scenario where |
67 | you use wxAny across application's shared library and application | |
68 | itself (or, with another of your shared libraries), then you must | |
69 | use wxDECLARE_ANY_TYPE() macro in your shared library code to | |
70 | correctly make sure that the wxAnyValueType implementation is | |
71 | generated correctly. Failure to do this will result in breakage | |
72 | of the wxAny type recognition with type in question. Below is an | |
73 | example how to use the macro. | |
74 | @code | |
75 | // In your shared library/DLL-only | |
76 | wxDECLARE_ANY_TYPE(MyClass, WXEXPORT) | |
77 | ||
78 | // In your shared library/DLL source code | |
79 | WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
80 | ||
81 | // In code using said shared library/DLL | |
82 | wxDECLARE_ANY_TYPE(MyClass, WXIMPORT) | |
83 | @endcode | |
84 | ||
39601a7f VZ |
85 | @library{wxbase} |
86 | @category{data} | |
87 | ||
88 | @see wxAnyValueType, wxVariant | |
89 | */ | |
90 | class wxAny | |
91 | { | |
92 | public: | |
93 | /** | |
94 | Default constructor. It seeds the object with a null value. | |
95 | */ | |
96 | wxAny(); | |
97 | ||
98 | /** | |
99 | Constructs wxAny from data. | |
100 | */ | |
101 | template<typename T> | |
102 | wxAny(const T& value); | |
103 | ||
104 | /** | |
105 | Constructs wxAny from another wxAny. | |
106 | */ | |
107 | wxAny(const wxAny& any); | |
108 | ||
109 | /** | |
110 | Destructor. | |
111 | */ | |
112 | ~wxAny(); | |
113 | ||
114 | /** | |
115 | This template function converts wxAny into given type. No dynamic | |
116 | conversion is performed, so if the type is incorrect an assertion | |
117 | failure will occur in debug builds, and a bogus value is returned | |
118 | in release ones. | |
119 | ||
120 | @remarks This template function may not work properly with Visual C++ | |
121 | 6. For full compiler compatibility, please use | |
122 | wxANY_AS(any, T) macro instead. | |
123 | */ | |
124 | template<typename T> | |
125 | T As() const; | |
126 | ||
127 | /** | |
128 | Use this template function for checking if this wxAny holds | |
129 | a specific C++ data type. | |
130 | ||
131 | @remarks This template function may not work properly with Visual C++ | |
132 | 6. For full compiler compatibility, please use | |
133 | wxANY_CHECK_TYPE(any, T) macro instead. | |
134 | ||
135 | @see wxAnyValueType::CheckType() | |
136 | */ | |
137 | template<typename T> | |
138 | bool CheckType(); | |
139 | ||
140 | /** | |
141 | Template function that retrieves and converts the value of this | |
142 | wxAny to the type that T* value is. | |
143 | ||
57f21754 | 144 | @return Returns @true if conversion was successful. |
39601a7f VZ |
145 | */ |
146 | template<typename T> | |
147 | bool GetAs(T* value) const; | |
148 | ||
149 | /** | |
150 | Returns the value type as wxAnyValueType instance. | |
151 | ||
152 | @remarks You cannot reliably test whether two wxAnys are of | |
153 | same value type by simply comparing return values | |
154 | of wxAny::GetType(). Instead use | |
155 | wxAnyValueType::CheckType<T>() template function. | |
156 | */ | |
157 | const wxAnyValueType* GetType() const; | |
158 | ||
159 | /** | |
160 | Tests if wxAny is null (that is, whether there is data). | |
161 | */ | |
162 | bool IsNull() const; | |
163 | ||
164 | /** | |
165 | Makes wxAny null (that is, clears it). | |
166 | */ | |
167 | void MakeNull(); | |
168 | ||
169 | //@{ | |
170 | /** | |
171 | @name Assignment operators | |
172 | */ | |
173 | template<typename T> | |
174 | wxAny& operator=(const T &value); | |
175 | wxAny& operator=(const wxAny &any); | |
176 | //@} | |
177 | ||
178 | //@{ | |
179 | /** | |
180 | @name Equality operators | |
181 | ||
182 | @remarks Generic template-based comparison operators have not been | |
183 | provided for various code consistency reasons, so for custom | |
184 | data types you have do something like this: | |
185 | ||
186 | @code | |
187 | if ( any.CheckType<MyClass*>() && | |
188 | any.As<MyClass*>() == myObjectPtr ) | |
189 | { | |
190 | // Do something if any stores myObjectPtr | |
191 | } | |
192 | @endcode | |
193 | */ | |
194 | bool operator==(signed char value) const; | |
195 | bool operator==(signed short value) const; | |
196 | bool operator==(signed int value) const; | |
197 | bool operator==(signed long value) const; | |
198 | bool operator==(wxLongLong_t value) const; | |
199 | bool operator==(unsigned char value) const; | |
200 | bool operator==(unsigned short value) const; | |
201 | bool operator==(unsigned int value) const; | |
202 | bool operator==(unsigned long value) const; | |
203 | bool operator==(wxULongLong_t value) const; | |
204 | bool operator==(float value) const; | |
205 | bool operator==(double value) const; | |
206 | bool operator==(bool value) const; | |
207 | bool operator==(const char* value) const; | |
208 | bool operator==(const wchar_t* value) const; | |
209 | bool operator==(const wxString& value) const; | |
210 | //@} | |
211 | ||
212 | //@{ | |
213 | /** | |
214 | @name Inequality operators | |
215 | */ | |
216 | bool operator!=(signed char value) const; | |
217 | bool operator!=(signed short value) const; | |
218 | bool operator!=(signed int value) const; | |
219 | bool operator!=(signed long value) const; | |
220 | bool operator!=(wxLongLong_t value) const; | |
221 | bool operator!=(unsigned char value) const; | |
222 | bool operator!=(unsigned short value) const; | |
223 | bool operator!=(unsigned int value) const; | |
224 | bool operator!=(unsigned long value) const; | |
225 | bool operator!=(wxULongLong_t value) const; | |
226 | bool operator!=(float value) const; | |
227 | bool operator!=(double value) const; | |
228 | bool operator!=(bool value) const; | |
229 | bool operator!=(const char* value) const; | |
230 | bool operator!=(const wchar_t* value) const; | |
231 | bool operator!=(const wxString& value) const; | |
232 | //@} | |
233 | }; | |
234 | ||
235 | /** | |
236 | This is value getter macro that is more compatible with older | |
237 | compilers, such as Visual C++ 6.0. | |
238 | */ | |
239 | #define wxANY_AS(any, T) | |
240 | ||
241 | ||
242 | /** | |
243 | This is type checking macro that is more compatible with older | |
244 | compilers, such as Visual C++ 6.0. | |
245 | */ | |
246 | #define wxANY_CHECK_TYPE(any, T) | |
247 | ||
248 | ||
249 | /** | |
250 | Size of the wxAny value buffer. | |
251 | */ | |
252 | enum | |
253 | { | |
254 | WX_ANY_VALUE_BUFFER_SIZE = 16 | |
255 | }; | |
256 | ||
257 | /** | |
258 | Type for buffer within wxAny for holding data. | |
259 | */ | |
260 | union wxAnyValueBuffer | |
261 | { | |
262 | void* m_ptr; | |
263 | wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; | |
264 | }; | |
265 | ||
266 | ||
267 | /** | |
268 | @class wxAnyValueType | |
269 | ||
270 | wxAnyValueType is base class for value type functionality for C++ data | |
271 | types used with wxAny. Usually the default template will create a | |
272 | satisfactory wxAnyValueType implementation for a data type, but | |
273 | sometimes you may need to add some customization. To do this you will need | |
274 | to add specialized template of wxAnyValueTypeImpl<>. Often your only | |
275 | need may be to add dynamic type conversion which would be done like | |
276 | this: | |
277 | ||
278 | @code | |
279 | template<> | |
280 | class wxAnyValueTypeImpl<MyClass> : | |
281 | public wxAnyValueTypeImplBase<MyClass> | |
282 | { | |
283 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
284 | public: | |
285 | wxAnyValueTypeImpl() : | |
286 | wxAnyValueTypeImplBase<MyClass>() { } | |
287 | virtual ~wxAnyValueTypeImpl() { } | |
288 | ||
289 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
290 | wxAnyValueType* dstType, | |
291 | wxAnyValueBuffer& dst) const | |
292 | { | |
293 | // GetValue() is a static member function implemented | |
294 | // in wxAnyValueTypeImplBase<>. | |
295 | MyClass value = GetValue(src); | |
296 | ||
297 | // TODO: Convert value from src buffer to destination | |
298 | // type and buffer. If cannot be done, return | |
299 | // false. This is a simple sample. | |
300 | if ( dstType->CheckType<wxString>() ) | |
301 | { | |
302 | wxString s = value.ToString(); | |
303 | wxAnyValueTypeImpl<wxString>::SetValue(s, dst); | |
304 | } | |
305 | else | |
306 | { | |
307 | return false; | |
308 | } | |
309 | } | |
310 | }; | |
311 | ||
312 | // | |
313 | // Following must be placed somewhere in your source code | |
314 | WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
315 | @endcode | |
316 | ||
317 | wxAnyValueTypeImplBase<> template, from which we inherit in the above | |
318 | example, contains the bulk of the default wxAnyValueTypeImpl<> template | |
319 | implementation, and as such allows you to easily add some minor | |
320 | customization. | |
321 | ||
322 | If you need a have complete control over the type interpretation, you | |
323 | will need to derive a class directly from wxAnyValueType, like this: | |
324 | ||
325 | @code | |
326 | template <> | |
327 | class wxAnyValueTypeImpl<MyClass> : public wxAnyValueType | |
328 | { | |
329 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
330 | public: | |
331 | virtual void DeleteValue(wxAnyValueBuffer& buf) const | |
332 | { | |
333 | // TODO: Free the data in buffer | |
334 | // It is important to clear the buffer like this | |
335 | // at the end of DeleteValue(). | |
336 | buf.m_ptr = NULL; | |
337 | } | |
338 | ||
339 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
340 | wxAnyValueBuffer& dst) const | |
341 | { | |
342 | // TODO: Copy value from one buffer to another. | |
24985a9b JS |
343 | // dst is already uninitialized and does not |
344 | // need to be freed. | |
39601a7f VZ |
345 | } |
346 | ||
347 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
348 | wxAnyValueType* dstType, | |
349 | wxAnyValueBuffer& dst) const | |
350 | { | |
351 | // TODO: Convert value from src buffer to destination | |
352 | // type and buffer. | |
353 | } | |
354 | ||
355 | // | |
356 | // Following static functions must be implemented | |
357 | // | |
358 | ||
359 | static void SetValue(const T& value, | |
360 | wxAnyValueBuffer& buf) | |
361 | { | |
362 | // TODO: Store value into buf. | |
363 | } | |
364 | ||
365 | static const T& GetValue(const wxAnyValueBuffer& buf) | |
366 | { | |
367 | // TODO: Return reference to value stored in buffer. | |
368 | } | |
369 | }; | |
370 | ||
371 | // | |
372 | // Following must be placed somewhere in your source code | |
373 | WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
374 | ||
375 | @endcode | |
376 | ||
377 | @library{wxbase} | |
378 | @category{data} | |
379 | ||
380 | @see wxAny | |
381 | */ | |
382 | class wxAnyValueType | |
383 | { | |
384 | public: | |
385 | /** | |
386 | Default constructor. | |
387 | */ | |
388 | wxAnyValueType(); | |
389 | ||
390 | /** | |
391 | Destructor. | |
392 | */ | |
393 | virtual ~wxAnyValueType(); | |
394 | ||
395 | /** | |
396 | Use this template function for checking if wxAnyValueType represents | |
397 | a specific C++ data type. | |
398 | ||
399 | @remarks This template function does not work on some older compilers | |
400 | (such as Visual C++ 6.0). For full compiler ccompatibility | |
401 | please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro | |
402 | instead. | |
403 | ||
404 | @see wxAny::CheckType() | |
405 | */ | |
406 | template <typename T> | |
407 | bool CheckType(); | |
408 | ||
409 | /** | |
410 | Convert value into buffer of different type. Return false if | |
411 | not possible. | |
412 | */ | |
413 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
414 | wxAnyValueType* dstType, | |
415 | wxAnyValueBuffer& dst) const = 0; | |
416 | ||
417 | /** | |
24985a9b JS |
418 | Implement this for buffer-to-buffer copy. |
419 | ||
420 | @param src | |
421 | This is the source data buffer. | |
422 | ||
423 | @param dst | |
424 | This is the destination data buffer that is in either | |
425 | uninitialized or freed state. | |
39601a7f VZ |
426 | */ |
427 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
428 | wxAnyValueBuffer& dst) const = 0; | |
429 | ||
430 | /** | |
431 | This function is called every time the data in wxAny | |
432 | buffer needs to be freed. | |
433 | */ | |
434 | virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0; | |
435 | ||
436 | /** | |
437 | This function is used for internal type matching. | |
438 | */ | |
439 | virtual wxAnyClassInfo GetClassInfo() const = 0; | |
440 | ||
441 | /** | |
442 | This function is used for internal type matching. | |
443 | */ | |
444 | virtual bool IsSameType(const wxAnyValueType* otherType) const = 0; | |
445 | }; | |
446 | ||
447 | /** | |
448 | This is type checking macro that is more compatible with older | |
449 | compilers, such as Visual C++ 6.0. | |
450 | */ | |
451 | #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) |