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