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/xtistrm.h"
30 #include "wx/txtstrm.h"
33 #if wxUSE_EXTENDED_RTTI
35 #include "wx/beforestd.h"
39 #include "wx/afterstd.h"
43 struct wxWriter::wxWriterInternal
45 map
< const wxObject
* , int > m_writtenObjects
;
51 m_data
= new wxWriterInternal
;
52 m_data
->m_nextId
= 0 ;
60 struct wxWriter::wxWriterInternalPropertiesData
65 void wxWriter::ClearObjectContext()
68 m_data
= new wxWriterInternal() ;
69 m_data
->m_nextId
= 0 ;
72 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, const wxString
&name
, wxxVariantArray
&metadata
)
74 DoBeginWriteTopLevelEntry( name
) ;
75 WriteObject( object
, classInfo
, persister
, false , metadata
) ;
76 DoEndWriteTopLevelEntry( name
) ;
79 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, bool isEmbedded
, wxxVariantArray
&metadata
)
81 if ( !classInfo
->BeforeWriteObject( object
, this , persister
, metadata
) )
84 if ( persister
->BeforeWriteObject( this , object
, classInfo
, metadata
) )
88 else if ( IsObjectKnown( object
) )
89 DoWriteRepeatedObject( GetObjectID(object
) ) ;
92 int oid
= m_data
->m_nextId
++ ;
94 m_data
->m_writtenObjects
[object
] = oid
;
96 // in case this object is a wxDynamicObject we also have to insert is superclass
97 // instance with the same id, so that object relations are streamed out correctly
98 const wxDynamicObject
* dynobj
= dynamic_cast<const wxDynamicObject
*>( object
) ;
99 if ( !isEmbedded
&& dynobj
)
100 m_data
->m_writtenObjects
[dynobj
->GetSuperClassInstance()] = oid
;
102 DoBeginWriteObject( object
, classInfo
, oid
, metadata
) ;
103 wxWriterInternalPropertiesData data
;
104 WriteAllProperties( object
, classInfo
, persister
, &data
) ;
105 DoEndWriteObject( object
, classInfo
, oid
) ;
107 persister
->AfterWriteObject( this ,object
, classInfo
) ;
111 void wxWriter::FindConnectEntry(const wxEvtHandler
* evSource
,const wxDelegateTypeInfo
* dti
, const wxObject
* &sink
, const wxHandlerInfo
*&handler
)
113 wxList
*dynamicEvents
= evSource
->GetDynamicEventTable() ;
117 wxList::compatibility_iterator node
= dynamicEvents
->GetFirst();
120 wxDynamicEventTableEntry
*entry
= (wxDynamicEventTableEntry
*)node
->GetData();
124 (dti
->GetEventType() == entry
->m_eventType
) &&
125 (entry
->m_id
== -1 ) &&
126 (entry
->m_eventSink
!= NULL
) )
128 sink
= entry
->m_eventSink
;
129 const wxClassInfo
* sinkClassInfo
= sink
->GetClassInfo() ;
130 const wxHandlerInfo
* sinkHandler
= sinkClassInfo
->GetFirstHandler() ;
131 while ( sinkHandler
)
133 if ( sinkHandler
->GetEventFunction() == entry
->m_fn
)
135 handler
= sinkHandler
;
138 sinkHandler
= sinkHandler
->GetNext() ;
142 node
= node
->GetNext();
146 void wxWriter::WriteAllProperties( const wxObject
* obj
, const wxClassInfo
* ci
, wxPersister
*persister
, wxWriterInternalPropertiesData
* data
)
148 wxPropertyInfoMap map
;
149 ci
->GetProperties( map
) ;
150 for ( int i
= 0 ; i
< ci
->GetCreateParamCount() ; ++i
)
152 wxString name
= ci
->GetCreateParamName(i
) ;
153 const wxPropertyInfo
* prop
= map
.find(name
)->second
;
154 wxASSERT_MSG( prop
, wxT("Create Parameter not found in declared RTTI Parameters") ) ;
155 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
159 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
161 const wxPropertyInfo
* prop
= iter
->second
;
162 if ( prop
->GetFlags() & wxPROP_OBJECT_GRAPH
)
164 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
168 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
170 const wxPropertyInfo
* prop
= iter
->second
;
171 if ( !(prop
->GetFlags() & wxPROP_OBJECT_GRAPH
) )
173 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
178 void wxWriter::WriteOneProperty( const wxObject
*obj
, const wxClassInfo
* ci
, const wxPropertyInfo
* pi
, wxPersister
*persister
, wxWriterInternalPropertiesData
*WXUNUSED(data
) )
180 if ( pi
->GetFlags() & wxPROP_DONT_STREAM
)
183 // make sure that we are picking the correct object for accessing the property
184 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (obj
) ;
185 if ( dynobj
&& (dynamic_cast<const wxDynamicClassInfo
*>(ci
) == NULL
) )
186 obj
= dynobj
->GetSuperClassInstance() ;
188 DoBeginWriteProperty( pi
) ;
189 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
191 wxxVariantArray data
;
192 pi
->GetAccessor()->GetPropertyCollection(obj
, data
) ;
193 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
194 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
196 DoBeginWriteElement() ;
197 wxxVariant value
= data
[i
] ;
198 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
200 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
203 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
204 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
206 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
210 DoWriteSimpleType( value
) ;
213 DoEndWriteElement() ;
218 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
221 const wxObject
* sink
= NULL
;
222 const wxHandlerInfo
*handler
= NULL
;
224 const wxEvtHandler
* evSource
= dynamic_cast<const wxEvtHandler
*>(obj
) ;
225 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-wxEvtHandler) as Event Source") ) ;
227 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
228 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
230 if ( sink
!= NULL
&& handler
!= NULL
)
232 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
233 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
240 pi
->GetAccessor()->GetProperty(obj
, value
) ;
241 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
243 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
246 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
247 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
249 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
253 if ( pi
->GetFlags() & wxPROP_ENUM_STORE_LONG
)
255 const wxEnumTypeInfo
*eti
= dynamic_cast<const wxEnumTypeInfo
*>( pi
->GetTypeInfo() ) ;
256 wxASSERT_MSG( eti
, wxT("Type must have enum - long conversion") ) ;
257 eti
->ConvertFromLong( value
.Get
<long>() , value
) ;
259 DoWriteSimpleType( value
) ;
264 DoEndWriteProperty( pi
) ;
267 int wxWriter::GetObjectID(const wxObject
*obj
)
269 if ( !IsObjectKnown( obj
) )
270 return wxInvalidObjectID
;
272 return m_data
->m_writtenObjects
[obj
] ;
275 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
277 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
281 // ----------------------------------------------------------------------------
282 // reading objects in
283 // ----------------------------------------------------------------------------
285 struct wxReader::wxReaderInternal
287 map
<int,wxClassInfo
*> m_classInfos
;
292 m_data
= new wxReaderInternal
;
295 wxReader::~wxReader()
300 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
302 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
303 return m_data
->m_classInfos
[objectID
] ;
306 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
308 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
309 m_data
->m_classInfos
[objectID
] = classInfo
;
312 bool wxReader::HasObjectClassInfo( int objectID
)
314 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
318 // ----------------------------------------------------------------------------
320 // ----------------------------------------------------------------------------
323 Reading components has not to be extended for components
324 as properties are always sought by typeinfo over all levels
325 and create params are always toplevel class only
329 // ----------------------------------------------------------------------------
330 // depersisting to memory
331 // ----------------------------------------------------------------------------
333 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
335 map
<int,wxObject
*> m_objects
;
337 void SetObject(int objectID
, wxObject
*obj
)
339 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
340 m_objects
[objectID
] = obj
;
342 wxObject
* GetObject( int objectID
)
344 if ( objectID
== wxNullObjectID
)
347 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
348 return m_objects
[objectID
] ;
352 wxRuntimeDepersister::wxRuntimeDepersister()
354 m_data
= new wxRuntimeDepersisterInternal() ;
357 wxRuntimeDepersister::~wxRuntimeDepersister()
362 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
363 wxxVariantArray
&WXUNUSED(metadata
))
366 O
= classInfo
->CreateObject();
367 m_data
->SetObject(objectID
, O
);
370 void wxRuntimeDepersister::CreateObject(int objectID
,
371 const wxClassInfo
*classInfo
,
375 const wxClassInfo
**objectClassInfos
,
376 wxxVariantArray
&WXUNUSED(metadata
))
379 o
= m_data
->GetObject(objectID
);
380 for ( int i
= 0 ; i
< paramCount
; ++i
)
382 if ( objectIdValues
[i
] != wxInvalidObjectID
)
385 o
= m_data
->GetObject(objectIdValues
[i
]);
386 // if this is a dynamic object and we are asked for another class
387 // than wxDynamicObject we cast it down manually.
388 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
389 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
391 o
= dyno
->GetSuperClassInstance() ;
393 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
396 classInfo
->Create(o
, paramCount
, params
);
399 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
402 o
= m_data
->GetObject(objectID
);
406 void wxRuntimeDepersister::SetProperty(int objectID
,
407 const wxClassInfo
*classInfo
,
408 const wxPropertyInfo
* propertyInfo
,
409 const wxxVariant
&value
)
412 o
= m_data
->GetObject(objectID
);
413 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
416 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
417 const wxClassInfo
*classInfo
,
418 const wxPropertyInfo
* propertyInfo
,
422 o
= m_data
->GetObject(objectID
);
423 valo
= m_data
->GetObject(valueObjectId
);
424 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
425 // if this is a dynamic object and we are asked for another class
426 // than wxDynamicObject we cast it down manually.
427 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
428 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
430 valo
= dynvalo
->GetSuperClassInstance() ;
433 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
436 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
437 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
438 const wxDelegateTypeInfo
*delegateInfo
,
439 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
440 const wxHandlerInfo
* handlerInfo
,
441 int eventSinkObjectID
)
443 wxEvtHandler
*ehsource
= dynamic_cast< wxEvtHandler
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
444 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
446 if ( ehsource
&& ehsink
)
448 ehsource
->Connect( -1 , delegateInfo
->GetEventType() ,
449 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
454 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
456 return m_data
->GetObject( objectID
) ;
459 // adds an element to a property collection
460 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
461 const wxClassInfo
*classInfo
,
462 const wxPropertyInfo
* propertyInfo
,
463 const wxxVariant
&value
)
466 o
= m_data
->GetObject(objectID
);
467 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
470 // sets the corresponding property (value is an object)
471 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
472 const wxClassInfo
*classInfo
,
473 const wxPropertyInfo
* propertyInfo
,
477 o
= m_data
->GetObject(objectID
);
478 valo
= m_data
->GetObject(valueObjectId
);
479 const wxCollectionTypeInfo
* collectionTypeInfo
= dynamic_cast< const wxCollectionTypeInfo
* >(propertyInfo
->GetTypeInfo() ) ;
480 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(collectionTypeInfo
->GetElementType()))->GetClassInfo() ;
481 // if this is a dynamic object and we are asked for another class
482 // than wxDynamicObject we cast it down manually.
483 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
484 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
486 valo
= dynvalo
->GetSuperClassInstance() ;
489 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
492 // ----------------------------------------------------------------------------
493 // depersisting to code
494 // ----------------------------------------------------------------------------
496 struct wxCodeDepersister::wxCodeDepersisterInternal
498 map
<int,string
> m_objectNames
;
500 void SetObjectName(int objectID
, const wxString
&name
)
502 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
503 m_objectNames
[objectID
] = (const char *)name
;
505 wxString
GetObjectName( int objectID
)
507 if ( objectID
== wxNullObjectID
)
510 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
511 return wxString( m_objectNames
[objectID
].c_str() ) ;
515 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
518 m_data
= new wxCodeDepersisterInternal
;
521 wxCodeDepersister::~wxCodeDepersister()
526 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
527 wxxVariantArray
&WXUNUSED(metadata
))
529 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
530 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
531 classInfo
->GetClassName(),
533 classInfo
->GetClassName()) );
534 m_data
->SetObjectName( objectID
, objectName
) ;
537 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
539 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
540 m_data
->GetObjectName( objectID
).c_str() ) );
543 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
546 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
547 if ( type
->GetKind() == wxT_CUSTOM
)
549 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
550 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
551 value
.Printf( "%s(%s)",cti
->GetTypeName().c_str(),param
.GetAsString().c_str() );
553 else if ( type
->GetKind() == wxT_STRING
)
555 value
.Printf( "\"%s\"",param
.GetAsString().c_str() );
559 value
.Printf( "%s", param
.GetAsString().c_str() );
564 void wxCodeDepersister::CreateObject(int objectID
,
565 const wxClassInfo
*WXUNUSED(classInfo
),
569 const wxClassInfo
**WXUNUSED(objectClassInfos
) ,
570 wxxVariantArray
&WXUNUSED(metadata
)
574 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
).c_str() ) );
575 for (i
= 0; i
< paramCount
; i
++)
577 if ( objectIDValues
[i
] != wxInvalidObjectID
)
578 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ).c_str() ) );
581 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]).c_str() ) );
583 if (i
< paramCount
- 1)
584 m_fp
->WriteString( ", ");
586 m_fp
->WriteString( ");\n");
589 void wxCodeDepersister::SetProperty(int objectID
,
590 const wxClassInfo
*WXUNUSED(classInfo
),
591 const wxPropertyInfo
* propertyInfo
,
592 const wxxVariant
&value
)
594 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
595 m_data
->GetObjectName(objectID
).c_str(),
596 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
597 ValueAsCode(value
).c_str()) );
600 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
601 const wxClassInfo
*WXUNUSED(classInfo
),
602 const wxPropertyInfo
* propertyInfo
,
605 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
606 m_fp
->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
607 m_data
->GetObjectName(objectID
).c_str(),
608 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
609 m_data
->GetObjectName( valueObjectId
).c_str() ) );
611 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
612 m_data
->GetObjectName(objectID
).c_str(),
613 propertyInfo
->GetAccessor()->GetSetterName().c_str(),
614 m_data
->GetObjectName( valueObjectId
).c_str() ) );
617 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
618 const wxClassInfo
*WXUNUSED(classInfo
),
619 const wxPropertyInfo
* propertyInfo
,
620 const wxxVariant
&value
)
622 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
623 m_data
->GetObjectName(objectID
).c_str(),
624 propertyInfo
->GetAccessor()->GetAdderName().c_str(),
625 ValueAsCode(value
).c_str()) );
628 // sets the corresponding property (value is an object)
629 void wxCodeDepersister::AddToPropertyCollectionAsObject(int WXUNUSED(objectID
),
630 const wxClassInfo
*WXUNUSED(classInfo
),
631 const wxPropertyInfo
* WXUNUSED(propertyInfo
) ,
632 int WXUNUSED(valueObjectId
))
637 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
638 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
639 const wxDelegateTypeInfo
*delegateInfo
,
640 const wxClassInfo
*eventSinkClassInfo
,
641 const wxHandlerInfo
* handlerInfo
,
642 int eventSinkObjectID
)
644 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
645 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
646 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
647 int eventType
= delegateInfo
->GetEventType() ;
648 wxString handlerName
= handlerInfo
->GetName() ;
650 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
651 ehsource
.c_str() , ehsource
.c_str() , eventType
, ehsinkClass
.c_str() , handlerName
.c_str() , ehsink
.c_str() ) );
654 #include <wx/arrimpl.cpp>
656 WX_DEFINE_OBJARRAY(wxxVariantArray
);