xti expansions, streaming code changes
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@22711 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -166,159 +166,18 @@ template<> const wxTypeInfo* wxGetTypeInfo( wxString * )
|
||||
|
||||
// this are compiler induced specialization which are never used anywhere
|
||||
|
||||
// char const *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( char const ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , const char* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , char const * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// char *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( char ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , char* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , char * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// unsigned char *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( unsigned char ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , unsigned char* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , unsigned char * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// int *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( int ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , int* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , int * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// bool *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( bool ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , bool* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , bool * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// long *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( long ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , long* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , long * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
// wxString *
|
||||
|
||||
template<> const wxTypeInfo* wxGetTypeInfo( wxString ** )
|
||||
{
|
||||
assert(0) ;
|
||||
static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
|
||||
return &s_typeInfo ;
|
||||
}
|
||||
|
||||
template<> void wxStringReadValue(const wxString & , wxString* & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
template<> void wxStringWriteValue(wxString & , wxString * const & )
|
||||
{
|
||||
assert(0) ;
|
||||
}
|
||||
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
|
||||
WX_ILLEGAL_TYPE_SPECIALIZATION( wxString * )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// value streaming
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// convenience function (avoids including xml headers in users code)
|
||||
|
||||
void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
|
||||
{
|
||||
node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
|
||||
}
|
||||
|
||||
wxString wxXmlGetContentFromNode( wxXmlNode *node )
|
||||
{
|
||||
if ( node->GetChildren() )
|
||||
return node->GetChildren()->GetContent() ;
|
||||
else
|
||||
return wxEmptyString ;
|
||||
}
|
||||
|
||||
// streamer specializations
|
||||
// for all built-in types
|
||||
|
||||
|
@@ -21,8 +21,8 @@
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/hash.h"
|
||||
#include "wx/object.h"
|
||||
#include "wx/hash.h"
|
||||
#include "wx/object.h"
|
||||
#endif
|
||||
|
||||
#include "wx/xml/xml.h"
|
||||
@@ -37,41 +37,102 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// streaming xml out
|
||||
// ----------------------------------------------------------------------------
|
||||
struct wxWriter::wxWriterInternal
|
||||
{
|
||||
map< const wxObject* , int > m_writtenObjects ;
|
||||
int m_nextId ;
|
||||
} ;
|
||||
|
||||
void WriteComponent(wxObject *Object, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString& nodeName , int &nextId, bool embeddedObject, map< wxObject* , int > &writtenObjects ) ;
|
||||
wxWriter::wxWriter()
|
||||
{
|
||||
m_data = new wxWriterInternal ;
|
||||
m_data->m_nextId = 0 ;
|
||||
}
|
||||
|
||||
void WriteComponentProperties( wxObject* obj , const wxClassInfo* ci , wxXmlNode *onode , int &nextId, map< wxObject* , int > &writtenObjects, map< string , int > &writtenProperties)
|
||||
wxWriter::~wxWriter()
|
||||
{
|
||||
delete m_data ;
|
||||
}
|
||||
|
||||
struct wxWriter::wxWriterInternalPropertiesData
|
||||
{
|
||||
map< string , int > m_writtenProperties ;
|
||||
} ;
|
||||
|
||||
void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name )
|
||||
{
|
||||
if ( persister->BeforeWriteObject( object , classInfo , name ) )
|
||||
{
|
||||
int oid = m_data->m_nextId++ ;
|
||||
m_data->m_writtenObjects[object] = oid ;
|
||||
DoBeginWriteObject( object , classInfo , oid , name ) ;
|
||||
wxWriterInternalPropertiesData data ;
|
||||
WriteAllProperties( object , classInfo , persister , &data ) ;
|
||||
DoEndWriteObject( object , classInfo , oid , name ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
|
||||
{
|
||||
const wxPropertyInfo *pi = ci->GetFirstProperty() ;
|
||||
while( pi )
|
||||
{
|
||||
if ( writtenProperties.find( pi->GetName() ) == writtenProperties.end() )
|
||||
if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() )
|
||||
{
|
||||
writtenProperties[ pi->GetName() ] = 1 ;
|
||||
data->m_writtenProperties[ pi->GetName() ] = 1 ;
|
||||
const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
|
||||
if ( cti )
|
||||
{
|
||||
const wxClassInfo* pci = cti->GetClassInfo() ;
|
||||
wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
|
||||
WriteComponent( pci->VariantToInstance( value ) , pci , onode , pi->GetName() , nextId ,
|
||||
( cti->GetKind() == wxT_OBJECT ) , writtenObjects ) ;
|
||||
if ( persister->BeforeWritePropertyAsObject( obj , ci , pi , value ) )
|
||||
{
|
||||
wxObject *vobj = pci->VariantToInstance( value ) ;
|
||||
bool embeddedObject = cti->GetKind() == wxT_OBJECT ;
|
||||
|
||||
if ( vobj == NULL || IsObjectKnown( vobj ) )
|
||||
{
|
||||
DoWriteObjectReference( obj , ci , vobj , pci , GetObjectID(vobj) , pi ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
int oid = m_data->m_nextId++ ;
|
||||
if ( !embeddedObject)
|
||||
m_data->m_writtenObjects[vobj] = oid ;
|
||||
|
||||
DoBeginWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ;
|
||||
if ( vobj != NULL )
|
||||
{
|
||||
wxWriterInternalPropertiesData data ;
|
||||
WriteAllProperties( vobj , pci , persister , &data ) ;
|
||||
}
|
||||
DoEndWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
|
||||
if ( dti )
|
||||
{
|
||||
// in which form should we stream out these ?
|
||||
const wxObject* sink = NULL ;
|
||||
const wxHandlerInfo *handler = NULL ;
|
||||
if ( persister->BeforeWriteDelegate( obj , ci , pi , sink , handler ) )
|
||||
{
|
||||
if ( sink != NULL && handler != NULL )
|
||||
{
|
||||
wxASSERT_MSG( IsObjectKnown( sink ) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
|
||||
DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxXmlNode *pnode;
|
||||
pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
|
||||
pi->GetAccessor()->WriteValue(pnode, obj ) ;
|
||||
onode->AddChild(pnode);
|
||||
wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
|
||||
if ( persister->BeforeWriteProperty( obj , ci , pi , value ) )
|
||||
{
|
||||
DoWriteProperty( obj , ci , pi , value ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,54 +141,143 @@ void WriteComponentProperties( wxObject* obj , const wxClassInfo* ci , wxXmlNode
|
||||
const wxClassInfo** parents = ci->GetParents() ;
|
||||
for ( int i = 0 ; parents[i] ; ++ i )
|
||||
{
|
||||
WriteComponentProperties( obj , parents[i] , onode , nextId , writtenObjects , writtenProperties ) ;
|
||||
WriteAllProperties( obj , parents[i] , persister , data ) ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Writing Components does have to take inheritance into account, that's why we are iterating
|
||||
over our parents as well
|
||||
*/
|
||||
|
||||
void WriteComponent(wxObject *obj, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString &nodeName)
|
||||
int wxWriter::GetObjectID(const wxObject *obj)
|
||||
{
|
||||
int nextid = 0 ; // 0 is the root element
|
||||
map< wxObject* , int > writtenobjects ;
|
||||
WriteComponent( obj , classInfo, parent, nodeName , nextid , false , writtenobjects ) ;
|
||||
if ( !IsObjectKnown( obj ) )
|
||||
return wxInvalidObjectID ;
|
||||
|
||||
return m_data->m_writtenObjects[obj] ;
|
||||
}
|
||||
|
||||
void WriteComponent(wxObject *obj, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString& nodeName , int &nextId, bool embeddedObject, map< wxObject* , int > &writtenObjects )
|
||||
bool wxWriter::IsObjectKnown( const wxObject *obj )
|
||||
{
|
||||
return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ;
|
||||
}
|
||||
|
||||
//
|
||||
// XML Streaming
|
||||
//
|
||||
|
||||
// convenience functions
|
||||
|
||||
void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
|
||||
{
|
||||
node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
|
||||
}
|
||||
|
||||
wxString wxXmlGetContentFromNode( wxXmlNode *node )
|
||||
{
|
||||
if ( node->GetChildren() )
|
||||
return node->GetChildren()->GetContent() ;
|
||||
else
|
||||
return wxEmptyString ;
|
||||
}
|
||||
|
||||
struct wxXmlWriter::wxXmlWriterInternal
|
||||
{
|
||||
wxXmlNode *m_root ;
|
||||
wxXmlNode *m_current ;
|
||||
vector< wxXmlNode * > m_objectStack ;
|
||||
} ;
|
||||
|
||||
wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode )
|
||||
{
|
||||
m_data = new wxXmlWriterInternal() ;
|
||||
m_data->m_root = rootnode ;
|
||||
m_data->m_current = rootnode ;
|
||||
}
|
||||
|
||||
wxXmlWriter::~wxXmlWriter()
|
||||
{
|
||||
delete m_data ;
|
||||
}
|
||||
|
||||
// start of writing the root object
|
||||
void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID , const wxString &name )
|
||||
{
|
||||
map< string , int > writtenProperties ;
|
||||
wxXmlNode *onode;
|
||||
|
||||
onode = new wxXmlNode(wxXML_ELEMENT_NODE, nodeName);
|
||||
|
||||
onode = new wxXmlNode(wxXML_ELEMENT_NODE, name);
|
||||
onode->AddProperty(wxString("class"), wxString(classInfo->GetClassName()));
|
||||
if ( obj == NULL )
|
||||
onode->AddProperty(wxString("id"), wxString::Format( "%d" , objectID ) );
|
||||
|
||||
m_data->m_current->AddChild(onode) ;
|
||||
m_data->m_objectStack.push_back( m_data->m_current ) ;
|
||||
m_data->m_current = onode ;
|
||||
}
|
||||
|
||||
// end of writing the root object
|
||||
void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) , const wxString &WXUNUSED(name) )
|
||||
{
|
||||
m_data->m_current = m_data->m_objectStack.back() ;
|
||||
m_data->m_objectStack.pop_back() ;
|
||||
}
|
||||
|
||||
// writes a property in the stream format
|
||||
void wxXmlWriter::DoWriteProperty( const wxObject *WXUNUSED(obj), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi , wxxVariant &value )
|
||||
{
|
||||
wxXmlNode *pnode;
|
||||
pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
|
||||
wxXmlAddContentToNode( pnode ,value.GetAsString() ) ;
|
||||
m_data->m_current->AddChild(pnode);
|
||||
}
|
||||
|
||||
void wxXmlWriter::DoBeginWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
|
||||
const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
|
||||
{
|
||||
wxXmlNode *onode;
|
||||
onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
|
||||
onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
|
||||
onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
|
||||
m_data->m_current->AddChild(onode) ;
|
||||
m_data->m_objectStack.push_back( m_data->m_current ) ;
|
||||
m_data->m_current = onode ;
|
||||
}
|
||||
|
||||
// insert an object reference to an already written object
|
||||
void wxXmlWriter::DoWriteObjectReference(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *valueObject,
|
||||
const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
|
||||
{
|
||||
wxXmlNode *onode;
|
||||
onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
|
||||
onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
|
||||
if ( valueObject == NULL )
|
||||
{
|
||||
wxXmlNode* nullnode = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, "null");
|
||||
onode->AddChild(nullnode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have already written this object, just insert an id
|
||||
// embedded objects have to be written out fully always, their address will be reused and is not a valid key
|
||||
if ( !embeddedObject && (writtenObjects.find( obj ) != writtenObjects.end()) )
|
||||
{
|
||||
onode->AddProperty(wxString("id"), wxString::Format( "%d" , writtenObjects[obj] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int id = nextId++ ;
|
||||
if ( !embeddedObject )
|
||||
writtenObjects[obj] = id ;
|
||||
onode->AddProperty(wxString("id"), wxString::Format( "%d" , id ) );
|
||||
WriteComponentProperties( obj , classInfo , onode , nextId , writtenObjects, writtenProperties) ;
|
||||
}
|
||||
onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
|
||||
}
|
||||
|
||||
parent->AddChild(onode);
|
||||
m_data->m_current->AddChild(onode) ;
|
||||
}
|
||||
|
||||
void wxXmlWriter::DoEndWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
|
||||
const wxClassInfo *WXUNUSED(valueObjectClassInfo), int WXUNUSED(valueObjectID) , const wxPropertyInfo *WXUNUSED(propInfo) )
|
||||
{
|
||||
m_data->m_current = m_data->m_objectStack.back() ;
|
||||
m_data->m_objectStack.pop_back() ;
|
||||
}
|
||||
|
||||
|
||||
// writes a delegate in the stream format
|
||||
void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi ,
|
||||
const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo )
|
||||
{
|
||||
if ( eventSink != NULL && handlerInfo != NULL )
|
||||
{
|
||||
wxXmlNode *pnode;
|
||||
pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
|
||||
wxString s ;
|
||||
s.Printf(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName() ) ;
|
||||
wxXmlAddContentToNode( pnode ,s ) ;
|
||||
m_data->m_current->AddChild(pnode);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -172,9 +322,9 @@ bool wxReader::HasObjectClassInfo( int objectID )
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Reading components has not to be extended for components
|
||||
as properties are always sought by typeinfo over all levels
|
||||
and create params are always toplevel class only
|
||||
Reading components has not to be extended for components
|
||||
as properties are always sought by typeinfo over all levels
|
||||
and create params are always toplevel class only
|
||||
*/
|
||||
|
||||
int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
|
||||
@@ -337,7 +487,7 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
|
||||
wxxVariant wxXmlReader::ReadValue(wxXmlNode *node,
|
||||
wxPropertyAccessor *accessor )
|
||||
{
|
||||
return accessor->ReadValue(node) ;
|
||||
return accessor->ReadValue(wxXmlGetContentFromNode( node ) ) ;
|
||||
}
|
||||
|
||||
int wxXmlReader::ReadObject(wxDepersister *callbacks)
|
||||
@@ -483,7 +633,7 @@ struct wxCodeDepersister::wxCodeDepersisterInternal
|
||||
} ;
|
||||
|
||||
wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
|
||||
: m_fp(out)
|
||||
: m_fp(out)
|
||||
{
|
||||
m_data = new wxCodeDepersisterInternal ;
|
||||
}
|
||||
|
Reference in New Issue
Block a user