]>
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"
26 #if wxUSE_SERIAL && wxUSE_STREAMS
28 #include "wx/object.h"
29 #include "wx/objstrm.h"
30 #include "wx/datstrm.h"
32 #define WXOBJ_BEGIN "OBEGIN"
33 #define WXOBJ_BEG_LEN 6
35 #define TAG_EMPTY_OBJECT "NULL"
36 #define TAG_DUPLICATE_OBJECT "DUPLIC"
38 // ----------------------------------------------------------------------------
39 // wxObjectOutputStream
40 // ----------------------------------------------------------------------------
42 wxObjectOutputStream::wxObjectOutputStream(wxOutputStream
& s
)
43 : wxFilterOutputStream(s
)
48 wxString
wxObjectOutputStream::GetObjectName(wxObject
*obj
)
52 name
.Printf(_T("%x"), (unsigned long)obj
);
56 void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo
& info
)
58 wxDataOutputStream
data_s(*this);
60 Write(WXOBJ_BEGIN
, WXOBJ_BEG_LEN
);
63 data_s
.WriteString(TAG_DUPLICATE_OBJECT
);
64 data_s
.WriteString(GetObjectName(info
.object
));
65 wxPrintf(_T("info.object (dup %s)\n"), info
.object
->GetClassInfo()->GetClassName());
70 data_s
.WriteString(info
.object
->GetClassInfo()->GetClassName());
71 wxPrintf(_T("info.object (%s)\n"), info
.object
->GetClassInfo()->GetClassName());
73 data_s
.WriteString(TAG_EMPTY_OBJECT
);
74 wxPrintf(_T("info.object (NULL)\n"));
78 data_s
.WriteString(GetObjectName(info
.object
));
80 // I assume an object will not have millions of children
81 // Hmmm ... it could have (for example wxGrid)
82 data_s
.Write32(info
.children
.Number());
85 void wxObjectOutputStream::AddChild(wxObject
*obj
)
87 wxObjectStreamInfo
*info
;
92 info
= new wxObjectStreamInfo
;
94 if (m_saved_objs
.Member(obj
) != NULL
) {
95 info
->duplicate
= TRUE
;
97 info
->duplicate
= FALSE
;
98 m_saved_objs
.Append(obj
);
101 info
->duplicate
= FALSE
;
103 info
->n_children
= 0;
105 info
->parent
= m_current_info
; // Not useful here.
106 m_current_info
->n_children
++;
107 m_current_info
->children
.Append(info
);
110 void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo
*info
)
114 m_current_info
= info
;
115 // First stage: get children of obj
116 if (info
->object
&& !info
->duplicate
)
117 info
->object
->StoreObject(*this);
119 // Prepare and write the sub-entry about the child obj.
120 WriteObjectDef(*info
);
122 node
= info
->children
.First();
125 ProcessObjectDef((wxObjectStreamInfo
*)node
->Data());
130 void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo
*info
)
132 wxNode
*node
= info
->children
.First();
134 m_current_info
= info
;
136 if (info
->object
&& !info
->duplicate
)
137 info
->object
->StoreObject(*this);
140 ProcessObjectData((wxObjectStreamInfo
*)node
->Data());
145 bool wxObjectOutputStream::SaveObject(wxObject
& obj
)
147 wxObjectStreamInfo info
;
158 info
.duplicate
= FALSE
;
159 ProcessObjectDef(&info
);
162 ProcessObjectData(&info
);
164 info
.children
.Clear();
165 m_saved_objs
.Clear();
172 // ----------------------------------------------------------------------------
173 // wxObjectInputStream
174 // ----------------------------------------------------------------------------
176 wxObjectInputStream::wxObjectInputStream(wxInputStream
& s
)
177 : wxFilterInputStream(s
)
179 m_secondcall
= FALSE
;
182 wxObject
*wxObjectInputStream::SolveName(const wxString
& name
) const
184 wxNode
*node
= m_solver
.First();
185 wxObjectStreamInfo
*info
;
188 info
= (wxObjectStreamInfo
*)node
->Data();
189 if (info
->object_name
== name
)
194 return (wxObject
*) NULL
;
197 wxObject
*wxObjectInputStream::GetParent() const
199 if (!m_current_info
->parent
)
200 return (wxObject
*) NULL
;
202 return m_current_info
->parent
->object
;
205 wxObject
*wxObjectInputStream::GetChild()
207 wxObject
*obj
= GetChild(0);
209 m_current_info
->children_removed
++;
214 wxObject
*wxObjectInputStream::GetChild(int no
) const
217 wxObjectStreamInfo
*info
;
219 if (m_current_info
->children_removed
>= m_current_info
->n_children
)
220 return (wxObject
*) NULL
;
222 node
= m_current_info
->children
.Nth(m_current_info
->children_removed
+no
);
225 return (wxObject
*) NULL
;
227 info
= (wxObjectStreamInfo
*)node
->Data();
232 void wxObjectInputStream::RemoveChildren(int nb
)
234 m_current_info
->children_removed
+= nb
;
237 bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo
*info
)
239 wxDataInputStream
data_s(*this);
240 char sig
[WXOBJ_BEG_LEN
+1];
243 Read(sig
, WXOBJ_BEG_LEN
);
244 sig
[WXOBJ_BEG_LEN
] = 0;
245 if (wxString(sig
) != WXOBJ_BEGIN
)
248 class_name
= data_s
.ReadString();
249 info
->children_removed
= 0;
250 info
->n_children
= 0;
252 if (class_name
== TAG_EMPTY_OBJECT
)
253 info
->object
= (wxObject
*) NULL
;
254 else if (class_name
== TAG_DUPLICATE_OBJECT
) {
255 info
->object_name
= data_s
.ReadString();
256 info
->object
= SolveName(info
->object_name
);
258 info
->object_name
= data_s
.ReadString();
259 info
->object
= wxCreateDynamicObject( WXSTRINGCAST class_name
);
260 info
->n_children
= data_s
.Read32();
265 wxObjectStreamInfo
*wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo
*parent
)
267 wxObjectStreamInfo
*info
, *c_info
;
270 info
= new wxObjectStreamInfo
;
271 info
->parent
= parent
;
272 info
->children
.DeleteContents(TRUE
);
274 m_solver
.Append(info
);
276 if (!ReadObjectDef(info
))
277 return (wxObjectStreamInfo
*) NULL
;
279 for (c
=0;c
<info
->n_children
;c
++) {
280 c_info
= ProcessObjectDef(info
);
282 return (wxObjectStreamInfo
*) NULL
;
283 info
->children
.Append(c_info
);
289 void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo
*info
)
291 wxNode
*node
= info
->children
.First();
293 m_current_info
= info
;
296 info
->object
->LoadObject(*this);
298 ProcessObjectData((wxObjectStreamInfo
*)node
->Data());
302 m_current_info
= info
;
306 info
->object
->LoadObject(*this);
307 m_secondcall
= FALSE
;
311 wxObject
*wxObjectInputStream::LoadObject()
313 wxObjectStreamInfo
*info
;
316 info
= ProcessObjectDef((wxObjectStreamInfo
*) NULL
);
318 return (wxObject
*) NULL
;
319 ProcessObjectData(info
);
321 object
= info
->object
;
323 delete info
; // It's magic ! The whole tree is destroyed.