]> git.saurik.com Git - wxWidgets.git/blame - src/common/objstrm.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / objstrm.cpp
CommitLineData
6d44bf31
GL
1/////////////////////////////////////////////////////////////////////////////
2// Name: objstrm.cpp
3// Purpose: wxObjectStream classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 16/07/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Guilhem Lavaux
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
6dc6fda6 11
6d44bf31 12#ifdef __GNUG__
6dc6fda6 13 #pragma implementation "objstrm.h"
6d44bf31
GL
14#endif
15
fcc6dddd
JS
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
ce4169a4 20 #pragma hdrstop
fcc6dddd
JS
21#endif
22
ce4169a4 23#if wxUSE_SERIAL && wxUSE_STREAMS
fcc6dddd 24
6d44bf31
GL
25#include "wx/object.h"
26#include "wx/objstrm.h"
27#include "wx/datstrm.h"
28
29#define WXOBJ_BEGIN "OBEGIN"
30#define WXOBJ_BEG_LEN 6
31
7a4b9130 32#define TAG_EMPTY_OBJECT "NULL"
8d43638d 33#define TAG_DUPLICATE_OBJECT "DUPLIC"
7a4b9130 34
6d44bf31
GL
35// ----------------------------------------------------------------------------
36// wxObjectOutputStream
37// ----------------------------------------------------------------------------
38
39wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s)
40 : wxFilterOutputStream(s)
41{
42 m_saving = FALSE;
43}
44
45wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
46{
47 wxString name;
48
223d09f6 49 name.Printf(wxT("%x"), (unsigned long)obj);
6d44bf31
GL
50 return name;
51}
52
53void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info)
54{
55 wxDataOutputStream data_s(*this);
56
57 Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN);
7a4b9130 58
8d43638d
GL
59 if (info.duplicate) {
60 data_s.WriteString(TAG_DUPLICATE_OBJECT);
61 data_s.WriteString(GetObjectName(info.object));
223d09f6 62 wxPrintf(wxT("info.object (dup %s)\n"), info.object->GetClassInfo()->GetClassName());
8d43638d
GL
63 return;
64 }
65
7a4b9130
GL
66 if (info.object) {
67 data_s.WriteString(info.object->GetClassInfo()->GetClassName());
223d09f6 68 wxPrintf(wxT("info.object (%s)\n"), info.object->GetClassInfo()->GetClassName());
7a4b9130
GL
69 } else {
70 data_s.WriteString(TAG_EMPTY_OBJECT);
223d09f6 71 wxPrintf(wxT("info.object (NULL)\n"));
1d44aaf8 72 return;
7a4b9130
GL
73 }
74
6d44bf31 75 data_s.WriteString(GetObjectName(info.object));
7a4b9130 76
6d44bf31 77 // I assume an object will not have millions of children
8d43638d
GL
78 // Hmmm ... it could have (for example wxGrid)
79 data_s.Write32(info.children.Number());
6d44bf31
GL
80}
81
1eac776c 82void wxObjectOutputStream::AddChild(wxObject *obj)
6d44bf31
GL
83{
84 wxObjectStreamInfo *info;
85
86 if (!FirstStage())
87 return;
88
89 info = new wxObjectStreamInfo;
8d43638d
GL
90
91 if (m_saved_objs.Member(obj) != NULL) {
92 info->duplicate = TRUE;
93 } else {
94 info->duplicate = FALSE;
95 m_saved_objs.Append(obj);
96 }
1d44aaf8
GL
97 if (!obj)
98 info->duplicate = FALSE;
99
6d44bf31
GL
100 info->n_children = 0;
101 info->object = obj;
7a4b9130 102 info->parent = m_current_info; // Not useful here.
6d44bf31
GL
103 m_current_info->n_children++;
104 m_current_info->children.Append(info);
105}
106
107void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info)
108{
109 wxNode *node;
110
111 m_current_info = info;
112 // First stage: get children of obj
8d43638d 113 if (info->object && !info->duplicate)
7a4b9130 114 info->object->StoreObject(*this);
6d44bf31
GL
115
116 // Prepare and write the sub-entry about the child obj.
117 WriteObjectDef(*info);
118
119 node = info->children.First();
120
121 while (node) {
122 ProcessObjectDef((wxObjectStreamInfo *)node->Data());
123 node = node->Next();
124 }
125}
126
127void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info)
128{
129 wxNode *node = info->children.First();
130
131 m_current_info = info;
132
8d43638d 133 if (info->object && !info->duplicate)
7a4b9130 134 info->object->StoreObject(*this);
6d44bf31
GL
135
136 while (node) {
137 ProcessObjectData((wxObjectStreamInfo *)node->Data());
138 node = node->Next();
139 }
140}
141
142bool wxObjectOutputStream::SaveObject(wxObject& obj)
143{
144 wxObjectStreamInfo info;
145
146 if (m_saving)
147 return FALSE;
148
149 m_saving = TRUE;
150
151 // First stage
152 m_stage = 0;
153 info.object = &obj;
154 info.n_children = 0;
1d44aaf8 155 info.duplicate = FALSE;
6d44bf31
GL
156 ProcessObjectDef(&info);
157
158 m_stage = 1;
159 ProcessObjectData(&info);
160
161 info.children.Clear();
8d43638d 162 m_saved_objs.Clear();
6d44bf31
GL
163
164 m_saving = FALSE;
165
166 return TRUE;
167}
168
169// ----------------------------------------------------------------------------
170// wxObjectInputStream
171// ----------------------------------------------------------------------------
172
173wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
174 : wxFilterInputStream(s)
175{
856d2e52 176 m_secondcall = FALSE;
6d44bf31
GL
177}
178
179wxObject *wxObjectInputStream::SolveName(const wxString& name) const
180{
181 wxNode *node = m_solver.First();
182 wxObjectStreamInfo *info;
183
184 while (node) {
185 info = (wxObjectStreamInfo *)node->Data();
186 if (info->object_name == name)
187 return info->object;
188
189 node = node->Next();
190 }
c67daf87 191 return (wxObject *) NULL;
6d44bf31
GL
192}
193
7a4b9130
GL
194wxObject *wxObjectInputStream::GetParent() const
195{
196 if (!m_current_info->parent)
c67daf87 197 return (wxObject *) NULL;
7a4b9130
GL
198
199 return m_current_info->parent->object;
200}
201
1d44aaf8
GL
202wxObject *wxObjectInputStream::GetChild()
203{
204 wxObject *obj = GetChild(0);
205
206 m_current_info->children_removed++;
207
208 return obj;
209}
210
6d44bf31
GL
211wxObject *wxObjectInputStream::GetChild(int no) const
212{
1d44aaf8 213 wxNode *node;
7a4b9130
GL
214 wxObjectStreamInfo *info;
215
1d44aaf8 216 if (m_current_info->children_removed >= m_current_info->n_children)
5104949d 217 return (wxObject *) NULL;
1d44aaf8
GL
218
219 node = m_current_info->children.Nth(m_current_info->children_removed+no);
220
7a4b9130 221 if (!node)
c67daf87 222 return (wxObject *) NULL;
7a4b9130
GL
223
224 info = (wxObjectStreamInfo *)node->Data();
225
226 return info->object;
227}
228
229void wxObjectInputStream::RemoveChildren(int nb)
230{
231 m_current_info->children_removed += nb;
6d44bf31
GL
232}
233
234bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
235{
236 wxDataInputStream data_s(*this);
237 char sig[WXOBJ_BEG_LEN+1];
7a4b9130 238 wxString class_name;
6d44bf31
GL
239
240 Read(sig, WXOBJ_BEG_LEN);
241 sig[WXOBJ_BEG_LEN] = 0;
242 if (wxString(sig) != WXOBJ_BEGIN)
243 return FALSE;
7a4b9130
GL
244
245 class_name = data_s.ReadString();
7a4b9130 246 info->children_removed = 0;
f4a8c29f 247 info->n_children = 0;
6d44bf31 248
8d43638d 249 if (class_name == TAG_EMPTY_OBJECT)
c67daf87 250 info->object = (wxObject *) NULL;
8d43638d 251 else if (class_name == TAG_DUPLICATE_OBJECT) {
1d44aaf8 252 info->object_name = data_s.ReadString();
8d43638d 253 info->object = SolveName(info->object_name);
8d43638d 254 } else {
1d44aaf8 255 info->object_name = data_s.ReadString();
8d43638d 256 info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
1d44aaf8 257 info->n_children = data_s.Read32();
8d43638d 258 }
6d44bf31
GL
259 return TRUE;
260}
261
262wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *parent)
263{
264 wxObjectStreamInfo *info, *c_info;
265 int c;
266
267 info = new wxObjectStreamInfo;
268 info->parent = parent;
269 info->children.DeleteContents(TRUE);
270
271 m_solver.Append(info);
272
273 if (!ReadObjectDef(info))
c67daf87 274 return (wxObjectStreamInfo *) NULL;
6d44bf31
GL
275
276 for (c=0;c<info->n_children;c++) {
277 c_info = ProcessObjectDef(info);
278 if (!c_info)
c67daf87 279 return (wxObjectStreamInfo *) NULL;
6d44bf31
GL
280 info->children.Append(c_info);
281 }
282
283 return info;
284}
285
286void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info)
287{
288 wxNode *node = info->children.First();
6d44bf31
GL
289
290 m_current_info = info;
291
7a4b9130
GL
292 if (info->object)
293 info->object->LoadObject(*this);
6d44bf31 294 while (node) {
7a4b9130 295 ProcessObjectData((wxObjectStreamInfo *)node->Data());
6d44bf31
GL
296 node = node->Next();
297 }
1d44aaf8
GL
298
299 m_current_info = info;
300
301 if (info->recall) {
302 m_secondcall = TRUE;
303 info->object->LoadObject(*this);
304 m_secondcall = FALSE;
305 }
6d44bf31
GL
306}
307
308wxObject *wxObjectInputStream::LoadObject()
309{
310 wxObjectStreamInfo *info;
311 wxObject *object;
312
c67daf87 313 info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
6d44bf31 314 if (!info)
c67daf87 315 return (wxObject *) NULL;
6d44bf31
GL
316 ProcessObjectData(info);
317
318 object = info->object;
319
320 delete info; // It's magic ! The whole tree is destroyed.
321
322 return object;
323}
fcc6dddd 324
6dc6fda6 325#endif // wxUSE_SERIAL && wxUSE_STREAMS
fcc6dddd 326