1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/xtistrm.cpp
3 // Purpose: streaming runtime metadata information
4 // Author: Stefan Csomor
8 // Copyright: (c) 2003 Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "xtistrm.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/object.h"
28 #include "wx/tokenzr.h"
29 #include "wx/txtstrm.h"
32 #if wxUSE_EXTENDED_RTTI
34 #include "wx/xtistrm.h"
36 #include "wx/beforestd.h"
40 #include "wx/afterstd.h"
44 struct wxWriter::wxWriterInternal
46 map
< const wxObject
* , int > m_writtenObjects
;
52 m_data
= new wxWriterInternal
;
53 m_data
->m_nextId
= 0 ;
61 struct wxWriter::wxWriterInternalPropertiesData
66 void wxWriter::ClearObjectContext()
69 m_data
= new wxWriterInternal() ;
70 m_data
->m_nextId
= 0 ;
73 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, const wxString
&name
, wxxVariantArray
&metadata
)
75 DoBeginWriteTopLevelEntry( name
) ;
76 WriteObject( object
, classInfo
, persister
, false , metadata
) ;
77 DoEndWriteTopLevelEntry( name
) ;
80 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, bool isEmbedded
, wxxVariantArray
&metadata
)
82 if ( !classInfo
->BeforeWriteObject( object
, this , persister
, metadata
) )
85 if ( persister
->BeforeWriteObject( this , object
, classInfo
, metadata
) )
89 else if ( IsObjectKnown( object
) )
90 DoWriteRepeatedObject( GetObjectID(object
) ) ;
93 int oid
= m_data
->m_nextId
++ ;
95 m_data
->m_writtenObjects
[object
] = oid
;
97 // in case this object is a wxDynamicObject we also have to insert is superclass
98 // instance with the same id, so that object relations are streamed out correctly
99 const wxDynamicObject
* dynobj
= dynamic_cast<const wxDynamicObject
*>( object
) ;
100 if ( !isEmbedded
&& dynobj
)
101 m_data
->m_writtenObjects
[dynobj
->GetSuperClassInstance()] = oid
;
103 DoBeginWriteObject( object
, classInfo
, oid
, metadata
) ;
104 wxWriterInternalPropertiesData data
;
105 WriteAllProperties( object
, classInfo
, persister
, &data
) ;
106 DoEndWriteObject( object
, classInfo
, oid
) ;
108 persister
->AfterWriteObject( this ,object
, classInfo
) ;
112 void wxWriter::FindConnectEntry(const wxEvtHandler
* evSource
,const wxDelegateTypeInfo
* dti
, const wxObject
* &sink
, const wxHandlerInfo
*&handler
)
114 wxList
*dynamicEvents
= evSource
->GetDynamicEventTable() ;
118 wxList::compatibility_iterator node
= dynamicEvents
->GetFirst();
121 wxDynamicEventTableEntry
*entry
= (wxDynamicEventTableEntry
*)node
->GetData();
125 (dti
->GetEventType() == entry
->m_eventType
) &&
126 (entry
->m_id
== -1 ) &&
127 (entry
->m_eventSink
!= NULL
) )
129 sink
= entry
->m_eventSink
;
130 const wxClassInfo
* sinkClassInfo
= sink
->GetClassInfo() ;
131 const wxHandlerInfo
* sinkHandler
= sinkClassInfo
->GetFirstHandler() ;
132 while ( sinkHandler
)
134 if ( sinkHandler
->GetEventFunction() == entry
->m_fn
)
136 handler
= sinkHandler
;
139 sinkHandler
= sinkHandler
->GetNext() ;
143 node
= node
->GetNext();
147 void wxWriter::WriteAllProperties( const wxObject
* obj
, const wxClassInfo
* ci
, wxPersister
*persister
, wxWriterInternalPropertiesData
* data
)
149 wxPropertyInfoMap map
;
150 ci
->GetProperties( map
) ;
151 for ( int i
= 0 ; i
< ci
->GetCreateParamCount() ; ++i
)
153 wxString name
= ci
->GetCreateParamName(i
) ;
154 const wxPropertyInfo
* prop
= map
.find(name
)->second
;
155 wxASSERT_MSG( prop
, wxT("Create Parameter not found in declared RTTI Parameters") ) ;
156 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
160 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
162 const wxPropertyInfo
* prop
= iter
->second
;
163 if ( prop
->GetFlags() & wxPROP_OBJECT_GRAPH
)
165 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
169 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
171 const wxPropertyInfo
* prop
= iter
->second
;
172 if ( !(prop
->GetFlags() & wxPROP_OBJECT_GRAPH
) )
174 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
179 void wxWriter::WriteOneProperty( const wxObject
*obj
, const wxClassInfo
* ci
, const wxPropertyInfo
* pi
, wxPersister
*persister
, wxWriterInternalPropertiesData
*WXUNUSED(data
) )
181 if ( pi
->GetFlags() & wxPROP_DONT_STREAM
)
184 // make sure that we are picking the correct object for accessing the property
185 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (obj
) ;
186 if ( dynobj
&& (dynamic_cast<const wxDynamicClassInfo
*>(ci
) == NULL
) )
187 obj
= dynobj
->GetSuperClassInstance() ;
189 DoBeginWriteProperty( pi
) ;
190 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
192 wxxVariantArray data
;
193 pi
->GetAccessor()->GetPropertyCollection(obj
, data
) ;
194 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
195 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
197 DoBeginWriteElement() ;
198 wxxVariant value
= data
[i
] ;
199 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
201 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
204 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
205 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
207 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
211 DoWriteSimpleType( value
) ;
214 DoEndWriteElement() ;
219 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
222 const wxObject
* sink
= NULL
;
223 const wxHandlerInfo
*handler
= NULL
;
225 const wxEvtHandler
* evSource
= dynamic_cast<const wxEvtHandler
*>(obj
) ;
226 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-wxEvtHandler) as Event Source") ) ;
228 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
229 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
231 if ( sink
!= NULL
&& handler
!= NULL
)
233 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
234 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
241 pi
->GetAccessor()->GetProperty(obj
, value
) ;
242 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
244 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
247 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
248 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
250 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
254 if ( pi
->GetFlags() & wxPROP_ENUM_STORE_LONG
)
256 const wxEnumTypeInfo
*eti
= dynamic_cast<const wxEnumTypeInfo
*>( pi
->GetTypeInfo() ) ;
257 wxASSERT_MSG( eti
, wxT("Type must have enum - long conversion") ) ;
258 eti
->ConvertFromLong( value
.Get
<long>() , value
) ;
260 DoWriteSimpleType( value
) ;
265 DoEndWriteProperty( pi
) ;
268 int wxWriter::GetObjectID(const wxObject
*obj
)
270 if ( !IsObjectKnown( obj
) )
271 return wxInvalidObjectID
;
273 return m_data
->m_writtenObjects
[obj
] ;
276 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
278 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
282 // ----------------------------------------------------------------------------
283 // reading objects in
284 // ----------------------------------------------------------------------------
286 struct wxReader::wxReaderInternal
288 map
<int,wxClassInfo
*> m_classInfos
;
293 m_data
= new wxReaderInternal
;
296 wxReader::~wxReader()
301 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
303 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
304 return m_data
->m_classInfos
[objectID
] ;
307 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
309 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
310 m_data
->m_classInfos
[objectID
] = classInfo
;
313 bool wxReader::HasObjectClassInfo( int objectID
)
315 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
319 // ----------------------------------------------------------------------------
321 // ----------------------------------------------------------------------------
324 Reading components has not to be extended for components
325 as properties are always sought by typeinfo over all levels
326 and create params are always toplevel class only
330 // ----------------------------------------------------------------------------
331 // depersisting to memory
332 // ----------------------------------------------------------------------------
334 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
336 map
<int,wxObject
*> m_objects
;
338 void SetObject(int objectID
, wxObject
*obj
)
340 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
341 m_objects
[objectID
] = obj
;
343 wxObject
* GetObject( int objectID
)
345 if ( objectID
== wxNullObjectID
)
348 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
349 return m_objects
[objectID
] ;
353 wxRuntimeDepersister::wxRuntimeDepersister()
355 m_data
= new wxRuntimeDepersisterInternal() ;
358 wxRuntimeDepersister::~wxRuntimeDepersister()
363 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
364 wxxVariantArray
&WXUNUSED(metadata
))
367 O
= classInfo
->CreateObject();
368 m_data
->SetObject(objectID
, O
);
371 void wxRuntimeDepersister::CreateObject(int objectID
,
372 const wxClassInfo
*classInfo
,
376 const wxClassInfo
**objectClassInfos
,
377 wxxVariantArray
&WXUNUSED(metadata
))
380 o
= m_data
->GetObject(objectID
);
381 for ( int i
= 0 ; i
< paramCount
; ++i
)
383 if ( objectIdValues
[i
] != wxInvalidObjectID
)
386 o
= m_data
->GetObject(objectIdValues
[i
]);
387 // if this is a dynamic object and we are asked for another class
388 // than wxDynamicObject we cast it down manually.
389 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
390 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
392 o
= dyno
->GetSuperClassInstance() ;
394 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
397 classInfo
->Create(o
, paramCount
, params
);
400 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
403 o
= m_data
->GetObject(objectID
);
407 void wxRuntimeDepersister::SetProperty(int objectID
,
408 const wxClassInfo
*classInfo
,
409 const wxPropertyInfo
* propertyInfo
,
410 const wxxVariant
&value
)
413 o
= m_data
->GetObject(objectID
);
414 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
417 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
418 const wxClassInfo
*classInfo
,
419 const wxPropertyInfo
* propertyInfo
,
423 o
= m_data
->GetObject(objectID
);
424 valo
= m_data
->GetObject(valueObjectId
);
425 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
426 // if this is a dynamic object and we are asked for another class
427 // than wxDynamicObject we cast it down manually.
428 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
429 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
431 valo
= dynvalo
->GetSuperClassInstance() ;
434 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
437 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
438 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
439 const wxDelegateTypeInfo
*delegateInfo
,
440 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
441 const wxHandlerInfo
* handlerInfo
,
442 int eventSinkObjectID
)
444 wxEvtHandler
*ehsource
= dynamic_cast< wxEvtHandler
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
445 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
447 if ( ehsource
&& ehsink
)
449 ehsource
->Connect( -1 , delegateInfo
->GetEventType() ,
450 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
455 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
457 return m_data
->GetObject( objectID
) ;
460 // adds an element to a property collection
461 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
462 const wxClassInfo
*classInfo
,
463 const wxPropertyInfo
* propertyInfo
,
464 const wxxVariant
&value
)
467 o
= m_data
->GetObject(objectID
);
468 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
471 // sets the corresponding property (value is an object)
472 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
473 const wxClassInfo
*classInfo
,
474 const wxPropertyInfo
* propertyInfo
,
478 o
= m_data
->GetObject(objectID
);
479 valo
= m_data
->GetObject(valueObjectId
);
480 const wxCollectionTypeInfo
* collectionTypeInfo
= dynamic_cast< const wxCollectionTypeInfo
* >(propertyInfo
->GetTypeInfo() ) ;
481 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(collectionTypeInfo
->GetElementType()))->GetClassInfo() ;
482 // if this is a dynamic object and we are asked for another class
483 // than wxDynamicObject we cast it down manually.
484 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
485 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
487 valo
= dynvalo
->GetSuperClassInstance() ;
490 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
493 // ----------------------------------------------------------------------------
494 // depersisting to code
495 // ----------------------------------------------------------------------------
497 struct wxCodeDepersister::wxCodeDepersisterInternal
499 map
<int,string
> m_objectNames
;
501 void SetObjectName(int objectID
, const wxString
&name
)
503 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
504 m_objectNames
[objectID
] = (const char *)name
;
506 wxString
GetObjectName( int objectID
)
508 if ( objectID
== wxNullObjectID
)
511 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
512 return wxString( m_objectNames
[objectID
].c_str() ) ;
516 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
519 m_data
= new wxCodeDepersisterInternal
;
522 wxCodeDepersister::~wxCodeDepersister()
527 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
528 wxxVariantArray
&WXUNUSED(metadata
))
530 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
531 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
532 classInfo
->GetClassName(),
534 classInfo
->GetClassName()) );
535 m_data
->SetObjectName( objectID
, objectName
) ;
538 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
540 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
541 m_data
->GetObjectName( objectID
).c_str() ) );
544 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
547 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
548 if ( type
->GetKind() == wxT_CUSTOM
)
550 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
551 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
552 value
.Printf( "%s(%s)",cti
->GetTypeName().c_str(),param
.GetAsString().c_str() );
554 else if ( type
->GetKind() == wxT_STRING
)
556 value
.Printf( "\"%s\"",param
.GetAsString().c_str() );
560 value
.Printf( "%s", param
.GetAsString().c_str() );
565 void wxCodeDepersister::CreateObject(int objectID
,
566 const wxClassInfo
*WXUNUSED(classInfo
),
570 const wxClassInfo
**WXUNUSED(objectClassInfos
) ,
571 wxxVariantArray
&WXUNUSED(metadata
)
575 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
).c_str() ) );
576 for (i
= 0; i
< paramCount
; i
++)
578 if ( objectIDValues
[i
] != wxInvalidObjectID
)
579 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ).c_str() ) );
582 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]).c_str() ) );
584 if (i
< paramCount
- 1)
585 m_fp
->WriteString( ", ");
587 m_fp
->WriteString( ");\n");
590 void wxCodeDepersister::SetProperty(int objectID
,
591 const wxClassInfo
*WXUNUSED(classInfo
),
592 const wxPropertyInfo
* propertyInfo
,
593 const wxxVariant
&value
)
595 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
596 m_data
->GetObjectName(objectID
).c_str(),
597 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
598 ValueAsCode(value
).c_str()) );
601 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
602 const wxClassInfo
*WXUNUSED(classInfo
),
603 const wxPropertyInfo
* propertyInfo
,
606 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
607 m_fp
->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
608 m_data
->GetObjectName(objectID
).c_str(),
609 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
610 m_data
->GetObjectName( valueObjectId
).c_str() ) );
612 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
613 m_data
->GetObjectName(objectID
).c_str(),
614 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
615 m_data
->GetObjectName( valueObjectId
).c_str() ) );
618 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
619 const wxClassInfo
*WXUNUSED(classInfo
),
620 const wxPropertyInfo
* propertyInfo
,
621 const wxxVariant
&value
)
623 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
624 m_data
->GetObjectName(objectID
).c_str(),
625 propertyInfo
->GetAccessor()->GetAdderName().c_str(),
626 ValueAsCode(value
).c_str()) );
629 // sets the corresponding property (value is an object)
630 void wxCodeDepersister::AddToPropertyCollectionAsObject(int WXUNUSED(objectID
),
631 const wxClassInfo
*WXUNUSED(classInfo
),
632 const wxPropertyInfo
* WXUNUSED(propertyInfo
) ,
633 int WXUNUSED(valueObjectId
))
638 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
639 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
640 const wxDelegateTypeInfo
*delegateInfo
,
641 const wxClassInfo
*eventSinkClassInfo
,
642 const wxHandlerInfo
* handlerInfo
,
643 int eventSinkObjectID
)
645 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
646 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
647 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
648 int eventType
= delegateInfo
->GetEventType() ;
649 wxString handlerName
= handlerInfo
->GetName() ;
651 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
652 ehsource
.c_str() , ehsource
.c_str() , eventType
, ehsinkClass
.c_str() , handlerName
.c_str() , ehsink
.c_str() ) );
655 #include <wx/arrimpl.cpp>
657 WX_DEFINE_OBJARRAY(wxxVariantArray
);