2 * Copyright 2007 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Niels Sascha Reedijk, niels.reedijk@gmail.com
7 * Alex Wilson, yourpalal2@gmail.com
8 * John Scipione, jscipione@gmail.com
11 * David Weizades, ddewbofh@hotmail.com
12 * Thom Holwerda, slakje@quicknet.nl
15 * headers/os/support/Archivable.h rev 37751
16 * src/kits/support/Archivable.cpp rev 44303
24 \brief Provides the BArchivable interface and declares the BArchiver and
33 \brief Interface for objects that can be archived into a BMessage.
35 BArchivable provides an interface for objects that can be put into message
36 archives and extracted into objects in another location. Using this you are
37 able to send objects between applications, or even between computers across
40 BArchivable differs from BFlattenable in that BFlattenable is designed to
41 store objects into flat streams of data, the main objective being storage to
42 disk. The objective of this interface, however, is to store objects that
43 will later be restored as new (but identical) objects. To illustrate this
44 point, BArchivable objects can be restored automatically to the correct
45 class, whereas BFlattenable objects have a data type which you need to map
48 Archiving is done with the Archive() method. If your class supports it, the
49 caller can request it to store into a deep archive, meaning that all child
50 objects in it will be stored. Extracting the archive works with the
51 Instantiate() method, which is static. Since the interface is designed to
52 extract objects without the caller knowing what kind of object it actually
53 is, the global function #instantiate_object() instantiates a message without
54 you manually having to determine the class the message is from. This adds
55 considerable flexibility and allows BArchivable to be used in combination
58 To provide this interface in your classes you should publicly inherit this
59 class. You should implement Archive() and Instantiate(), and provide one
60 constructor that takes one BMessage argument.
62 If your class holds references to other BArchivable objects that you wish
63 to archive, then you should consider using the BArchiver and BUnarchiver
64 classes in your Archive() method and archive constructor, respectively.
65 You should also consider implementing the AllArchived() and AllUnarchived()
66 methods, which were designed to ease archiving and unarchiving in such
74 \fn BArchivable::BArchivable(BMessage* from)
75 \brief Constructor. Does important behind-the-scenes work in the
78 If you inherit this interface you should provide at least one constructor
79 that takes one BMessage argument. In that constructor, you should call
80 your parent class' archive constructor (even if your parent class is
88 \fn BArchivable::BArchivable()
89 \brief Constructor. Does nothing.
96 \fn BArchivable::~BArchivable()
97 \brief Destructor. Does nothing.
104 \fn virtual status_t BArchivable::Archive(BMessage* into, bool deep) const
105 \brief Archive the object into a BMessage.
107 You should call this method from your derived implementation as it adds the
108 data needed to instantiate your object to the message.
110 \param into The message you store your object in.
111 \param deep If \c true, all children of this object should be archived as
114 \retval B_OK The archive operation was successful.
115 \retval B_BAD_VALUE \c NULL \a archive message.
116 \retval B_ERROR The archive operation failed.
123 \fn static BArchivable* BArchivable::Instantiate(BMessage* archive)
124 \brief Static member to restore objects from messages.
126 You should always check that the \a archive argument actually corresponds to
127 your class. The automatic functions, such as #instantiate_object() and
128 BUnarchiver::InstantiateObject() will not choose the wrong class but manual
129 calls to this member might be faulty. You can verify that \c archive
130 stores an object of your class with the validate_instantiation() function.
132 \param archive The message with the data of the object to restore.
134 \return A pointer to a BArchivable object.
135 \retval You should return a pointer to the object you create with
136 \c archive, or \c NULL if the unarchival fails.
138 \warning The default implementation will always return \c NULL. Even though
139 it is possible to store plain BArchivable objects, it is impossible to
142 \see instantiate_object(BMessage*)
143 \see BUnarchiver::InstantiateObject()
150 \fn virtual status_t BArchivable::Perform(perform_code d, void* arg)
151 \brief Perform some action (Internal method defined for binary
152 compatibility purposes).
154 \internal This method is defined for binary compatibility purposes, it is
155 used to ensure that the correct AllUnarchived() and AllArchived()
156 methods are called for objects, as those methods are new to
159 \param d The perform code.
160 \param arg A pointer to store some data.
162 \returns A status code.
169 \fn virtual status_t BArchivable::AllUnarchived(const BMessage* archive)
170 \brief Method relating to the use of \c BUnarchiver.
172 This hook function is called triggered in the BUnarchiver::Finish() method.
173 In this method, you can rebuild references to objects that may be direct
174 children of your object, or may be children of other objects.
175 Implementations of this method should call the implementation of
176 their parent class, the same as for the Archive() method.
178 \warning To guarantee that your AllUnarchived() method will be called
179 during unarchival, you must create a BUnarchiver object in your
182 \see BUnarchiver, BUnarchiver::Finish()
188 /*! \fn virtual status_t BArchivable::AllArchived(BMessage* into) const
189 \brief Method relating to the use of \c BArchiver.
191 This hook function is called once the first BArchiver that was created in
192 an archiving session is either destroyed, or has its Finish() method
193 called. Implementations of this method can be used, in conjunction with
194 BArchiver::IsArchived(), to reference objects in your archive that you
195 do not own, depending on whether or not those objects were archived by their
196 owners. Implementations of this method should call the implementation of
197 their parent class, the same as for the Archive() method.
199 \warning To guarantee that your AllArchived() method will be called
200 during archival, you must create a BArchiver object in your
201 Archive() implementation.
203 \warning You should archive any objects you own in your Archive()
204 method implementation, and \b NOT your AllArchived() method.
206 \see BArchiver BArchiver::Finish()
212 ///// BArchiver /////
219 \brief A class that simplifies the archiving of complicated BArchivable
222 The BArchiver class is a small class that is used for archiving of
223 complicated BArchivable hierarchies. Such a hierarchy may include
224 multiple BArchivable objects, each of which might be referenced by
225 many BArchivable objects. With the BArchiver class, you can be certain
226 that each BArchivable object is archived only once with very little work.
227 When used in conjuction with the BArchivable::AllArchived() and
228 BArchivable::AllUnarchived() methods, it is simple to rebuild your system of
229 references upon unarchival so that they are equivalent to those that were
230 present in your original hierarchy.
232 The objects you archive can be retrieved using a BUnarchiver object.
239 \fn BArchiver::BArchiver(BMessage* archive)
240 \brief Constructs a BArchiver object that manages \c archive.
247 \fn BArchiver::~BArchiver()
248 \brief Destroys a BArchiver object. If the BArchiver object has not had its
249 Finish() method called, this will be done now.
256 \fn status_t BArchiver::AddArchivable(const char* name,
257 BArchivable* archivable, bool deep = true)
258 \brief Adds a reference to \c archivable to the archive used to
259 construct this BArchiver. May call \c archivable's Archive() method.
261 \param name Where this reference will be stored in the archive.
262 \param archivable The BArchivable* object that to reference.
263 \param deep Passed to \c archivable->Archive() if \c archivable must
266 Adds a reference to \c archivable to your archive. If \c archivable has
267 not yet been archived, then its Archive() method is called. BArchiver
268 can only track BArchivable objects that have been archived through this
269 method or the GetTokenForArchivable() methods.
271 \warning If you manually archive an object, and then pass it to
272 AddArchivable() or GetTokenForArchivable(), it will be archived
273 again, and when unarchived you will end up with two different
281 \fn status_t BArchiver::GetTokenForArchivable(BArchivable* archivable,
282 bool deep, int32& _token);
283 \brief Get a token representing a BArchivable object for this archiving
286 \param archivable The BArchivable object for which you wish to get a
288 \param deep Controls how \c archivable will be archived, if it has not yet
289 been archived in this session.
290 \param[out] _token The token representing \c archivable is stored here.
292 Retrieves or creates a token to represent \c archivable in this archiving
293 session. If \c archivable has not yet been archived, it will be now. If
294 \c archivable gets archived, the \c deep parameter will be passed to its
297 \warning If you manually archive an object, and then pass it to
298 GetTokenForArchivable(), it will be archived again, and when
299 unarchived you will end up with two different BArchivable objects.
306 \fn status_t BArchiver::GetTokenForArchivable(BArchivable* archivable,
308 \brief Equivalent to calling the expanded GetTokenForArchivable(
309 BArchivable*, bool, int32&), with the deep parameter equal to
312 \see GetTokenForArchivable(BArchivable*, bool, int32&)
319 \fn bool BArchiver::IsArchived(BArchivable* archivable);
320 \brief Returns whether \c archivable has already been archived in this
323 \return Whether or not the object has already been archived.
324 \retval true \c archivable has been archived in this archiving session.
325 \retval false \c archivable has not been archived in this archiving session.
332 \fn status_t BArchiver::Finish(status_t err = B_OK);
333 \brief Report any archiving errors and possibly complete the archiving
336 This method may finish an archiving session (triggering the call of all
337 archived objects' AllArchived() methods) if the following conditions
339 - No errors have been reported to this or any other BArchiver object
341 - This is the last remaining BArchiver that has not had its Finish()
344 If you call this method with an error code not equal to B_OK, then this
345 archiving session has failed, archived objects will not have their
346 AllArchived() methods called, and any subsequent calls to this method
347 on any BArchiver objects in this session will return your error code.
349 \return The first error reported in this archiving session, or \c B_OK.
356 \fn const BMessage* BArchiver::ArchiveMessage() const
357 \brief Returns the BMessage* used to construct this BArchiver. This is
358 the archive that AddArchivable() modifies.
364 ///// BUnarchiver /////
371 \brief A class that simplifies the unarchiving of complicated BArchivable
374 The BUnarchiver class is a small class used to recover BArchivable objects
375 that have been archived with the BArchiver class. It also provides ownership
376 semantics, so that memory leaks can be avoided during the unarchival
377 process. When retrieving an object (either via GetObject() or FindObject()),
378 you can specify a BUnarchiver::ownership_policy. If you specify
379 BUnarchiver::B_ASSUME_OWNERSHIP, you will become responsible for deleting
380 the retrieved item. If you specify BUnarchiver::B_DONT_ASSUME_OWNERSHIP,
381 you will not become responsible. You cannot take ownership of the same
382 object twice. After the unarchival process finishes, any unclaimed objects,
383 excluding the root object (the object being instantiated via
384 instantiate_object() or BUnarchiver::InstantiateObject()), will be deleted.
386 If you are updating a class that previously did not use the BArchiver and
387 BUnarchiver helper classes, and want to maintain backwards compatibility
388 with old archive, this can be done using the IsArchiveManaged() method.
390 \warning Calling methods on your BUnarchiver with a legacy archive (one
391 that was not managed by a BArchiver during archival) will result
392 in a call to debugger().
399 \fn BUnarchiver::BUnarchiver(const BMessage* archive)
400 \brief Constructs a BUnarchiver object to manage \c archive.
402 \note To guarantee that your AllUnarchived() method will be called during
403 archival, you must create a BUnarchiver object in your archive
404 constructor. It is necessary to do this even if you won't use the
405 BUnarchiver object in your archive constructor.
407 \warning Do not construct a BUnarchiver object without first calling
408 BUnarchiver::PrepareArchive() on \c archive. It is only safe to
409 build a BUnarchiver without this call in your AllUnarchived()
412 \see BUnarchiver::PrepareArchive()
419 \fn BUnarchiver::~BUnarchiver()
420 \brief Destroys a BUnarchiver object.
422 Calls this objects Finish() method, if it has not yet been called.
429 \fn status_t BUnarchiver::EnsureUnarchived(int32 token)
430 \brief Ensure the object represented by \a token is unarchived and
433 \param token the object \a token
435 \returns A status code.
442 \fn status_t BUnarchiver::EnsureUnarchived(const char* name,
444 \brief Ensure the object archived under \a name at \a index is unarchived
447 \param name The archive \a name.
448 \param index The archive \a index.
450 \returns A status code.
457 \fn bool BUnarchiver::IsInstantiated(int32 token)
458 \brief Checks whether the object represented by \c token has been
459 instantiated in this session.
461 \param token The object \a token.
463 \returns \c true if instantiated, \c false otherwise
470 \fn bool BUnarchiver::IsInstantiated(const char* name, int32 index = 0)
471 \brief Checks whether the object archived under \a name at \a index has been
472 instantiated in this session.
474 \param name The archive \a name.
475 \param index The arcive \a token.
477 \returns \c true if instantiated, \c false otherwise.
484 \fn template<class T> status_t BUnarchiver::GetObject(int32 token,
485 ownership_policy owning, T*& object)
486 \brief Recover an object by token that was archived by a BArchiver object.
487 If the object has not yet been instantiated, and this request is not coming
488 from an AllUnarchived() implementation, the object will be instantiated now.
490 If the retrieved object is not of the type T, then this method will fail.
491 If this method fails, you will not receive ownership of the object, no
492 matter what you specified in \c owning.
494 \tparam T The type of \a object you wish to find.
496 \param token The \a token you got for this object from
497 BArchiver::GetTokenForArchivable() during archival.
498 \param owning Whether or not you wish to take ownership of the
500 \param object Return parameter for the retrieved object of type T.
502 \returns A status code.
503 \retval B_OK The object retrieved was of type T.
504 \retval B_BAD_TYPE The object retrieved was not of type T.
511 \fn template<class T> status_t BUnarchiver::GetObject(int32 token,
513 \brief Recover and take ownership of an object represented by \a token.
515 Equivalent to calling GetObject(token, \c B_ASSUME_OWNERSHIP, object)
517 \tparam T The type of \a object you wish to find.
519 \param token The \a token you got for this object from
520 BArchiver::GetTokenForArchivable() during archival.
521 \param object The return parameter for the retrieved object of type T.
523 \returns A status code.
524 \retval B_OK The object retrieved was of type T.
525 \retval B_BAD_TYPE The object retrieved was not of type T.
532 \fn template<class T> status_t BUnarchiver::FindObject(const char* name,
533 int32 index, ownership_policy owning, T*& object)
534 \brief Recover an object that had previously been archived using
535 the BArchiver::AddArchivable() method.
537 If the object has not yet been instantiated, and this request is not
538 coming from an AllUnarchived() implementation, the object will be
541 If the retrieved object is not of the type T, then this method will fail.
542 If this method fails, you will not receive ownership of the object, no
543 matter what you specified in \c owning.
545 \tparam T The type of object you wish to find.
547 \param name The name that was passed to BArchiver::AddArchivable() when
549 \param index The index of the object you wish to recover (\c 0-based,
550 like BMessage::FindData().
551 \param owning Dictates whether or not you wish to take ownership of the
553 \param object Return parameter for the retrieved object of type T.
555 \returns A status code.
556 \retval B_OK The object retrieved was of type T.
557 \retval B_BAD_TYPE The object retrieved was not of type T.
564 \fn template<class T> status_t BUnarchiver::FindObject(const char* name,
565 int32 index, T*& object)
566 \brief Recover and take ownership of an object that had previously been
567 archived using the BArchiver::AddArchivable() method.
569 \tparam T The type of object you wish to find.
571 \param name The name that was passed to BArchiver::AddArchivable() when
573 \param index The index of the object you wish to recover (\c 0-based,
574 like #BMessage::FindData().
575 \param object Return parameter for the retrieved object of type T.
577 \returns A status code.
578 \retval B_OK The object retrieved was of type T.
579 \retval B_BAD_TYPE The object retrieved was not of type T.
586 \fn template<class T> status_t BUnarchiver::FindObject(const char* name,
587 ownership_policy owning, T*& object)
588 \brief Recover an object at index \c 0 that had previously been
589 archived using the BArchiver::AddArchivable() method.
591 Equivalent to calling FindObject(name, \c 0, owning, object).
593 \tparam T The type of \a object you wish to find.
595 \param name The name that was passed to BArchiver::AddArchivable() when
597 \param owning Dictates whether or not you wish to take ownership of the
599 \param object Return parameter for the retrieved object of type T.
601 \returns A status code.
602 \retval B_OK The object retrieved was of type T.
603 \retval B_BAD_TYPE The object retrieved was not of type T.
610 \fn template<class T> status_t BUnarchiver::FindObject(const char* name,
612 \brief Recover and take ownership of an object at index \c 0 that had
613 previously been archived using the BArchiver::AddArchivable() method.
615 Equivalent to calling FindObject(name, \c 0,
616 BUnarchiver::B_ASSUME_OWNERSHIP, object).
618 \tparam T The type of \a object you wish to find.
620 \param name The name that was passed to BArchiver::AddArchivable() when
622 \param object Return parameter for the retrieved \a object of type T.
624 \returns A status code.
625 \retval B_OK The \a object retrieved was of type T.
626 \retval B_BAD_TYPE The \a object retrieved was not of type T.
633 \fn status_t BUnarchiver::Finish(status_t err = B_OK);
634 \brief Report any unarchiving errors and possibly complete the archiving
637 This method may finish an unarchiving session (triggering the call of all
638 instantiated objects' AllUnarchived() methods) if the following conditions
641 - No errors have been reported to this or any other BUnarchiver
642 object within this session.
643 - This is the last remaining BUnarchiver that has not had its
644 Finish() method invoked.
646 If you call this method with an error code not equal to B_OK, then this
647 unarchiving session has failed, instantiated objects will not have their
648 AllUnarchived() methods called, and any subsequent calls to this method
649 on any BUnarchiver objects in this session will return your error code.
650 Furthermore, any objects that have been instantiated, but have not had
651 their ownership assumed by another object will now be deleted (excluding
654 \return The first error reported in this unarchiving session, or \c B_OK.
661 \fn const BMessage* BUnarchiver::ArchiveMessage() const
662 \brief Returns the BMessage* used to construct this BUnarchiver.
664 This is the archive that FindObject() uses.
669 \fn static bool BUnarchiver::IsArchiveManaged(const BMessage* archive)
670 \brief Checks whether \a archive was managed by a BArchiver object.
672 This method can be used to maintain archive backwards-compatibility for a
673 class that has been updated to use the BArchiver class. If there is a
674 possibility that you are may dealing with a legacy archive, you can use
675 this method to find out before calling any methods on your BUnarchiver
678 Here is an example of how you might use this method. Note that you
679 must still call PrepareArchive(archive) either way.
682 MyArchivableClas::MyArchivableClass(BMessage* archive)
684 BArchivable(BUnarchiver::PrepareArchive(archive))
686 BUnarchiver unarchiver(archive);
688 if (BUnarchiver::IsArchiveManaged(archive)) {
689 // ... calls to FindObject() or GetObject() here ...
691 // ... calls to BMessage::FindMessage() here ...
696 \returns Whether \a archive was managed by a BArchiver object.
697 \retval true if \a archive was managed by a BArchiver object.
698 \retval false otherwise.
705 \fn static BMessage* BUnarchiver::PrepareArchive(BMessage* &archive)
706 \brief Prepares \c archive for use by a BUnarchiver.
708 This method must be called if you plan to use a BUnarchiver on an archive.
709 It must be called once for each class an object inherits from that
710 will use a BUnarchiver.
712 \warning This method \b must be called \b before a call to the
713 archive constructor of your parent class.
715 Notice the use of this method in the example provided below.
717 MyArchivableClas::MyArchivableClas(BMessage* archive)
719 BArchivable(BUnarchiver::PrepareArchive(archive))
725 \param archive The archive you wish to have prepared.
727 \return The same #BMessage as is passed in.
734 \fn void BUnarchiver::AssumeOwnership(BArchivable* archivable)
735 \brief Become the owner of \a archivable.
737 After calling this method you are responsible for deleting the
740 \param archivable The \a archivable object.
747 \fn void BUnarchiver::RelinquishOwnership(BArchivable* archivable)
748 \brief Relinquish ownership of \a archivable. If \a archivable remains
749 unclaimed at the end of the unarchiving session, it will be deleted
750 (unless it is the root object).
752 \param archivable The \a archivable object.
759 \fn template<class T> status_t BUnarchiver::InstantiateObject(
760 BMessage* from, T*& object)
761 \brief Attempt to instantiate an object of type T from BMessage*
764 If the instantiated object is not of type T, then it will be deleted,
765 and this method will return \c B_BAD_TYPE. This method is similar to
766 the instantiate_object() function, but provides error reporting and
767 protection from memory leaks.
769 \param from The #BMessage to instantiate from.
770 \param object Return parameter for the retrieved object of type T.
772 \returns A status code.
773 \retval B_OK The object retrieved was of type T.
774 \retval B_BAD_TYPE The object retrieved was not of type T.
780 ///// Global methods /////
784 \addtogroup support_globals
792 \typedef typedef BArchivable* (*instantiation_func)(BMessage*)
793 \brief Internal definition of a function that can instantiate objects that
794 have been created with the BArchivable API.
801 \fn BArchivable* instantiate_object(BMessage *from, image_id *id)
802 \brief Instantiate an archived object with the object being defined in a
803 different application or library.
805 This function is similar to instantiate_object(BMessage *from), except that
806 it takes the \a id argument referring to an image where the object might be
809 \note Images are names for executable files. Image id's refer to these
810 executable files that have been loaded by your application. Have a
811 look at the kernel API for further information.
818 \fn BArchivable* instantiate_object(BMessage *from)
819 \brief Instantiate an archived object.
821 This global function will determine the base class, based on the \a from
822 argument, and it will call the Instantiate() function of that object to
825 \param from The archived object.
827 \return The object returns a pointer to the instantiated object, or \c NULL
828 if the instantiation failed. The global \c errno variable will
829 contain the reason why it failed.
831 \see instantiate_object(BMessage *from, image_id *id)
838 \fn bool validate_instantiation(BMessage* from, const char* className)
839 \brief Internal function that checks if the \a className is the same as the
840 one stored in the \a from message.
847 \fn instantiation_func find_instantiation_func(const char* className,
848 const char* signature)
849 \brief Internal function that searches for the instantiation func with a
850 specific signature. Use instantiate_object() instead.
857 \fn instantiation_func find_instantiation_func(const char* className)
858 \brief Internal function that searches for the instantiation func of a
859 specific class. Use instantiate_object() instead.
866 \fn instantiation_func find_instantiation_func(BMessage* archive)
867 \brief Internal function that searches for the instantiation func that
868 works on the specified \a archive. Use instantiate_object() instead.