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