]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/objstrm.cpp
* Fixed two memory leaks.
[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#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
22#define TAG_EMPTY_OBJECT "NULL"
23#define TAG_DUPLICATE_OBJECT "DUPLIC"
24
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);
48
49 if (info.duplicate) {
50 data_s.WriteString(TAG_DUPLICATE_OBJECT);
51 data_s.WriteString(GetObjectName(info.object));
52 return;
53 }
54
55 if (info.object) {
56 data_s.WriteString(info.object->GetClassInfo()->GetClassName());
57 } else {
58 data_s.WriteString(TAG_EMPTY_OBJECT);
59 return;
60 }
61
62 data_s.WriteString(GetObjectName(info.object));
63
64 // I assume an object will not have millions of children
65 // Hmmm ... it could have (for example wxGrid)
66 data_s.Write32(info.children.Number());
67}
68
69void wxObjectOutputStream::AddChild(wxObject *obj)
70{
71 wxObjectStreamInfo *info;
72
73 if (!FirstStage())
74 return;
75
76 info = new wxObjectStreamInfo;
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 }
84 if (!obj)
85 info->duplicate = FALSE;
86
87 info->n_children = 0;
88 info->object = obj;
89 info->parent = m_current_info; // Not useful here.
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
100 if (info->object && !info->duplicate)
101 info->object->StoreObject(*this);
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
120 if (info->object && !info->duplicate)
121 info->object->StoreObject(*this);
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;
142 info.duplicate = FALSE;
143 ProcessObjectDef(&info);
144
145 m_stage = 1;
146 ProcessObjectData(&info);
147
148 info.children.Clear();
149 m_saved_objs.Clear();
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 }
177 return (wxObject *) NULL;
178}
179
180wxObject *wxObjectInputStream::GetParent() const
181{
182 if (!m_current_info->parent)
183 return (wxObject *) NULL;
184
185 return m_current_info->parent->object;
186}
187
188wxObject *wxObjectInputStream::GetChild()
189{
190 wxObject *obj = GetChild(0);
191
192 m_current_info->children_removed++;
193
194 return obj;
195}
196
197wxObject *wxObjectInputStream::GetChild(int no) const
198{
199 wxNode *node;
200 wxObjectStreamInfo *info;
201
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
207 if (!node)
208 return (wxObject *) NULL;
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;
218}
219
220bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
221{
222 wxDataInputStream data_s(*this);
223 char sig[WXOBJ_BEG_LEN+1];
224 wxString class_name;
225
226 Read(sig, WXOBJ_BEG_LEN);
227 sig[WXOBJ_BEG_LEN] = 0;
228 if (wxString(sig) != WXOBJ_BEGIN)
229 return FALSE;
230
231 class_name = data_s.ReadString();
232 info->children_removed = 0;
233
234 if (class_name == TAG_EMPTY_OBJECT)
235 info->object = (wxObject *) NULL;
236 else if (class_name == TAG_DUPLICATE_OBJECT) {
237 info->object_name = data_s.ReadString();
238 info->object = SolveName(info->object_name);
239 info->n_children = 0;
240 } else {
241 info->object_name = data_s.ReadString();
242 info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
243 info->n_children = data_s.Read32();
244 }
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))
260 return (wxObjectStreamInfo *) NULL;
261
262 for (c=0;c<info->n_children;c++) {
263 c_info = ProcessObjectDef(info);
264 if (!c_info)
265 return (wxObjectStreamInfo *) NULL;
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();
275
276 m_current_info = info;
277
278 if (info->object)
279 info->object->LoadObject(*this);
280 while (node) {
281 ProcessObjectData((wxObjectStreamInfo *)node->Data());
282 node = node->Next();
283 }
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 }
292}
293
294wxObject *wxObjectInputStream::LoadObject()
295{
296 wxObjectStreamInfo *info;
297 wxObject *object;
298
299 info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
300 if (!info)
301 return (wxObject *) NULL;
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}