1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: enum, set, basic types support
4 // Author: Stefan Csomor
5 // Modified by: Francesco Montorsi
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2003 Stefan Csomor
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
18 #if wxUSE_EXTENDED_RTTI
20 #include "wx/string.h"
21 #include "wx/hashmap.h"
22 #include "wx/arrstr.h"
28 class WXDLLIMPEXP_BASE wxClassInfo
;
30 // ----------------------------------------------------------------------------
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:
36 // wxBEGIN_ENUM( wxFlavor )
37 // wxENUM_MEMBER( Vanilla )
38 // wxENUM_MEMBER( Chocolate )
39 // wxENUM_MEMBER( Strawberry )
40 // wxEND_ENUM( wxFlavor )
41 // ----------------------------------------------------------------------------
43 struct WXDLLIMPEXP_BASE wxEnumMemberData
49 class WXDLLIMPEXP_BASE wxEnumData
52 wxEnumData( wxEnumMemberData
* data
);
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;
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;
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;
67 // returns the number of members in this enum
68 int GetEnumCount() const { return m_count
; }
70 // returns the value of the nth member
71 int GetEnumMemberValueByIndex( int n
) const;
73 // returns the value of the nth member
74 const wxChar
*GetEnumMemberNameByIndex( int n
) const;
77 wxEnumMemberData
*m_members
;
81 #define wxBEGIN_ENUM( e ) \
82 wxEnumMemberData s_enumDataMembers##e[] = {
84 #define wxENUM_MEMBER( v ) { wxT(#v), v },
86 #define wxEND_ENUM( e ) \
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 ) \
91 { data = (e) s_enumData##e.GetEnumMemberValue(s); } \
92 template<> void wxStringWriteValue(wxString &s, const e &data ) \
93 { s = s_enumData##e.GetEnumMemberName((int)data); } \
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)); } \
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() );
106 // ----------------------------------------------------------------------------
118 // typedef wxBitset<wxFlavor> wxCoupe;
120 // in the implementation file :
122 // wxBEGIN_ENUM( wxFlavor )
123 // wxENUM_MEMBER( Vanilla )
124 // wxENUM_MEMBER( Chocolate )
125 // wxENUM_MEMBER( Strawberry )
126 // wxEND_ENUM( wxFlavor )
128 // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
130 // implementation note: no partial specialization for streaming, but a delegation
131 // to a different class
133 // ----------------------------------------------------------------------------
135 void WXDLLIMPEXP_BASE
wxSetStringToArray( const wxString
&s
, wxArrayString
&array
);
138 void wxSetFromString(const wxString
&s
, wxBitset
<e
> &data
)
140 wxEnumData
* edata
= wxGetEnumData((e
) 0);
144 wxSetStringToArray( s
, array
);
146 for ( int i
= 0; i
< array
.Count(); ++i
)
150 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
152 data
.set( (e
) ivalue
);
158 void wxSetToString( wxString
&s
, const wxBitset
<e
> &data
)
160 wxEnumData
* edata
= wxGetEnumData((e
) 0);
161 int count
= edata
->GetEnumCount();
164 for ( i
= 0; i
< count
; i
++ )
166 e value
= (e
) edata
->GetEnumMemberValueByIndex(i
);
167 if ( data
.test( value
) )
169 // this could also be done by the templated calls
172 s
+= edata
->GetEnumMemberNameByIndex(i
);
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 ); } \
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(); } \
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() );
193 void wxFlagsFromString(const wxString
&s
, e
&data
)
195 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
199 wxSetStringToArray( s
, array
);
201 for ( size_t i
= 0; i
< array
.Count(); ++i
)
205 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
207 data
.m_data
|= ivalue
;
213 void wxFlagsToString( wxString
&s
, const e
& data
)
215 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
216 int count
= edata
->GetEnumCount();
219 long dataValue
= data
.m_data
;
220 for ( i
= 0; i
< count
; i
++ )
222 int value
= edata
->GetEnumMemberValueByIndex(i
);
223 // make this to allow for multi-bit constants to work
224 if ( value
&& ( dataValue
& value
) == value
)
226 // clear the flags we just set
228 // this could also be done by the templated calls
231 s
+= edata
->GetEnumMemberNameByIndex(i
);
236 #define wxBEGIN_FLAGS( e ) \
237 wxEnumMemberData s_enumDataMembers##e[] = {
239 #define wxFLAGS_MEMBER( v ) { wxT(#v), v },
241 #define wxEND_FLAGS( e ) \
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 ); } \
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; } \
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() );
259 // ----------------------------------------------------------------------------
261 // ----------------------------------------------------------------------------
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.
272 wxT_VOID
= 0, // unknown type
284 wxT_STRING
, // must be wxString
285 wxT_SET
, // must be wxBitset<> template
287 wxT_CUSTOM
, // user defined type (e.g. wxPoint)
289 wxT_LAST_SIMPLE_TYPE_KIND
= wxT_CUSTOM
,
291 wxT_OBJECT_PTR
, // object reference
292 wxT_OBJECT
, // embedded object
293 wxT_COLLECTION
, // collection
295 wxT_DELEGATE
, // for connecting against an event source
297 wxT_LAST_TYPE_KIND
= wxT_DELEGATE
// sentinel for bad data, asserts, debugging
300 class WXDLLIMPEXP_BASE wxAny
;
301 class WXDLLIMPEXP_BASE wxTypeInfo
;
303 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo
*, wxTypeInfoMap
, class WXDLLIMPEXP_BASE
);
305 class WXDLLIMPEXP_BASE wxTypeInfo
308 typedef void (*wxVariant2StringFnc
)( const wxAny
& data
, wxString
&result
);
309 typedef void (*wxString2VariantFnc
)( const wxString
& data
, wxAny
&result
);
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
)
318 #if 0 // wxUSE_UNICODE
319 wxTypeInfo(wxTypeKind kind
,
320 wxVariant2StringFnc to
, wxString2VariantFnc from
,
322 m_toString(to
), m_fromString(from
), m_kind(kind
),
323 m_name(wxString::FromAscii(name
))
329 virtual ~wxTypeInfo()
334 // return the kind of this type (wxT_... constants)
335 wxTypeKind
GetKind() const { return m_kind
; }
337 // returns the unique name of this type
338 const wxString
& GetTypeName() const { return m_name
; }
340 // is this type a delegate type
341 bool IsDelegateType() const { return m_kind
== wxT_DELEGATE
; }
343 // is this type a custom type
344 bool IsCustomType() const { return m_kind
== wxT_CUSTOM
; }
346 // is this type an object type
347 bool IsObjectType() const { return m_kind
== wxT_OBJECT
|| m_kind
== wxT_OBJECT_PTR
; }
349 // can the content of this type be converted to and from strings ?
350 bool HasStringConverters() const { return m_toString
!= NULL
&& m_fromString
!= NULL
; }
352 // convert a wxAny holding data of this type into a string
353 void ConvertToString( const wxAny
& data
, wxString
&result
) const
356 (*m_toString
)( data
, result
);
358 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
361 // convert a string into a wxAny holding the corresponding data in this type
362 void ConvertFromString( const wxString
& data
, wxAny
&result
) const
365 (*m_fromString
)( data
, result
);
367 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
372 // looks for the corresponding type, will return NULL if not found
373 static wxTypeInfo
*FindType( const wxString
& typeName
);
378 wxVariant2StringFnc m_toString
;
379 wxString2VariantFnc m_fromString
;
384 // the static list of all types we know about
385 static wxTypeInfoMap
* ms_typeTable
;
388 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo
: public wxTypeInfo
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") ); }
398 class WXDLLIMPEXP_BASE wxCustomTypeInfo
: public wxTypeInfo
401 wxCustomTypeInfo( const wxString
&name
, wxVariant2StringFnc to
,
402 wxString2VariantFnc from
) :
403 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
407 class WXDLLIMPEXP_BASE wxEnumTypeInfo
: public wxTypeInfo
410 typedef void (*converterToLong_t
)( const wxAny
& data
, long &result
);
411 typedef void (*converterFromLong_t
)( long data
, wxAny
&result
);
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
)
418 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
419 wxT("Illegal Kind for Enum Type"));
420 m_enumInfo
= enumInfo
;
423 const wxEnumData
* GetEnumData() const { return m_enumInfo
; }
425 // convert a wxAny holding data of this type into a long
426 void ConvertToLong( const wxAny
& data
, long &result
) const
429 (*m_toLong
)( data
, result
);
431 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
434 // convert a long into a wxAny holding the corresponding data in this type
435 void ConvertFromLong( long data
, wxAny
&result
) const
438 (*m_fromLong
)( data
, result
);
440 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
444 converterToLong_t m_toLong
;
445 converterFromLong_t m_fromLong
;
447 wxEnumData
*m_enumInfo
; // Kind == wxT_ENUM or Kind == wxT_SET
450 class WXDLLIMPEXP_BASE wxClassTypeInfo
: public wxTypeInfo
453 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
,
454 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
455 const wxString
&name
= wxEmptyString
);
457 const wxClassInfo
*GetClassInfo() const { return m_classInfo
; }
460 wxClassInfo
*m_classInfo
; // Kind == wxT_OBJECT - could be NULL
463 class WXDLLIMPEXP_BASE wxCollectionTypeInfo
: public wxTypeInfo
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
; }
471 const wxTypeInfo
* GetElementType() const
473 if ( m_elementType
== NULL
)
474 m_elementType
= wxTypeInfo::FindType( m_elementTypeName
);
475 return m_elementType
;
479 mutable wxTypeInfo
* m_elementType
;
480 wxString m_elementTypeName
;
483 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo
: public wxTypeInfo
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
);
492 int GetEventType() const { return m_eventType
; }
493 int GetLastEventType() const { return m_lastEventType
; }
494 const wxClassInfo
* GetEventClass() const { return m_eventClass
; }
497 const wxClassInfo
*m_eventClass
; // (extended will merge into classinfo)
502 template<typename T
> const wxTypeInfo
* wxGetTypeInfo( T
* )
503 { return wxTypeInfo::FindType(typeid(T
).name()); }
505 // this macro is for usage with custom, non-object derived classes and structs,
506 // wxPoint is such a custom type
508 #if wxUSE_FUNC_TEMPLATE_POINTER
509 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
510 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
512 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
513 void ToString##e( const wxAny& data, wxString &result ) \
514 { toString(data, result); } \
515 void FromString##e( const wxString& data, wxAny &result ) \
516 { fromString(data, result); } \
517 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
518 &ToString##e, &FromString##e);
521 #define wxCOLLECTION_TYPE_INFO( element, collection ) \
522 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
523 NULL, NULL, typeid(collection).name() );
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
530 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
532 #endif // wxUSE_EXTENDED_RTTI
533 #endif // _XTITYPES_H_