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