]>
git.saurik.com Git - wxWidgets.git/blob - src/common/objstrm.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxObjectStream classes
4 // Author: Guilhem Lavaux
8 // Copyright: (c) 1998 Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "objstrm.h"
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
22 #if wxUSE_SERIAL && wxUSE_STREAMS
24 #include "wx/object.h"
25 #include "wx/objstrm.h"
26 #include "wx/datstrm.h"
28 #define WXOBJ_BEGIN "OBEGIN"
29 #define WXOBJ_BEG_LEN 6
31 #define TAG_EMPTY_OBJECT "NULL"
32 #define TAG_DUPLICATE_OBJECT "DUPLIC"
34 // ----------------------------------------------------------------------------
35 // wxObjectOutputStream
36 // ----------------------------------------------------------------------------
38 wxObjectOutputStream::wxObjectOutputStream(wxOutputStream
& s
)
39 : wxFilterOutputStream(s
)
44 wxString
wxObjectOutputStream::GetObjectName(wxObject
*obj
)
48 name
.Printf(_T("%x"), (unsigned long)obj
);
52 void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo
& info
)
54 wxDataOutputStream
data_s(*this);
56 Write(WXOBJ_BEGIN
, WXOBJ_BEG_LEN
);
59 data_s
.WriteString(TAG_DUPLICATE_OBJECT
);
60 data_s
.WriteString(GetObjectName(info
.object
));
61 wxPrintf(_T("info.object (dup %s)\n"), info
.object
->GetClassInfo()->GetClassName());
66 data_s
.WriteString(info
.object
->GetClassInfo()->GetClassName());
67 wxPrintf(_T("info.object (%s)\n"), info
.object
->GetClassInfo()->GetClassName());
69 data_s
.WriteString(TAG_EMPTY_OBJECT
);
70 wxPrintf(_T("info.object (NULL)\n"));
74 data_s
.WriteString(GetObjectName(info
.object
));
76 // I assume an object will not have millions of children
77 // Hmmm ... it could have (for example wxGrid)
78 data_s
.Write32(info
.children
.Number());
81 void wxObjectOutputStream::AddChild(wxObject
*obj
)
83 wxObjectStreamInfo
*info
;
88 info
= new wxObjectStreamInfo
;
90 if (m_saved_objs
.Member(obj
) != NULL
) {
91 info
->duplicate
= TRUE
;
93 info
->duplicate
= FALSE
;
94 m_saved_objs
.Append(obj
);
97 info
->duplicate
= FALSE
;
101 info
->parent
= m_current_info
; // Not useful here.
102 m_current_info
->n_children
++;
103 m_current_info
->children
.Append(info
);
106 void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo
*info
)
110 m_current_info
= info
;
111 // First stage: get children of obj
112 if (info
->object
&& !info
->duplicate
)
113 info
->object
->StoreObject(*this);
115 // Prepare and write the sub-entry about the child obj.
116 WriteObjectDef(*info
);
118 node
= info
->children
.First();
121 ProcessObjectDef((wxObjectStreamInfo
*)node
->Data());
126 void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo
*info
)
128 wxNode
*node
= info
->children
.First();
130 m_current_info
= info
;
132 if (info
->object
&& !info
->duplicate
)
133 info
->object
->StoreObject(*this);
136 ProcessObjectData((wxObjectStreamInfo
*)node
->Data());
141 bool wxObjectOutputStream::SaveObject(wxObject
& obj
)
143 wxObjectStreamInfo info
;
154 info
.duplicate
= FALSE
;
155 ProcessObjectDef(&info
);
158 ProcessObjectData(&info
);
160 info
.children
.Clear();
161 m_saved_objs
.Clear();
168 // ----------------------------------------------------------------------------
169 // wxObjectInputStream
170 // ----------------------------------------------------------------------------
172 wxObjectInputStream::wxObjectInputStream(wxInputStream
& s
)
173 : wxFilterInputStream(s
)
175 m_secondcall
= FALSE
;
178 wxObject
*wxObjectInputStream::SolveName(const wxString
& name
) const
180 wxNode
*node
= m_solver
.First();
181 wxObjectStreamInfo
*info
;
184 info
= (wxObjectStreamInfo
*)node
->Data();
185 if (info
->object_name
== name
)
190 return (wxObject
*) NULL
;
193 wxObject
*wxObjectInputStream::GetParent() const
195 if (!m_current_info
->parent
)
196 return (wxObject
*) NULL
;
198 return m_current_info
->parent
->object
;
201 wxObject
*wxObjectInputStream::GetChild()
203 wxObject
*obj
= GetChild(0);
205 m_current_info
->children_removed
++;
210 wxObject
*wxObjectInputStream::GetChild(int no
) const
213 wxObjectStreamInfo
*info
;
215 if (m_current_info
->children_removed
>= m_current_info
->n_children
)
216 return (wxObject
*) NULL
;
218 node
= m_current_info
->children
.Nth(m_current_info
->children_removed
+no
);
221 return (wxObject
*) NULL
;
223 info
= (wxObjectStreamInfo
*)node
->Data();
228 void wxObjectInputStream::RemoveChildren(int nb
)
230 m_current_info
->children_removed
+= nb
;
233 bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo
*info
)
235 wxDataInputStream
data_s(*this);
236 char sig
[WXOBJ_BEG_LEN
+1];
239 Read(sig
, WXOBJ_BEG_LEN
);
240 sig
[WXOBJ_BEG_LEN
] = 0;
241 if (wxString(sig
) != WXOBJ_BEGIN
)
244 class_name
= data_s
.ReadString();
245 info
->children_removed
= 0;
246 info
->n_children
= 0;
248 if (class_name
== TAG_EMPTY_OBJECT
)
249 info
->object
= (wxObject
*) NULL
;
250 else if (class_name
== TAG_DUPLICATE_OBJECT
) {
251 info
->object_name
= data_s
.ReadString();
252 info
->object
= SolveName(info
->object_name
);
254 info
->object_name
= data_s
.ReadString();
255 info
->object
= wxCreateDynamicObject( WXSTRINGCAST class_name
);
256 info
->n_children
= data_s
.Read32();
261 wxObjectStreamInfo
*wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo
*parent
)
263 wxObjectStreamInfo
*info
, *c_info
;
266 info
= new wxObjectStreamInfo
;
267 info
->parent
= parent
;
268 info
->children
.DeleteContents(TRUE
);
270 m_solver
.Append(info
);
272 if (!ReadObjectDef(info
))
273 return (wxObjectStreamInfo
*) NULL
;
275 for (c
=0;c
<info
->n_children
;c
++) {
276 c_info
= ProcessObjectDef(info
);
278 return (wxObjectStreamInfo
*) NULL
;
279 info
->children
.Append(c_info
);
285 void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo
*info
)
287 wxNode
*node
= info
->children
.First();
289 m_current_info
= info
;
292 info
->object
->LoadObject(*this);
294 ProcessObjectData((wxObjectStreamInfo
*)node
->Data());
298 m_current_info
= info
;
302 info
->object
->LoadObject(*this);
303 m_secondcall
= FALSE
;
307 wxObject
*wxObjectInputStream::LoadObject()
309 wxObjectStreamInfo
*info
;
312 info
= ProcessObjectDef((wxObjectStreamInfo
*) NULL
);
314 return (wxObject
*) NULL
;
315 ProcessObjectData(info
);
317 object
= info
->object
;
319 delete info
; // It's magic ! The whole tree is destroyed.