1/*
2 * Copyright 2001-2010 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _ARCHIVABLE_H
6#define _ARCHIVABLE_H
7
8
9#include <image.h>
10#include <Message.h>
11#include <SupportDefs.h>
12
13
14class BMessage;
15
16
17namespace BPrivate {
18namespace Archiving {
19	class BArchiveManager;
20	class BUnarchiveManager;
21}
22}
23
24using ::BPrivate::Archiving::BArchiveManager;
25using ::BPrivate::Archiving::BUnarchiveManager;
26
27
28class BArchivable {
29public:
30								BArchivable(BMessage* from);
31								BArchivable();
32	virtual 					~BArchivable();
33
34	virtual	status_t 			Archive(BMessage* into, bool deep = true) const;
35	static 	BArchivable*		Instantiate(BMessage* archive);
36
37	virtual status_t			Perform(perform_code d, void* arg);
38
39	virtual	status_t 			AllUnarchived(const BMessage* archive);
40	virtual	status_t 			AllArchived(BMessage* archive) const;
41
42private:
43	friend 	class BUnarchiveManager;
44
45	virtual	void				_ReservedArchivable3();
46
47			int32				fArchivingToken;
48			uint32				_reserved;
49};
50
51
52class BArchiver {
53public:
54								BArchiver(BMessage* archive);
55								~BArchiver();
56
57			status_t			AddArchivable(const char* name,
58									BArchivable* archivable, bool deep = true);
59
60	inline	status_t			GetTokenForArchivable(BArchivable* archivable,
61									int32& _token);
62			status_t			GetTokenForArchivable(BArchivable* archivable,
63									bool deep, int32& _token);
64
65			bool				IsArchived(BArchivable* archivable);
66			status_t			Finish(status_t err = B_OK);
67			BMessage*			ArchiveMessage() const;
68
69private:
70	friend class BArchivable;
71
72								BArchiver(); // not defined
73								BArchiver(const BArchiver&); // not defined
74
75			void				RegisterArchivable(
76									const BArchivable* archivable);
77
78			BArchiveManager*	fManager;
79			BMessage*			fArchive;
80			bool				fFinished;
81			uint32				_reserved[2];
82};
83
84
85class BUnarchiver {
86public:
87			enum ownership_policy {
88				B_ASSUME_OWNERSHIP,
89				B_DONT_ASSUME_OWNERSHIP
90			};
91
92								BUnarchiver(const BMessage* archive);
93								~BUnarchiver();
94
95	template<class T>
96	inline	status_t			GetObject(int32 token, T*& object);
97
98	template<class T>
99			status_t			GetObject(int32 token, ownership_policy owning,
100									T*& object);
101
102	template<class T>
103	inline	status_t			FindObject(const char* name, T*& object);
104
105	template<class T>
106	inline	status_t			FindObject(const char* name,
107									ownership_policy owning,
108									T*& object);
109
110	template<class T>
111	inline	status_t			FindObject(const char* name,
112									int32 index, T*& object);
113
114	template<class T>
115			status_t			FindObject(const char* name, int32 index,
116									ownership_policy owning, T*& object);
117
118	inline	status_t			EnsureUnarchived(const char* name,
119									int32 index = 0);
120	inline	status_t			EnsureUnarchived(int32 token);
121
122			bool				IsInstantiated(int32 token);
123			bool				IsInstantiated(const char* name,
124									int32 index = 0);
125
126			status_t			Finish(status_t err = B_OK);
127			const BMessage*		ArchiveMessage() const;
128
129			void				AssumeOwnership(BArchivable* archivable);
130			void				RelinquishOwnership(BArchivable* archivable);
131
132	static	bool				IsArchiveManaged(const BMessage* archive);
133	static	BMessage*			PrepareArchive(BMessage*& archive);
134
135	template<class T>
136	static	status_t			InstantiateObject(BMessage* archive,
137									T*& object);
138
139private:
140	friend class BArchivable;
141
142								BUnarchiver(); // not defined
143								BUnarchiver(const BUnarchiver&); // not defined
144
145			void				RegisterArchivable(BArchivable* archivable);
146
147	inline	void				_CallDebuggerIfManagerNull();
148
149			BUnarchiveManager*	fManager;
150			const BMessage*		fArchive;
151			bool				fFinished;
152			uint32				_reserved[2];
153};
154
155
156// global functions
157
158typedef BArchivable* (*instantiation_func)(BMessage*);
159
160BArchivable* instantiate_object(BMessage* from, image_id* id);
161BArchivable* instantiate_object(BMessage* from);
162bool validate_instantiation(BMessage* from, const char* className);
163
164instantiation_func find_instantiation_func(const char* className,
165	const char* signature);
166instantiation_func find_instantiation_func(const char* className);
167instantiation_func find_instantiation_func(BMessage* archive);
168
169
170status_t
171BArchiver::GetTokenForArchivable(BArchivable* archivable, int32& _token)
172{
173	return GetTokenForArchivable(archivable, true, _token);
174}
175
176
177template<>
178status_t BUnarchiver::FindObject<BArchivable>(const char* name, int32 index,
179	ownership_policy owning, BArchivable*& archivable);
180
181
182template<class T>
183status_t
184BUnarchiver::FindObject(const char* name, int32 index,
185	ownership_policy owning, T*& object)
186{
187	object = NULL;
188
189	BArchivable* interim;
190	status_t err = FindObject(name, index, owning, interim);
191
192	if (err == B_OK && interim) {
193		object = dynamic_cast<T*>(interim);
194		if (!object) {
195			err = B_BAD_TYPE;
196			// we will not be deleting this item, but it must be deleted
197			if (owning == B_ASSUME_OWNERSHIP)
198				RelinquishOwnership(interim);
199		}
200	}
201	return err;
202}
203
204
205template<>
206status_t
207BUnarchiver::GetObject<BArchivable>(int32 token,
208	ownership_policy owning, BArchivable*& object);
209
210
211template<class T>
212status_t
213BUnarchiver::GetObject(int32 token, ownership_policy owning, T*& object)
214{
215	object = NULL;
216
217	BArchivable* interim;
218	status_t err = GetObject(token, owning, interim);
219
220	if (err == B_OK && interim) {
221		object = dynamic_cast<T*>(interim);
222		if (!object) {
223			err = B_BAD_TYPE;
224			// we will not be deleting this item, but it must be deleted
225			if (owning == B_ASSUME_OWNERSHIP)
226				RelinquishOwnership(interim);
227		}
228	}
229	return err;
230}
231
232
233template<class T>
234status_t
235BUnarchiver::GetObject(int32 token, T*& object)
236{
237	return GetObject<T>(token, B_ASSUME_OWNERSHIP, object);
238}
239
240
241template<class T>
242status_t
243BUnarchiver::FindObject(const char* name, ownership_policy owning, T*& object)
244{
245	return FindObject(name, 0, owning, object);
246}
247
248
249template<class T>
250status_t
251BUnarchiver::FindObject(const char* name, T*& object)
252{
253	return FindObject<T>(name, 0, B_ASSUME_OWNERSHIP, object);
254}
255
256
257template<class T>
258status_t
259BUnarchiver::FindObject(const char* name,
260	int32 index, T*& object)
261{
262	return FindObject(name, index, B_ASSUME_OWNERSHIP, object);
263}
264
265
266status_t
267BUnarchiver::EnsureUnarchived(int32 token)
268{
269	BArchivable* dummy;
270	return GetObject(token, B_DONT_ASSUME_OWNERSHIP, dummy);
271}
272
273
274status_t
275BUnarchiver::EnsureUnarchived(const char* name, int32 index)
276{
277	BArchivable* dummy;
278	return FindObject(name, index, B_DONT_ASSUME_OWNERSHIP, dummy);
279}
280
281
282template<>
283status_t
284BUnarchiver::InstantiateObject<BArchivable>(BMessage* from,
285	BArchivable*& object);
286
287
288template<class T>
289status_t
290BUnarchiver::InstantiateObject(BMessage* archive, T*& object)
291{
292	object = NULL;
293
294	BArchivable* interim;
295	status_t err = InstantiateObject(archive, interim);
296	if (err != B_OK || interim == NULL)
297		return err;
298
299	object = dynamic_cast<T*>(interim);
300	if (object == NULL) {
301		delete interim;
302		return B_BAD_TYPE;
303	}
304
305	return B_OK;
306}
307
308
309#endif	// _ARCHIVABLE_H
310