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