]> git.saurik.com Git - wxWidgets.git/blob - src/common/objstrm.cpp
* Fixed two memory leaks.
[wxWidgets.git] / src / common / objstrm.cpp
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
29 wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s)
30 : wxFilterOutputStream(s)
31 {
32 m_saving = FALSE;
33 }
34
35 wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
36 {
37 wxString name;
38
39 name.Printf("%x", (unsigned long)obj);
40 return name;
41 }
42
43 void 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
69 void 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
94 void 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
114 void 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
129 bool 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
160 wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
161 : wxFilterInputStream(s)
162 {
163 }
164
165 wxObject *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
180 wxObject *wxObjectInputStream::GetParent() const
181 {
182 if (!m_current_info->parent)
183 return (wxObject *) NULL;
184
185 return m_current_info->parent->object;
186 }
187
188 wxObject *wxObjectInputStream::GetChild()
189 {
190 wxObject *obj = GetChild(0);
191
192 m_current_info->children_removed++;
193
194 return obj;
195 }
196
197 wxObject *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
215 void wxObjectInputStream::RemoveChildren(int nb)
216 {
217 m_current_info->children_removed += nb;
218 }
219
220 bool 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
248 wxObjectStreamInfo *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
272 void 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
294 wxObject *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 }