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