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