]> git.saurik.com Git - wxWidgets.git/blame - include/wx/xtitypes.h
A better fix for wxHash{Map,Set} with g++ 4.7.
[wxWidgets.git] / include / wx / xtitypes.h
CommitLineData
e1d3601a
PC
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/xtitypes.h
3// Purpose: enum, set, basic types support
4// Author: Stefan Csomor
5// Modified by: Francesco Montorsi
6// Created: 27/07/03
7// RCS-ID: $Id$
8// Copyright: (c) 1997 Julian Smart
9// (c) 2003 Stefan Csomor
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13#ifndef _XTITYPES_H_
14#define _XTITYPES_H_
15
16#include "wx/defs.h"
17
18#if wxUSE_EXTENDED_RTTI
19
20#include "wx/string.h"
21#include "wx/hashmap.h"
22#include "wx/arrstr.h"
23#include "wx/flags.h"
24#include "wx/intl.h"
25#include "wx/log.h"
26#include <typeinfo>
27
28class WXDLLIMPEXP_BASE wxClassInfo;
29
30// ----------------------------------------------------------------------------
31// Enum Support
32//
33// In the header files XTI requires no change from pure c++ code, however in the
34// implementation, an enum needs to be enumerated eg:
35//
36// wxBEGIN_ENUM( wxFlavor )
37// wxENUM_MEMBER( Vanilla )
38// wxENUM_MEMBER( Chocolate )
39// wxENUM_MEMBER( Strawberry )
40// wxEND_ENUM( wxFlavor )
41// ----------------------------------------------------------------------------
42
43struct WXDLLIMPEXP_BASE wxEnumMemberData
44{
45 const wxChar* m_name;
46 int m_value;
47};
48
49class WXDLLIMPEXP_BASE wxEnumData
50{
51public:
52 wxEnumData( wxEnumMemberData* data );
53
54 // returns true if the member has been found and sets the int value
55 // pointed to accordingly (if ptr != null )
56 // if not found returns false, value left unchanged
57 bool HasEnumMemberValue( const wxChar *name, int *value = NULL ) const;
58
59 // returns the value of the member, if not found in debug mode an
60 // assert is issued, in release 0 is returned
61 int GetEnumMemberValue(const wxChar *name ) const;
62
63 // returns the name of the enum member having the passed in value
64 // returns an emtpy string if not found
65 const wxChar *GetEnumMemberName(int value) const;
66
67 // returns the number of members in this enum
68 int GetEnumCount() const { return m_count; }
69
70 // returns the value of the nth member
71 int GetEnumMemberValueByIndex( int n ) const;
72
73 // returns the value of the nth member
74 const wxChar *GetEnumMemberNameByIndex( int n ) const;
75
76private:
77 wxEnumMemberData *m_members;
78 int m_count;
79};
80
81#define wxBEGIN_ENUM( e ) \
82 wxEnumMemberData s_enumDataMembers##e[] = {
83
84#define wxENUM_MEMBER( v ) { wxT(#v), v },
85
86#define wxEND_ENUM( e ) \
87 { NULL, 0 } }; \
88 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
89 wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \
90 template<> void wxStringReadValue(const wxString& s, e &data ) \
44a00712 91 { data = (e) s_enumData##e.GetEnumMemberValue(s.c_str()); } \
e1d3601a
PC
92 template<> void wxStringWriteValue(wxString &s, const e &data ) \
93 { s = s_enumData##e.GetEnumMemberName((int)data); } \
6c887dde
SC
94 void FromLong##e( long data, wxAny& result ) \
95 { result = wxAny((e)data); } \
96 void ToLong##e( const wxAny& data, long &result ) \
97 { result = (long) (data).As(static_cast<e*>(NULL)); } \
e1d3601a
PC
98 \
99 wxTO_STRING_IMP( e ) \
100 wxFROM_STRING_IMP( e ) \
101 wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \
102 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
103 &FromLong##e, typeid(e).name() );
104
105
106// ----------------------------------------------------------------------------
107// Set Support
108//
109// in the header :
110//
111// enum wxFlavor
112// {
113// Vanilla,
114// Chocolate,
115// Strawberry,
116// };
117//
118// typedef wxBitset<wxFlavor> wxCoupe;
119//
120// in the implementation file :
121//
122// wxBEGIN_ENUM( wxFlavor )
123// wxENUM_MEMBER( Vanilla )
124// wxENUM_MEMBER( Chocolate )
125// wxENUM_MEMBER( Strawberry )
126// wxEND_ENUM( wxFlavor )
127//
128// wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
129//
130// implementation note: no partial specialization for streaming, but a delegation
131// to a different class
132//
133// ----------------------------------------------------------------------------
134
e1d3601a
PC
135void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array );
136
137template<typename e>
138void wxSetFromString(const wxString &s, wxBitset<e> &data )
139{
140 wxEnumData* edata = wxGetEnumData((e) 0);
141 data.reset();
142
143 wxArrayString array;
144 wxSetStringToArray( s, array );
145 wxString flag;
146 for ( int i = 0; i < array.Count(); ++i )
147 {
148 flag = array[i];
149 int ivalue;
31ba1c7e 150 if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
e1d3601a
PC
151 {
152 data.set( (e) ivalue );
153 }
154 }
155}
156
157template<typename e>
158void wxSetToString( wxString &s, const wxBitset<e> &data )
159{
160 wxEnumData* edata = wxGetEnumData((e) 0);
161 int count = edata->GetEnumCount();
162 int i;
163 s.Clear();
164 for ( i = 0; i < count; i++ )
165 {
166 e value = (e) edata->GetEnumMemberValueByIndex(i);
167 if ( data.test( value ) )
168 {
169 // this could also be done by the templated calls
170 if ( !s.empty() )
171 s += wxT("|");
172 s += edata->GetEnumMemberNameByIndex(i);
173 }
174 }
175}
176
177#define wxIMPLEMENT_SET_STREAMING(SetName,e) \
178 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
179 { wxSetFromString( s, data ); } \
180 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
181 { wxSetToString( s, data ); } \
6c887dde
SC
182 void FromLong##SetName( long data, wxAny& result ) \
183 { result = wxAny(SetName((unsigned long)data)); } \
184 void ToLong##SetName( const wxAny& data, long &result ) \
185 { result = (long) (data).As(static_cast<SetName*>(NULL)).to_ulong(); } \
e1d3601a
PC
186 wxTO_STRING_IMP( SetName ) \
187 wxFROM_STRING_IMP( SetName ) \
188 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
189 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
190 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
191
192template<typename e>
193void wxFlagsFromString(const wxString &s, e &data )
194{
195 wxEnumData* edata = wxGetEnumData((e*) 0);
196 data.m_data = 0;
197
198 wxArrayString array;
199 wxSetStringToArray( s, array );
200 wxString flag;
201 for ( size_t i = 0; i < array.Count(); ++i )
202 {
203 flag = array[i];
204 int ivalue;
44a00712 205 if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
e1d3601a
PC
206 {
207 data.m_data |= ivalue;
208 }
209 }
210}
211
212template<typename e>
213void wxFlagsToString( wxString &s, const e& data )
214{
215 wxEnumData* edata = wxGetEnumData((e*) 0);
216 int count = edata->GetEnumCount();
217 int i;
218 s.Clear();
219 long dataValue = data.m_data;
220 for ( i = 0; i < count; i++ )
221 {
222 int value = edata->GetEnumMemberValueByIndex(i);
223 // make this to allow for multi-bit constants to work
224 if ( value && ( dataValue & value ) == value )
225 {
226 // clear the flags we just set
227 dataValue &= ~value;
228 // this could also be done by the templated calls
229 if ( !s.empty() )
230 s +=wxT("|");
231 s += edata->GetEnumMemberNameByIndex(i);
232 }
233 }
234}
235
236#define wxBEGIN_FLAGS( e ) \
237 wxEnumMemberData s_enumDataMembers##e[] = {
238
29a1e530 239#define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast<int>(v) },
e1d3601a
PC
240
241#define wxEND_FLAGS( e ) \
242 { NULL, 0 } }; \
243 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
244 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
245 template<> void wxStringReadValue(const wxString &s, e &data ) \
246 { wxFlagsFromString<e>( s, data ); } \
247 template<> void wxStringWriteValue( wxString &s, const e& data ) \
248 { wxFlagsToString<e>( s, data ); } \
6c887dde
SC
249 void FromLong##e( long data, wxAny& result ) \
250 { result = wxAny(e(data)); } \
251 void ToLong##e( const wxAny& data, long &result ) \
252 { result = (long) (data).As(static_cast<e*>(NULL)).m_data; } \
e1d3601a
PC
253 wxTO_STRING_IMP( e ) \
254 wxFROM_STRING_IMP( e ) \
255 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
256 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
257 &FromLong##e, typeid(e).name() );
258
259// ----------------------------------------------------------------------------
260// Type Information
261// ----------------------------------------------------------------------------
262
263// All data exposed by the RTTI is characterized using the following classes.
264// The first characterization is done by wxTypeKind. All enums up to and including
265// wxT_CUSTOM represent so called simple types. These cannot be divided any further.
266// They can be converted to and from wxStrings, that's all.
267// Other wxTypeKinds can instead be splitted recursively into smaller parts until
268// the simple types are reached.
269
270enum wxTypeKind
271{
272 wxT_VOID = 0, // unknown type
273 wxT_BOOL,
274 wxT_CHAR,
275 wxT_UCHAR,
276 wxT_INT,
277 wxT_UINT,
278 wxT_LONG,
279 wxT_ULONG,
6c887dde
SC
280 wxT_LONGLONG,
281 wxT_ULONGLONG,
e1d3601a
PC
282 wxT_FLOAT,
283 wxT_DOUBLE,
284 wxT_STRING, // must be wxString
285 wxT_SET, // must be wxBitset<> template
286 wxT_ENUM,
287 wxT_CUSTOM, // user defined type (e.g. wxPoint)
288
289 wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM,
290
291 wxT_OBJECT_PTR, // object reference
292 wxT_OBJECT, // embedded object
293 wxT_COLLECTION, // collection
294
295 wxT_DELEGATE, // for connecting against an event source
296
297 wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging
298};
299
6c887dde 300class WXDLLIMPEXP_BASE wxAny;
e1d3601a
PC
301class WXDLLIMPEXP_BASE wxTypeInfo;
302
303WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE );
304
305class WXDLLIMPEXP_BASE wxTypeInfo
306{
307public:
6c887dde
SC
308 typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result );
309 typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result );
e1d3601a
PC
310
311 wxTypeInfo(wxTypeKind kind,
312 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
313 const wxString &name = wxEmptyString):
314 m_toString(to), m_fromString(from), m_kind(kind), m_name(name)
315 {
316 Register();
317 }
f06d6937 318#if 0 // wxUSE_UNICODE
e1d3601a
PC
319 wxTypeInfo(wxTypeKind kind,
320 wxVariant2StringFnc to, wxString2VariantFnc from,
321 const char *name):
322 m_toString(to), m_fromString(from), m_kind(kind),
323 m_name(wxString::FromAscii(name))
324 {
325 Register();
326 }
327#endif
328
329 virtual ~wxTypeInfo()
330 {
331 Unregister();
332 }
333
334 // return the kind of this type (wxT_... constants)
335 wxTypeKind GetKind() const { return m_kind; }
336
337 // returns the unique name of this type
338 const wxString& GetTypeName() const { return m_name; }
339
340 // is this type a delegate type
341 bool IsDelegateType() const { return m_kind == wxT_DELEGATE; }
342
343 // is this type a custom type
344 bool IsCustomType() const { return m_kind == wxT_CUSTOM; }
345
346 // is this type an object type
347 bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; }
348
349 // can the content of this type be converted to and from strings ?
350 bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; }
351
6c887dde
SC
352 // convert a wxAny holding data of this type into a string
353 void ConvertToString( const wxAny& data, wxString &result ) const
e1d3601a
PC
354 {
355 if ( m_toString )
356 (*m_toString)( data, result );
357 else
ebd98179 358 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
e1d3601a
PC
359 }
360
6c887dde
SC
361 // convert a string into a wxAny holding the corresponding data in this type
362 void ConvertFromString( const wxString& data, wxAny &result ) const
e1d3601a
PC
363 {
364 if( m_fromString )
365 (*m_fromString)( data, result );
366 else
ebd98179 367 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
e1d3601a
PC
368 }
369
370 // statics:
371
c294641f 372 // looks for the corresponding type, will return NULL if not found
6c887dde 373 static wxTypeInfo *FindType( const wxString& typeName );
e1d3601a
PC
374private:
375 void Register();
376 void Unregister();
377
378 wxVariant2StringFnc m_toString;
379 wxString2VariantFnc m_fromString;
380
381 wxTypeKind m_kind;
382 wxString m_name;
383
384 // the static list of all types we know about
385 static wxTypeInfoMap* ms_typeTable;
386};
387
388class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo
389{
390public:
391 wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL,
392 wxString2VariantFnc from = NULL,
393 const wxString &name = wxEmptyString ) :
394 wxTypeInfo( kind, to, from, name )
395 { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
e1d3601a
PC
396};
397
398class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo
399{
400public:
401 wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to,
402 wxString2VariantFnc from ) :
403 wxTypeInfo( wxT_CUSTOM, to, from, name )
404 {}
e1d3601a
PC
405};
406
407class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo
408{
409public:
6c887dde
SC
410 typedef void (*converterToLong_t)( const wxAny& data, long &result );
411 typedef void (*converterFromLong_t)( long data, wxAny &result );
e1d3601a
PC
412
413 wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to,
414 wxString2VariantFnc from, converterToLong_t toLong,
415 converterFromLong_t fromLong, const wxString &name ) :
416 wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong )
417 {
418 wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
419 wxT("Illegal Kind for Enum Type"));
420 m_enumInfo = enumInfo;
421 }
422
e1d3601a
PC
423 const wxEnumData* GetEnumData() const { return m_enumInfo; }
424
6c887dde
SC
425 // convert a wxAny holding data of this type into a long
426 void ConvertToLong( const wxAny& data, long &result ) const
e1d3601a
PC
427 {
428 if( m_toLong )
429 (*m_toLong)( data, result );
430 else
ebd98179 431 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
e1d3601a
PC
432 }
433
6c887dde
SC
434 // convert a long into a wxAny holding the corresponding data in this type
435 void ConvertFromLong( long data, wxAny &result ) const
e1d3601a
PC
436 {
437 if( m_fromLong )
438 (*m_fromLong)( data, result );
439 else
ebd98179 440 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
e1d3601a
PC
441 }
442
443private:
444 converterToLong_t m_toLong;
445 converterFromLong_t m_fromLong;
446
447 wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET
448};
449
450class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo
451{
452public:
453 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
454 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
455 const wxString &name = wxEmptyString);
456
e1d3601a
PC
457 const wxClassInfo *GetClassInfo() const { return m_classInfo; }
458
459private:
460 wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL
461};
462
463class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo
464{
465public:
466 wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to,
467 wxString2VariantFnc from , const wxString &name) :
468 wxTypeInfo( wxT_COLLECTION, to, from, name )
469 { m_elementTypeName = elementName; m_elementType = NULL; }
470
e1d3601a
PC
471 const wxTypeInfo* GetElementType() const
472 {
473 if ( m_elementType == NULL )
474 m_elementType = wxTypeInfo::FindType( m_elementTypeName );
475 return m_elementType;
476 }
477
478private:
479 mutable wxTypeInfo * m_elementType;
480 wxString m_elementTypeName;
481};
482
483class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo
484{
485public:
486 wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass,
487 wxVariant2StringFnc to = NULL,
488 wxString2VariantFnc from = NULL );
489 wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass,
490 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL );
491
492 int GetEventType() const { return m_eventType; }
493 int GetLastEventType() const { return m_lastEventType; }
494 const wxClassInfo* GetEventClass() const { return m_eventClass; }
495
496private:
497 const wxClassInfo *m_eventClass; // (extended will merge into classinfo)
498 int m_eventType;
499 int m_lastEventType;
500};
501
6c887dde 502template<typename T> const wxTypeInfo* wxGetTypeInfo( T * )
e1d3601a
PC
503 { return wxTypeInfo::FindType(typeid(T).name()); }
504
505// this macro is for usage with custom, non-object derived classes and structs,
506// wxPoint is such a custom type
507
508#if wxUSE_FUNC_TEMPLATE_POINTER
509 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
510 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
511#else
512 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
6c887dde 513 void ToString##e( const wxAny& data, wxString &result ) \
e1d3601a 514 { toString(data, result); } \
6c887dde 515 void FromString##e( const wxString& data, wxAny &result ) \
e1d3601a
PC
516 { fromString(data, result); } \
517 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
518 &ToString##e, &FromString##e);
519#endif
520
521#define wxCOLLECTION_TYPE_INFO( element, collection ) \
522 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
523 NULL, NULL, typeid(collection).name() );
524
525// sometimes a compiler invents specializations that are nowhere called,
526// use this macro to satisfy the refs, currently we don't have to play
527// tricks, but if we will have to according to the compiler, we will use
528// that macro for that
529
530#define wxILLEGAL_TYPE_SPECIALIZATION( a )
531
532#endif // wxUSE_EXTENDED_RTTI
533#endif // _XTITYPES_H_