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