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 },
87 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e>) \
88 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e*>) \
91 #define wxEND_ENUM( e ) \
93 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
94 wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \
95 template<> void wxStringReadValue(const wxString& s, e &data ) \
96 { data = (e) s_enumData##e.GetEnumMemberValue(s); } \
97 template<> void wxStringWriteValue(wxString &s, const e &data ) \
98 { s = s_enumData##e.GetEnumMemberName((int)data); } \
99 void FromLong##e( long data, wxAny& result ) \
100 { result = wxAny((e)data); } \
101 void ToLong##e( const wxAny& data, long &result ) \
102 { result = (long) (data).As(static_cast<e*>(NULL)); } \
104 wxTO_STRING_IMP( e ) \
105 wxFROM_STRING_IMP( e ) \
106 wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \
107 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
108 &FromLong##e, typeid(e).name() );
111 // ----------------------------------------------------------------------------
123 // typedef wxBitset<wxFlavor> wxCoupe;
125 // in the implementation file :
127 // wxBEGIN_ENUM( wxFlavor )
128 // wxENUM_MEMBER( Vanilla )
129 // wxENUM_MEMBER( Chocolate )
130 // wxENUM_MEMBER( Strawberry )
131 // wxEND_ENUM( wxFlavor )
133 // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
135 // implementation note: no partial specialization for streaming, but a delegation
136 // to a different class
138 // ----------------------------------------------------------------------------
140 // in order to remove dependancy on string tokenizer
141 void WXDLLIMPEXP_BASE
wxSetStringToArray( const wxString
&s
, wxArrayString
&array
);
144 void wxSetFromString(const wxString
&s
, wxBitset
<e
> &data
)
146 wxEnumData
* edata
= wxGetEnumData((e
) 0);
150 wxSetStringToArray( s
, array
);
152 for ( int i
= 0; i
< array
.Count(); ++i
)
156 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
158 data
.set( (e
) ivalue
);
164 void wxSetToString( wxString
&s
, const wxBitset
<e
> &data
)
166 wxEnumData
* edata
= wxGetEnumData((e
) 0);
167 int count
= edata
->GetEnumCount();
170 for ( i
= 0; i
< count
; i
++ )
172 e value
= (e
) edata
->GetEnumMemberValueByIndex(i
);
173 if ( data
.test( value
) )
175 // this could also be done by the templated calls
178 s
+= edata
->GetEnumMemberNameByIndex(i
);
183 #define wxIMPLEMENT_SET_STREAMING(SetName,e) \
184 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
185 { wxSetFromString( s, data ); } \
186 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
187 { wxSetToString( s, data ); } \
188 void FromLong##SetName( long data, wxAny& result ) \
189 { result = wxAny(SetName((unsigned long)data)); } \
190 void ToLong##SetName( const wxAny& data, long &result ) \
191 { result = (long) (data).As(static_cast<SetName*>(NULL)).to_ulong(); } \
192 wxTO_STRING_IMP( SetName ) \
193 wxFROM_STRING_IMP( SetName ) \
194 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
195 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
196 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
199 void wxFlagsFromString(const wxString
&s
, e
&data
)
201 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
205 wxSetStringToArray( s
, array
);
207 for ( size_t i
= 0; i
< array
.Count(); ++i
)
211 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
213 data
.m_data
|= ivalue
;
219 void wxFlagsToString( wxString
&s
, const e
& data
)
221 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
222 int count
= edata
->GetEnumCount();
225 long dataValue
= data
.m_data
;
226 for ( i
= 0; i
< count
; i
++ )
228 int value
= edata
->GetEnumMemberValueByIndex(i
);
229 // make this to allow for multi-bit constants to work
230 if ( value
&& ( dataValue
& value
) == value
)
232 // clear the flags we just set
234 // this could also be done by the templated calls
237 s
+= edata
->GetEnumMemberNameByIndex(i
);
242 #define wxBEGIN_FLAGS( e ) \
243 wxEnumMemberData s_enumDataMembers##e[] = {
245 #define wxFLAGS_MEMBER( v ) { wxT(#v), v },
248 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e>) \
249 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e*>) \
252 #define wxEND_FLAGS( e ) \
254 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
255 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
256 template<> void wxStringReadValue(const wxString &s, e &data ) \
257 { wxFlagsFromString<e>( s, data ); } \
258 template<> void wxStringWriteValue( wxString &s, const e& data ) \
259 { wxFlagsToString<e>( s, data ); } \
260 void FromLong##e( long data, wxAny& result ) \
261 { result = wxAny(e(data)); } \
262 void ToLong##e( const wxAny& data, long &result ) \
263 { result = (long) (data).As(static_cast<e*>(NULL)).m_data; } \
264 wxTO_STRING_IMP( e ) \
265 wxFROM_STRING_IMP( e ) \
266 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
267 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
268 &FromLong##e, typeid(e).name() );
270 // ----------------------------------------------------------------------------
272 // ----------------------------------------------------------------------------
274 // All data exposed by the RTTI is characterized using the following classes.
275 // The first characterization is done by wxTypeKind. All enums up to and including
276 // wxT_CUSTOM represent so called simple types. These cannot be divided any further.
277 // They can be converted to and from wxStrings, that's all.
278 // Other wxTypeKinds can instead be splitted recursively into smaller parts until
279 // the simple types are reached.
283 wxT_VOID
= 0, // unknown type
295 wxT_STRING
, // must be wxString
296 wxT_SET
, // must be wxBitset<> template
298 wxT_CUSTOM
, // user defined type (e.g. wxPoint)
300 wxT_LAST_SIMPLE_TYPE_KIND
= wxT_CUSTOM
,
302 wxT_OBJECT_PTR
, // object reference
303 wxT_OBJECT
, // embedded object
304 wxT_COLLECTION
, // collection
306 wxT_DELEGATE
, // for connecting against an event source
308 wxT_LAST_TYPE_KIND
= wxT_DELEGATE
// sentinel for bad data, asserts, debugging
311 class WXDLLIMPEXP_BASE wxAny
;
312 class WXDLLIMPEXP_BASE wxTypeInfo
;
314 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo
*, wxTypeInfoMap
, class WXDLLIMPEXP_BASE
);
316 class WXDLLIMPEXP_BASE wxTypeInfo
319 typedef void (*wxVariant2StringFnc
)( const wxAny
& data
, wxString
&result
);
320 typedef void (*wxString2VariantFnc
)( const wxString
& data
, wxAny
&result
);
322 wxTypeInfo(wxTypeKind kind
,
323 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
324 const wxString
&name
= wxEmptyString
):
325 m_toString(to
), m_fromString(from
), m_kind(kind
), m_name(name
)
330 wxTypeInfo(wxTypeKind kind
,
331 wxVariant2StringFnc to
, wxString2VariantFnc from
,
333 m_toString(to
), m_fromString(from
), m_kind(kind
),
334 m_name(wxString::FromAscii(name
))
340 virtual ~wxTypeInfo()
345 // return the kind of this type (wxT_... constants)
346 wxTypeKind
GetKind() const { return m_kind
; }
348 // returns the unique name of this type
349 const wxString
& GetTypeName() const { return m_name
; }
351 // is this type a delegate type
352 bool IsDelegateType() const { return m_kind
== wxT_DELEGATE
; }
354 // is this type a custom type
355 bool IsCustomType() const { return m_kind
== wxT_CUSTOM
; }
357 // is this type an object type
358 bool IsObjectType() const { return m_kind
== wxT_OBJECT
|| m_kind
== wxT_OBJECT_PTR
; }
360 // can the content of this type be converted to and from strings ?
361 bool HasStringConverters() const { return m_toString
!= NULL
&& m_fromString
!= NULL
; }
363 // convert a wxAny holding data of this type into a string
364 void ConvertToString( const wxAny
& data
, wxString
&result
) const
367 (*m_toString
)( data
, result
);
369 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
372 // convert a string into a wxAny holding the corresponding data in this type
373 void ConvertFromString( const wxString
& data
, wxAny
&result
) const
376 (*m_fromString
)( data
, result
);
378 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
383 static wxTypeInfo
*FindType( const wxString
& typeName
);
386 static wxTypeInfo
*FindType(const char *typeName
)
387 { return FindType( wxString::FromAscii(typeName
) ); }
389 static wxTypeInfo
*FindType(const wxChar
*typeName
);
390 static wxTypeInfo
*FindType(const wxString
& typeName
)
393 return FindType( typeName
.wchar_str() );
395 return FindType( typeName
.char_str() );
403 wxVariant2StringFnc m_toString
;
404 wxString2VariantFnc m_fromString
;
409 // the static list of all types we know about
410 static wxTypeInfoMap
* ms_typeTable
;
413 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo
: public wxTypeInfo
416 wxBuiltInTypeInfo( wxTypeKind kind
, wxVariant2StringFnc to
= NULL
,
417 wxString2VariantFnc from
= NULL
,
418 const wxString
&name
= wxEmptyString
) :
419 wxTypeInfo( kind
, to
, from
, name
)
420 { wxASSERT_MSG( GetKind() < wxT_SET
, wxT("Illegal Kind for Base Type") ); }
423 wxBuiltInTypeInfo( wxTypeKind kind
, wxVariant2StringFnc to
,
424 wxString2VariantFnc from
, const char *name
) :
425 wxTypeInfo( kind
, to
, from
, name
)
426 { wxASSERT_MSG( GetKind() < wxT_SET
, wxT("Illegal Kind for Base Type") ); }
430 class WXDLLIMPEXP_BASE wxCustomTypeInfo
: public wxTypeInfo
433 wxCustomTypeInfo( const wxString
&name
, wxVariant2StringFnc to
,
434 wxString2VariantFnc from
) :
435 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
439 wxCustomTypeInfo( const char *name
, wxVariant2StringFnc to
,
440 wxString2VariantFnc from
) :
441 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
446 class WXDLLIMPEXP_BASE wxEnumTypeInfo
: public wxTypeInfo
449 typedef void (*converterToLong_t
)( const wxAny
& data
, long &result
);
450 typedef void (*converterFromLong_t
)( long data
, wxAny
&result
);
452 wxEnumTypeInfo( wxTypeKind kind
, wxEnumData
* enumInfo
, wxVariant2StringFnc to
,
453 wxString2VariantFnc from
, converterToLong_t toLong
,
454 converterFromLong_t fromLong
, const wxString
&name
) :
455 wxTypeInfo( kind
, to
, from
, name
), m_toLong( toLong
), m_fromLong( fromLong
)
457 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
458 wxT("Illegal Kind for Enum Type"));
459 m_enumInfo
= enumInfo
;
463 wxEnumTypeInfo( wxTypeKind kind
, wxEnumData
* enumInfo
, wxVariant2StringFnc to
,
464 wxString2VariantFnc from
, converterToLong_t toLong
,
465 converterFromLong_t fromLong
, const char * name
) :
466 wxTypeInfo( kind
, to
, from
, name
), m_toLong( toLong
), m_fromLong( fromLong
)
468 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
469 wxT("Illegal Kind for Enum Type"));
470 m_enumInfo
= enumInfo
;
473 const wxEnumData
* GetEnumData() const { return m_enumInfo
; }
475 // convert a wxAny holding data of this type into a long
476 void ConvertToLong( const wxAny
& data
, long &result
) const
479 (*m_toLong
)( data
, result
);
481 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
484 // convert a long into a wxAny holding the corresponding data in this type
485 void ConvertFromLong( long data
, wxAny
&result
) const
488 (*m_fromLong
)( data
, result
);
490 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
494 converterToLong_t m_toLong
;
495 converterFromLong_t m_fromLong
;
497 wxEnumData
*m_enumInfo
; // Kind == wxT_ENUM or Kind == wxT_SET
500 class WXDLLIMPEXP_BASE wxClassTypeInfo
: public wxTypeInfo
503 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
,
504 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
505 const wxString
&name
= wxEmptyString
);
508 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
, wxVariant2StringFnc to
,
509 wxString2VariantFnc from
, const char *name
);
512 const wxClassInfo
*GetClassInfo() const { return m_classInfo
; }
515 wxClassInfo
*m_classInfo
; // Kind == wxT_OBJECT - could be NULL
518 class WXDLLIMPEXP_BASE wxCollectionTypeInfo
: public wxTypeInfo
521 wxCollectionTypeInfo( const wxString
&elementName
, wxVariant2StringFnc to
,
522 wxString2VariantFnc from
, const wxString
&name
) :
523 wxTypeInfo( wxT_COLLECTION
, to
, from
, name
)
524 { m_elementTypeName
= elementName
; m_elementType
= NULL
; }
527 wxCollectionTypeInfo( const char *elementName
, wxVariant2StringFnc to
,
528 wxString2VariantFnc from
, const char *name
) :
529 wxTypeInfo( wxT_COLLECTION
, to
, from
, name
)
530 { m_elementTypeName
= wxString::FromAscii( elementName
); m_elementType
= NULL
; }
533 const wxTypeInfo
* GetElementType() const
535 if ( m_elementType
== NULL
)
536 m_elementType
= wxTypeInfo::FindType( m_elementTypeName
);
537 return m_elementType
;
541 mutable wxTypeInfo
* m_elementType
;
542 wxString m_elementTypeName
;
545 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo
: public wxTypeInfo
548 wxEventSourceTypeInfo( int eventType
, wxClassInfo
* eventClass
,
549 wxVariant2StringFnc to
= NULL
,
550 wxString2VariantFnc from
= NULL
);
551 wxEventSourceTypeInfo( int eventType
, int lastEventType
, wxClassInfo
* eventClass
,
552 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
);
554 int GetEventType() const { return m_eventType
; }
555 int GetLastEventType() const { return m_lastEventType
; }
556 const wxClassInfo
* GetEventClass() const { return m_eventClass
; }
559 const wxClassInfo
*m_eventClass
; // (extended will merge into classinfo)
564 template<typename T
> const wxTypeInfo
* wxGetTypeInfo( T
* )
565 { return wxTypeInfo::FindType(typeid(T
).name()); }
567 // this macro is for usage with custom, non-object derived classes and structs,
568 // wxPoint is such a custom type
570 #if wxUSE_FUNC_TEMPLATE_POINTER
571 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
572 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
574 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
575 void ToString##e( const wxAny& data, wxString &result ) \
576 { toString(data, result); } \
577 void FromString##e( const wxString& data, wxAny &result ) \
578 { fromString(data, result); } \
579 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
580 &ToString##e, &FromString##e);
583 #define wxCOLLECTION_TYPE_INFO( element, collection ) \
584 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
585 NULL, NULL, typeid(collection).name() );
587 // sometimes a compiler invents specializations that are nowhere called,
588 // use this macro to satisfy the refs, currently we don't have to play
589 // tricks, but if we will have to according to the compiler, we will use
590 // that macro for that
592 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
594 #endif // wxUSE_EXTENDED_RTTI
595 #endif // _XTITYPES_H_