1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: enum, set, basic types support
4 // Author: Stefan Csomor
5 // Modified by: Francesco Montorsi
7 // RCS-ID: $Id: xti.h 47299 2007-07-10 15:58:27Z FM $
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, wxVariantBase& result ) \
95 { result = wxVariantBase((e)data); } \
96 void ToLong##e( const wxVariantBase& data, long &result ) \
97 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e); } \
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 // in order to remove dependancy on string tokenizer
136 void WXDLLIMPEXP_BASE
wxSetStringToArray( const wxString
&s
, wxArrayString
&array
);
139 void wxSetFromString(const wxString
&s
, wxBitset
<e
> &data
)
141 wxEnumData
* edata
= wxGetEnumData((e
) 0);
145 wxSetStringToArray( s
, array
);
147 for ( int i
= 0; i
< array
.Count(); ++i
)
151 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
153 data
.set( (e
) ivalue
);
159 void wxSetToString( wxString
&s
, const wxBitset
<e
> &data
)
161 wxEnumData
* edata
= wxGetEnumData((e
) 0);
162 int count
= edata
->GetEnumCount();
165 for ( i
= 0; i
< count
; i
++ )
167 e value
= (e
) edata
->GetEnumMemberValueByIndex(i
);
168 if ( data
.test( value
) )
170 // this could also be done by the templated calls
173 s
+= edata
->GetEnumMemberNameByIndex(i
);
178 #define wxIMPLEMENT_SET_STREAMING(SetName,e) \
179 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
180 { wxSetFromString( s, data ); } \
181 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
182 { wxSetToString( s, data ); } \
183 void FromLong##SetName( long data, wxVariantBase& result ) \
184 { result = wxVariantBase(SetName((unsigned long)data)); } \
185 void ToLong##SetName( const wxVariantBase& data, long &result ) \
186 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, SetName).to_ulong(); } \
187 wxTO_STRING_IMP( SetName ) \
188 wxFROM_STRING_IMP( SetName ) \
189 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
190 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
191 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
194 void wxFlagsFromString(const wxString
&s
, e
&data
)
196 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
200 wxSetStringToArray( s
, array
);
202 for ( size_t i
= 0; i
< array
.Count(); ++i
)
206 if ( edata
->HasEnumMemberValue( flag
, &ivalue
) )
208 data
.m_data
|= ivalue
;
214 void wxFlagsToString( wxString
&s
, const e
& data
)
216 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
217 int count
= edata
->GetEnumCount();
220 long dataValue
= data
.m_data
;
221 for ( i
= 0; i
< count
; i
++ )
223 int value
= edata
->GetEnumMemberValueByIndex(i
);
224 // make this to allow for multi-bit constants to work
225 if ( value
&& ( dataValue
& value
) == value
)
227 // clear the flags we just set
229 // this could also be done by the templated calls
232 s
+= edata
->GetEnumMemberNameByIndex(i
);
237 #define wxBEGIN_FLAGS( e ) \
238 wxEnumMemberData s_enumDataMembers##e[] = {
240 #define wxFLAGS_MEMBER( v ) { wxT(#v), v },
242 #define wxEND_FLAGS( e ) \
244 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
245 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
246 template<> void wxStringReadValue(const wxString &s, e &data ) \
247 { wxFlagsFromString<e>( s, data ); } \
248 template<> void wxStringWriteValue( wxString &s, const e& data ) \
249 { wxFlagsToString<e>( s, data ); } \
250 void FromLong##e( long data, wxVariantBase& result ) \
251 { result = wxVariantBase(e(data)); } \
252 void ToLong##e( const wxVariantBase& data, long &result ) \
253 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e).m_data; } \
254 wxTO_STRING_IMP( e ) \
255 wxFROM_STRING_IMP( e ) \
256 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
257 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
258 &FromLong##e, typeid(e).name() );
260 // ----------------------------------------------------------------------------
262 // ----------------------------------------------------------------------------
264 // All data exposed by the RTTI is characterized using the following classes.
265 // The first characterization is done by wxTypeKind. All enums up to and including
266 // wxT_CUSTOM represent so called simple types. These cannot be divided any further.
267 // They can be converted to and from wxStrings, that's all.
268 // Other wxTypeKinds can instead be splitted recursively into smaller parts until
269 // the simple types are reached.
273 wxT_VOID
= 0, // unknown type
283 wxT_STRING
, // must be wxString
284 wxT_SET
, // must be wxBitset<> template
286 wxT_CUSTOM
, // user defined type (e.g. wxPoint)
288 wxT_LAST_SIMPLE_TYPE_KIND
= wxT_CUSTOM
,
290 wxT_OBJECT_PTR
, // object reference
291 wxT_OBJECT
, // embedded object
292 wxT_COLLECTION
, // collection
294 wxT_DELEGATE
, // for connecting against an event source
296 wxT_LAST_TYPE_KIND
= wxT_DELEGATE
// sentinel for bad data, asserts, debugging
299 class WXDLLIMPEXP_BASE wxVariantBase
;
300 class WXDLLIMPEXP_BASE wxTypeInfo
;
302 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo
*, wxTypeInfoMap
, class WXDLLIMPEXP_BASE
);
304 class WXDLLIMPEXP_BASE wxTypeInfo
307 typedef void (*wxVariant2StringFnc
)( const wxVariantBase
& data
, wxString
&result
);
308 typedef void (*wxString2VariantFnc
)( const wxString
& data
, wxVariantBase
&result
);
310 wxTypeInfo(wxTypeKind kind
,
311 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
312 const wxString
&name
= wxEmptyString
):
313 m_toString(to
), m_fromString(from
), m_kind(kind
), m_name(name
)
318 wxTypeInfo(wxTypeKind kind
,
319 wxVariant2StringFnc to
, wxString2VariantFnc from
,
321 m_toString(to
), m_fromString(from
), m_kind(kind
),
322 m_name(wxString::FromAscii(name
))
328 virtual ~wxTypeInfo()
333 // return the kind of this type (wxT_... constants)
334 wxTypeKind
GetKind() const { return m_kind
; }
336 // returns the unique name of this type
337 const wxString
& GetTypeName() const { return m_name
; }
339 // is this type a delegate type
340 bool IsDelegateType() const { return m_kind
== wxT_DELEGATE
; }
342 // is this type a custom type
343 bool IsCustomType() const { return m_kind
== wxT_CUSTOM
; }
345 // is this type an object type
346 bool IsObjectType() const { return m_kind
== wxT_OBJECT
|| m_kind
== wxT_OBJECT_PTR
; }
348 // can the content of this type be converted to and from strings ?
349 bool HasStringConverters() const { return m_toString
!= NULL
&& m_fromString
!= NULL
; }
351 // convert a wxVariantBase holding data of this type into a string
352 void ConvertToString( const wxVariantBase
& data
, wxString
&result
) const
355 (*m_toString
)( data
, result
);
357 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
360 // convert a string into a wxVariantBase holding the corresponding data in this type
361 void ConvertFromString( const wxString
& data
, wxVariantBase
&result
) const
364 (*m_fromString
)( data
, result
);
366 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
372 static wxTypeInfo
*FindType(const char *typeName
)
373 { return FindType( wxString::FromAscii(typeName
) ); }
375 static wxTypeInfo
*FindType(const wxChar
*typeName
);
376 static wxTypeInfo
*FindType(const wxString
& typeName
)
379 return FindType( typeName
.wchar_str() );
381 return FindType( typeName
.char_str() );
389 wxVariant2StringFnc m_toString
;
390 wxString2VariantFnc m_fromString
;
395 // the static list of all types we know about
396 static wxTypeInfoMap
* ms_typeTable
;
399 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo
: public wxTypeInfo
402 wxBuiltInTypeInfo( wxTypeKind kind
, wxVariant2StringFnc to
= NULL
,
403 wxString2VariantFnc from
= NULL
,
404 const wxString
&name
= wxEmptyString
) :
405 wxTypeInfo( kind
, to
, from
, name
)
406 { wxASSERT_MSG( GetKind() < wxT_SET
, wxT("Illegal Kind for Base Type") ); }
409 wxBuiltInTypeInfo( wxTypeKind kind
, wxVariant2StringFnc to
,
410 wxString2VariantFnc from
, const char *name
) :
411 wxTypeInfo( kind
, to
, from
, name
)
412 { wxASSERT_MSG( GetKind() < wxT_SET
, wxT("Illegal Kind for Base Type") ); }
416 class WXDLLIMPEXP_BASE wxCustomTypeInfo
: public wxTypeInfo
419 wxCustomTypeInfo( const wxString
&name
, wxVariant2StringFnc to
,
420 wxString2VariantFnc from
) :
421 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
425 wxCustomTypeInfo( const char *name
, wxVariant2StringFnc to
,
426 wxString2VariantFnc from
) :
427 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
432 class WXDLLIMPEXP_BASE wxEnumTypeInfo
: public wxTypeInfo
435 typedef void (*converterToLong_t
)( const wxVariantBase
& data
, long &result
);
436 typedef void (*converterFromLong_t
)( long data
, wxVariantBase
&result
);
438 wxEnumTypeInfo( wxTypeKind kind
, wxEnumData
* enumInfo
, wxVariant2StringFnc to
,
439 wxString2VariantFnc from
, converterToLong_t toLong
,
440 converterFromLong_t fromLong
, const wxString
&name
) :
441 wxTypeInfo( kind
, to
, from
, name
), m_toLong( toLong
), m_fromLong( fromLong
)
443 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
444 wxT("Illegal Kind for Enum Type"));
445 m_enumInfo
= enumInfo
;
449 wxEnumTypeInfo( wxTypeKind kind
, wxEnumData
* enumInfo
, wxVariant2StringFnc to
,
450 wxString2VariantFnc from
, converterToLong_t toLong
,
451 converterFromLong_t fromLong
, const char * name
) :
452 wxTypeInfo( kind
, to
, from
, name
), m_toLong( toLong
), m_fromLong( fromLong
)
454 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
455 wxT("Illegal Kind for Enum Type"));
456 m_enumInfo
= enumInfo
;
459 const wxEnumData
* GetEnumData() const { return m_enumInfo
; }
461 // convert a wxVariantBase holding data of this type into a long
462 void ConvertToLong( const wxVariantBase
& data
, long &result
) const
465 (*m_toLong
)( data
, result
);
467 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
470 // convert a long into a wxVariantBase holding the corresponding data in this type
471 void ConvertFromLong( long data
, wxVariantBase
&result
) const
474 (*m_fromLong
)( data
, result
);
476 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
480 converterToLong_t m_toLong
;
481 converterFromLong_t m_fromLong
;
483 wxEnumData
*m_enumInfo
; // Kind == wxT_ENUM or Kind == wxT_SET
486 class WXDLLIMPEXP_BASE wxClassTypeInfo
: public wxTypeInfo
489 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
,
490 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
491 const wxString
&name
= wxEmptyString
);
494 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
, wxVariant2StringFnc to
,
495 wxString2VariantFnc from
, const char *name
);
498 const wxClassInfo
*GetClassInfo() const { return m_classInfo
; }
501 wxClassInfo
*m_classInfo
; // Kind == wxT_OBJECT - could be NULL
504 class WXDLLIMPEXP_BASE wxCollectionTypeInfo
: public wxTypeInfo
507 wxCollectionTypeInfo( const wxString
&elementName
, wxVariant2StringFnc to
,
508 wxString2VariantFnc from
, const wxString
&name
) :
509 wxTypeInfo( wxT_COLLECTION
, to
, from
, name
)
510 { m_elementTypeName
= elementName
; m_elementType
= NULL
; }
513 wxCollectionTypeInfo( const char *elementName
, wxVariant2StringFnc to
,
514 wxString2VariantFnc from
, const char *name
) :
515 wxTypeInfo( wxT_COLLECTION
, to
, from
, name
)
516 { m_elementTypeName
= wxString::FromAscii( elementName
); m_elementType
= NULL
; }
519 const wxTypeInfo
* GetElementType() const
521 if ( m_elementType
== NULL
)
522 m_elementType
= wxTypeInfo::FindType( m_elementTypeName
);
523 return m_elementType
;
527 mutable wxTypeInfo
* m_elementType
;
528 wxString m_elementTypeName
;
531 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo
: public wxTypeInfo
534 wxEventSourceTypeInfo( int eventType
, wxClassInfo
* eventClass
,
535 wxVariant2StringFnc to
= NULL
,
536 wxString2VariantFnc from
= NULL
);
537 wxEventSourceTypeInfo( int eventType
, int lastEventType
, wxClassInfo
* eventClass
,
538 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
);
540 int GetEventType() const { return m_eventType
; }
541 int GetLastEventType() const { return m_lastEventType
; }
542 const wxClassInfo
* GetEventClass() const { return m_eventClass
; }
545 const wxClassInfo
*m_eventClass
; // (extended will merge into classinfo)
550 template<typename T
> const wxTypeInfo
* wxGetTypeInfo( T
* ) \
551 { return wxTypeInfo::FindType(typeid(T
).name()); }
553 // this macro is for usage with custom, non-object derived classes and structs,
554 // wxPoint is such a custom type
556 #if wxUSE_FUNC_TEMPLATE_POINTER
557 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
558 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
560 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
561 void ToString##e( const wxVariantBase& data, wxString &result ) \
562 { toString(data, result); } \
563 void FromString##e( const wxString& data, wxVariantBase &result ) \
564 { fromString(data, result); } \
565 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
566 &ToString##e, &FromString##e);
569 #define wxCOLLECTION_TYPE_INFO( element, collection ) \
570 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
571 NULL, NULL, typeid(collection).name() );
573 // sometimes a compiler invents specializations that are nowhere called,
574 // use this macro to satisfy the refs, currently we don't have to play
575 // tricks, but if we will have to according to the compiler, we will use
576 // that macro for that
578 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
580 #endif // wxUSE_EXTENDED_RTTI
581 #endif // _XTITYPES_H_