git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5718 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
327 lines
7.2 KiB
C++
327 lines
7.2 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: objstrm.cpp
|
|
// Purpose: wxObjectStream classes
|
|
// Author: Guilhem Lavaux
|
|
// Modified by:
|
|
// Created: 16/07/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 1998 Guilhem Lavaux
|
|
// Licence: wxWindows license
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "objstrm.h"
|
|
#endif
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_SERIAL && wxUSE_STREAMS
|
|
|
|
#include "wx/object.h"
|
|
#include "wx/objstrm.h"
|
|
#include "wx/datstrm.h"
|
|
|
|
#define WXOBJ_BEGIN "OBEGIN"
|
|
#define WXOBJ_BEG_LEN 6
|
|
|
|
#define TAG_EMPTY_OBJECT "NULL"
|
|
#define TAG_DUPLICATE_OBJECT "DUPLIC"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxObjectOutputStream
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s)
|
|
: wxFilterOutputStream(s)
|
|
{
|
|
m_saving = FALSE;
|
|
}
|
|
|
|
wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
|
|
{
|
|
wxString name;
|
|
|
|
name.Printf(wxT("%x"), (unsigned long)obj);
|
|
return name;
|
|
}
|
|
|
|
void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info)
|
|
{
|
|
wxDataOutputStream data_s(*this);
|
|
|
|
Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN);
|
|
|
|
if (info.duplicate) {
|
|
data_s.WriteString(TAG_DUPLICATE_OBJECT);
|
|
data_s.WriteString(GetObjectName(info.object));
|
|
wxPrintf(wxT("info.object (dup %s)\n"), info.object->GetClassInfo()->GetClassName());
|
|
return;
|
|
}
|
|
|
|
if (info.object) {
|
|
data_s.WriteString(info.object->GetClassInfo()->GetClassName());
|
|
wxPrintf(wxT("info.object (%s)\n"), info.object->GetClassInfo()->GetClassName());
|
|
} else {
|
|
data_s.WriteString(TAG_EMPTY_OBJECT);
|
|
wxPrintf(wxT("info.object (NULL)\n"));
|
|
return;
|
|
}
|
|
|
|
data_s.WriteString(GetObjectName(info.object));
|
|
|
|
// I assume an object will not have millions of children
|
|
// Hmmm ... it could have (for example wxGrid)
|
|
data_s.Write32(info.children.Number());
|
|
}
|
|
|
|
void wxObjectOutputStream::AddChild(wxObject *obj)
|
|
{
|
|
wxObjectStreamInfo *info;
|
|
|
|
if (!FirstStage())
|
|
return;
|
|
|
|
info = new wxObjectStreamInfo;
|
|
|
|
if (m_saved_objs.Member(obj) != NULL) {
|
|
info->duplicate = TRUE;
|
|
} else {
|
|
info->duplicate = FALSE;
|
|
m_saved_objs.Append(obj);
|
|
}
|
|
if (!obj)
|
|
info->duplicate = FALSE;
|
|
|
|
info->n_children = 0;
|
|
info->object = obj;
|
|
info->parent = m_current_info; // Not useful here.
|
|
m_current_info->n_children++;
|
|
m_current_info->children.Append(info);
|
|
}
|
|
|
|
void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info)
|
|
{
|
|
wxNode *node;
|
|
|
|
m_current_info = info;
|
|
// First stage: get children of obj
|
|
if (info->object && !info->duplicate)
|
|
info->object->StoreObject(*this);
|
|
|
|
// Prepare and write the sub-entry about the child obj.
|
|
WriteObjectDef(*info);
|
|
|
|
node = info->children.First();
|
|
|
|
while (node) {
|
|
ProcessObjectDef((wxObjectStreamInfo *)node->Data());
|
|
node = node->Next();
|
|
}
|
|
}
|
|
|
|
void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info)
|
|
{
|
|
wxNode *node = info->children.First();
|
|
|
|
m_current_info = info;
|
|
|
|
if (info->object && !info->duplicate)
|
|
info->object->StoreObject(*this);
|
|
|
|
while (node) {
|
|
ProcessObjectData((wxObjectStreamInfo *)node->Data());
|
|
node = node->Next();
|
|
}
|
|
}
|
|
|
|
bool wxObjectOutputStream::SaveObject(wxObject& obj)
|
|
{
|
|
wxObjectStreamInfo info;
|
|
|
|
if (m_saving)
|
|
return FALSE;
|
|
|
|
m_saving = TRUE;
|
|
|
|
// First stage
|
|
m_stage = 0;
|
|
info.object = &obj;
|
|
info.n_children = 0;
|
|
info.duplicate = FALSE;
|
|
ProcessObjectDef(&info);
|
|
|
|
m_stage = 1;
|
|
ProcessObjectData(&info);
|
|
|
|
info.children.Clear();
|
|
m_saved_objs.Clear();
|
|
|
|
m_saving = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxObjectInputStream
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
|
|
: wxFilterInputStream(s)
|
|
{
|
|
m_secondcall = FALSE;
|
|
}
|
|
|
|
wxObject *wxObjectInputStream::SolveName(const wxString& name) const
|
|
{
|
|
wxNode *node = m_solver.First();
|
|
wxObjectStreamInfo *info;
|
|
|
|
while (node) {
|
|
info = (wxObjectStreamInfo *)node->Data();
|
|
if (info->object_name == name)
|
|
return info->object;
|
|
|
|
node = node->Next();
|
|
}
|
|
return (wxObject *) NULL;
|
|
}
|
|
|
|
wxObject *wxObjectInputStream::GetParent() const
|
|
{
|
|
if (!m_current_info->parent)
|
|
return (wxObject *) NULL;
|
|
|
|
return m_current_info->parent->object;
|
|
}
|
|
|
|
wxObject *wxObjectInputStream::GetChild()
|
|
{
|
|
wxObject *obj = GetChild(0);
|
|
|
|
m_current_info->children_removed++;
|
|
|
|
return obj;
|
|
}
|
|
|
|
wxObject *wxObjectInputStream::GetChild(int no) const
|
|
{
|
|
wxNode *node;
|
|
wxObjectStreamInfo *info;
|
|
|
|
if (m_current_info->children_removed >= m_current_info->n_children)
|
|
return (wxObject *) NULL;
|
|
|
|
node = m_current_info->children.Nth(m_current_info->children_removed+no);
|
|
|
|
if (!node)
|
|
return (wxObject *) NULL;
|
|
|
|
info = (wxObjectStreamInfo *)node->Data();
|
|
|
|
return info->object;
|
|
}
|
|
|
|
void wxObjectInputStream::RemoveChildren(int nb)
|
|
{
|
|
m_current_info->children_removed += nb;
|
|
}
|
|
|
|
bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
|
|
{
|
|
wxDataInputStream data_s(*this);
|
|
char sig[WXOBJ_BEG_LEN+1];
|
|
wxString class_name;
|
|
|
|
Read(sig, WXOBJ_BEG_LEN);
|
|
sig[WXOBJ_BEG_LEN] = 0;
|
|
if (wxString(sig) != WXOBJ_BEGIN)
|
|
return FALSE;
|
|
|
|
class_name = data_s.ReadString();
|
|
info->children_removed = 0;
|
|
info->n_children = 0;
|
|
|
|
if (class_name == TAG_EMPTY_OBJECT)
|
|
info->object = (wxObject *) NULL;
|
|
else if (class_name == TAG_DUPLICATE_OBJECT) {
|
|
info->object_name = data_s.ReadString();
|
|
info->object = SolveName(info->object_name);
|
|
} else {
|
|
info->object_name = data_s.ReadString();
|
|
info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
|
|
info->n_children = data_s.Read32();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *parent)
|
|
{
|
|
wxObjectStreamInfo *info, *c_info;
|
|
int c;
|
|
|
|
info = new wxObjectStreamInfo;
|
|
info->parent = parent;
|
|
info->children.DeleteContents(TRUE);
|
|
|
|
m_solver.Append(info);
|
|
|
|
if (!ReadObjectDef(info))
|
|
return (wxObjectStreamInfo *) NULL;
|
|
|
|
for (c=0;c<info->n_children;c++) {
|
|
c_info = ProcessObjectDef(info);
|
|
if (!c_info)
|
|
return (wxObjectStreamInfo *) NULL;
|
|
info->children.Append(c_info);
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info)
|
|
{
|
|
wxNode *node = info->children.First();
|
|
|
|
m_current_info = info;
|
|
|
|
if (info->object)
|
|
info->object->LoadObject(*this);
|
|
while (node) {
|
|
ProcessObjectData((wxObjectStreamInfo *)node->Data());
|
|
node = node->Next();
|
|
}
|
|
|
|
m_current_info = info;
|
|
|
|
if (info->recall) {
|
|
m_secondcall = TRUE;
|
|
info->object->LoadObject(*this);
|
|
m_secondcall = FALSE;
|
|
}
|
|
}
|
|
|
|
wxObject *wxObjectInputStream::LoadObject()
|
|
{
|
|
wxObjectStreamInfo *info;
|
|
wxObject *object;
|
|
|
|
info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
|
|
if (!info)
|
|
return (wxObject *) NULL;
|
|
ProcessObjectData(info);
|
|
|
|
object = info->object;
|
|
|
|
delete info; // It's magic ! The whole tree is destroyed.
|
|
|
|
return object;
|
|
}
|
|
|
|
#endif // wxUSE_SERIAL && wxUSE_STREAMS
|
|
|