Author: bonefish Date: 2010-07-08 16:54:25 +0200 (Thu, 08 Jul 2010) New Revision: 37431 Changeset: http://dev.haiku-os.org/changeset/37431/haiku Added: haiku/trunk/headers/private/binary_compatibility/Support.h haiku/trunk/src/kits/support/ArchivingManagers.cpp haiku/trunk/src/kits/support/ArchivingManagers.h Modified: haiku/trunk/headers/os/app/Message.h haiku/trunk/headers/os/support/Archivable.h haiku/trunk/headers/private/app/MessagePrivate.h haiku/trunk/headers/private/binary_compatibility/Global.h haiku/trunk/src/kits/app/Message.cpp haiku/trunk/src/kits/support/Archivable.cpp haiku/trunk/src/kits/support/Jamfile Log: Patch by Alex Wilson (compilation fixes by myself): Extended the archiving/ unarchiving protocol to support archival of arbitrary object graphs. Modified: haiku/trunk/headers/os/app/Message.h =================================================================== --- haiku/trunk/headers/os/app/Message.h 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/headers/os/app/Message.h 2010-07-08 14:54:25 UTC (rev 37431) @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009, Haiku Inc. All Rights Reserved. + * Copyright 2005-2010, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -320,8 +320,10 @@ BMessage* fQueueLink; // fQueueLink is used by BMessageQueue to build a linked list - uint32 fReserved[9]; + void* fArchivingPointer; + uint32 fReserved[8]; + // deprecated BMessage(BMessage *message); Modified: haiku/trunk/headers/os/support/Archivable.h =================================================================== --- haiku/trunk/headers/os/support/Archivable.h 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/headers/os/support/Archivable.h 2010-07-08 14:54:25 UTC (rev 37431) @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2001-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _ARCHIVABLE_H @@ -12,34 +12,116 @@ class BMessage; +namespace BPrivate { +namespace Archiving { + class BArchiveManager; + class BUnarchiveManager; +} +} +using BPrivate::Archiving::BArchiveManager; +using BPrivate::Archiving::BUnarchiveManager; + + class BArchivable { - public: - BArchivable(BMessage* from); - BArchivable(); - virtual ~BArchivable(); +public: + BArchivable(BMessage* from); + BArchivable(); + virtual ~BArchivable(); - virtual status_t Archive(BMessage* into, bool deep = true) const; - static BArchivable* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* archive); - // Private or reserved - virtual status_t Perform(perform_code d, void* arg); + virtual status_t Perform(perform_code d, void* arg); - private: - virtual void _ReservedArchivable1(); - virtual void _ReservedArchivable2(); - virtual void _ReservedArchivable3(); + virtual status_t AllUnarchived(const BMessage* archive); + virtual status_t AllArchived(BMessage* archive) const; - uint32 _reserved[2]; +private: + virtual void _ReservedArchivable3(); + + uint32 _reserved[2]; }; +class BArchiver { +public: + BArchiver(BMessage* archive); + ~BArchiver(); + + status_t AddArchivable(const char* name, + BArchivable* archivable, bool deep = true); + + status_t GetTokenForArchivable(BArchivable* archivable, + int32& _token, bool deep = true); + + bool IsArchived(BArchivable* archivable); + status_t Finish(); + BMessage* ArchiveMessage() const; + +private: + friend class BArchivable; + + BArchiver(); // not defined + BArchiver(const BArchiver&); // not defined + + void RegisterArchivable(const BArchivable* archivable); + + BArchiveManager* fManager; + BMessage* fArchive; + bool fFinished; +}; + + +class BUnarchiver { +public: + BUnarchiver(const BMessage* archive); + ~BUnarchiver(); + + status_t GetArchivable(int32 token, + BArchivable** archivable); + + status_t FindArchivable(const char* name, + BArchivable** archivable); + + status_t FindArchivable(const char* name, int32 index, + BArchivable** archivable); + + status_t EnsureUnarchived(const char* name, + int32 index = 0); + status_t EnsureUnarchived(int32 token); + + bool IsInstantiated(int32 token); + bool IsInstantiated(const char* name, + int32 index = 0); + + status_t Finish(); + const BMessage* ArchiveMessage() const; + + static bool IsArchiveManaged(BMessage* archive); + static BMessage* PrepareArchive(BMessage*& archive); +private: + friend class BArchivable; + + BUnarchiver(); // not defined + BUnarchiver(const BUnarchiver&); // not defined + + void RegisterArchivable(BArchivable* archivable); + + void _CallDebuggerIfManagerNull(); + + BUnarchiveManager* fManager; + const BMessage* fArchive; + bool fFinished; +}; + + // global functions typedef BArchivable* (*instantiation_func)(BMessage*); -BArchivable* instantiate_object(BMessage *from, image_id *id); -BArchivable* instantiate_object(BMessage *from); +BArchivable* instantiate_object(BMessage* from, image_id* id); +BArchivable* instantiate_object(BMessage* from); bool validate_instantiation(BMessage* from, const char* className); instantiation_func find_instantiation_func(const char* className, Modified: haiku/trunk/headers/private/app/MessagePrivate.h =================================================================== --- haiku/trunk/headers/private/app/MessagePrivate.h 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/headers/private/app/MessagePrivate.h 2010-07-08 14:54:25 UTC (rev 37431) @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009, Haiku Inc. All rights reserved. + * Copyright 2005-2010, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -191,6 +191,20 @@ reply, sendTimeout, replyTimeout); } + + void* + ArchivingPointer() + { + return fMessage->fArchivingPointer; + } + + + void + SetArchivingPointer(void* pointer) + { + fMessage->fArchivingPointer = pointer; + } + // static methods static status_t Modified: haiku/trunk/headers/private/binary_compatibility/Global.h =================================================================== --- haiku/trunk/headers/private/binary_compatibility/Global.h 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/headers/private/binary_compatibility/Global.h 2010-07-08 14:54:25 UTC (rev 37431) @@ -21,9 +21,12 @@ PERFORM_CODE_SET_LAYOUT = 1006, PERFORM_CODE_INVALIDATE_LAYOUT = 1007, PERFORM_CODE_DO_LAYOUT = 1008, - PERFORM_CODE_GET_TOOL_TIP_AT = 1009 + PERFORM_CODE_GET_TOOL_TIP_AT = 1009, // support kit + + PERFORM_CODE_ALL_ARCHIVED = 1010, + PERFORM_CODE_ALL_UNARCHIVED = 1011 }; Added: haiku/trunk/headers/private/binary_compatibility/Support.h =================================================================== --- haiku/trunk/headers/private/binary_compatibility/Support.h (rev 0) +++ haiku/trunk/headers/private/binary_compatibility/Support.h 2010-07-08 14:54:25 UTC (rev 37431) @@ -0,0 +1,23 @@ +/* + * Copyright 2010, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _BINARY_COMPATIBILITY_SUPPORT_H +#define _BINARY_COMPATIBILITY_SUPPORT_H + + +#include <binary_compatibility/Global.h> + + +struct perform_data_all_unarchived { + const BMessage* archive; + status_t return_value; +}; + + +struct perform_data_all_archived { + BMessage* archive; + status_t return_value; +}; + +#endif /* _BINARY_COMPATIBILITY_INTERFACE_H_ */ Modified: haiku/trunk/src/kits/app/Message.cpp =================================================================== --- haiku/trunk/src/kits/app/Message.cpp 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/src/kits/app/Message.cpp 2010-07-08 14:54:25 UTC (rev 37431) @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009, Haiku Inc. All rights reserved. + * Copyright 2005-2010, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -333,6 +333,8 @@ fOriginal = NULL; fQueueLink = NULL; + fArchivingPointer = NULL; + if (initHeader) return _InitHeader(); @@ -394,6 +396,8 @@ free(fData); fData = NULL; + fArchivingPointer = NULL; + fFieldsAvailable = 0; fDataAvailable = 0; Modified: haiku/trunk/src/kits/support/Archivable.cpp =================================================================== --- haiku/trunk/src/kits/support/Archivable.cpp 2010-07-08 13:11:53 UTC (rev 37430) +++ haiku/trunk/src/kits/support/Archivable.cpp 2010-07-08 14:54:25 UTC (rev 37431) @@ -1,9 +1,10 @@ /* - * Copyright (c) 2001-2008, Haiku, Inc. + * Copyright (c) 2001-2010, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: * Erik Jaesler (erik@xxxxxxxxxxxxxx) + * Alex Wilson (yourpalal2@xxxxxxxxx) */ /*! BArchivable mix-in class defines the archiving protocol. @@ -29,10 +30,16 @@ #include <Roster.h> #include <String.h> +#include <binary_compatibility/Support.h> +#include "ArchivingManagers.h" + + using std::string; using std::vector; +using namespace BPrivate::Archiving; + const char* B_CLASS_FIELD = "class"; const char* B_ADD_ON_FIELD = "add_on"; const int32 FUNC_NAME_LEN = 1024; @@ -61,7 +68,7 @@ namespaceCount = strtoul(name, (char**)&name, 10); if (name[0] != '_') - return B_BAD_VALUE; + return B_BAD_VALUE; } else namespaceCount = name[0] - '0'; @@ -69,7 +76,7 @@ for (int i = 0; i < namespaceCount - 1; i++) { if (!isdigit(name[0])) - return B_BAD_VALUE; + return B_BAD_VALUE; int nameLength = strtoul(name, (char**)&name, 10); out.Append(name, nameLength); @@ -209,6 +216,10 @@ BArchivable::BArchivable(BMessage* from) { + if (BUnarchiver::IsArchiveManaged(from)) { + BUnarchiver::PrepareArchive(from); + BUnarchiver(from).RegisterArchivable(this); + } } @@ -225,6 +236,9 @@ return B_BAD_VALUE; } + if (BManagerBase::ArchiveManager(into)) + BArchiver(into).RegisterArchivable(this); + BString name; status_t status = demangle_class_name(typeid(*this).name(), name); if (status != B_OK) @@ -245,19 +259,274 @@ status_t BArchivable::Perform(perform_code d, void* arg) { - // TODO: Check against original - return B_ERROR; + switch (d) { + case PERFORM_CODE_ALL_UNARCHIVED: + { + perform_data_all_unarchived* data = + (perform_data_all_unarchived*)arg; + + data->return_value = BArchivable::AllUnarchived(data->archive); + return B_OK; + } + + case PERFORM_CODE_ALL_ARCHIVED: + { + perform_data_all_archived* data = + (perform_data_all_archived*)arg; + + data->return_value = BArchivable::AllArchived(data->archive); + return B_OK; + } + } + return B_NAME_NOT_FOUND; } -void BArchivable::_ReservedArchivable1() {} -void BArchivable::_ReservedArchivable2() {} -void BArchivable::_ReservedArchivable3() {} +status_t +BArchivable::AllUnarchived(const BMessage* archive) +{ + return B_OK; +} +status_t +BArchivable::AllArchived(BMessage* archive) const +{ + return B_OK; +} + // #pragma mark - +BArchiver::BArchiver(BMessage* archive) + : + fManager(BManagerBase::ArchiveManager(archive)), + fArchive(archive), + fFinished(false) +{ + if (!fManager) + fManager = new BArchiveManager(this); +} + +BArchiver::~BArchiver() +{ + if (!fFinished) + fManager->ArchiverLeaving(this); +} + + +status_t +BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep) +{ + int32 token; + status_t err = GetTokenForArchivable(archivable, token, deep); + + if (err != B_OK) + return err; + + return fArchive->AddInt32(name, token); +} + + +status_t +BArchiver::GetTokenForArchivable(BArchivable* archivable, + int32& _token, bool deep) +{ + status_t err = B_OK; + + if (!IsArchived(archivable)) + err = fManager->ArchiveObject(archivable, deep); + + if (err == B_OK) + return fManager->GetTokenForArchivable(archivable, _token); + + return err; +} + + +bool +BArchiver::IsArchived(BArchivable* archivable) +{ + return fManager->IsArchived(archivable); +} + + +status_t +BArchiver::Finish() +{ + if (fFinished) + debugger("Finish() called multiple times on same BArchiver."); + + fFinished = true; + return fManager->ArchiverLeaving(this); +} + + +BMessage* +BArchiver::ArchiveMessage() const +{ + return fArchive; +} + + +void +BArchiver::RegisterArchivable(const BArchivable* archivable) +{ + fManager->RegisterArchivable(archivable); +} + + +// #pragma mark - + + +BUnarchiver::BUnarchiver(const BMessage* archive) + : + fManager(BManagerBase::UnarchiveManager(archive)), + fArchive(archive), + fFinished(false) +{ +} + + +BUnarchiver::~BUnarchiver() +{ + if (!fFinished && fManager) + fManager->UnarchiverLeaving(this); +} + + +status_t +BUnarchiver::GetArchivable(int32 token, BArchivable** archivable) +{ + _CallDebuggerIfManagerNull(); + + if (archivable == NULL) + return B_BAD_VALUE; + + return fManager->ArchivableForToken(archivable, token); +} + + +status_t +BUnarchiver::FindArchivable(const char* name, BArchivable** archivable) +{ + return FindArchivable(name, 0, archivable); +} + + +status_t +BUnarchiver::FindArchivable(const char* name, + int32 index, BArchivable** archivable) +{ + + int32 token; + status_t err = fArchive->FindInt32(name, index, &token); + if (err != B_OK) + return err; + + return GetArchivable(token, archivable); +} + + +status_t +BUnarchiver::EnsureUnarchived(const char* name, int32 index) +{ + BArchivable* dummy; + return FindArchivable(name, index, &dummy); +} + + +status_t +BUnarchiver::EnsureUnarchived(int32 token) +{ + BArchivable* dummy; + return GetArchivable(token, &dummy); +} + + +bool +BUnarchiver::IsInstantiated(int32 token) +{ + return fManager->IsInstantiated(token); +} + +bool +BUnarchiver::IsInstantiated(const char* field, int32 index) +{ + int32 token; + if (fArchive->FindInt32(field, index, &token) == B_OK) + return IsInstantiated(token); + return false; +} + +status_t +BUnarchiver::Finish() +{ + if (fFinished) + debugger("Finish() called multiple times on same BArchiver."); + + fFinished = true; + return fManager->UnarchiverLeaving(this); +} + + +const BMessage* +BUnarchiver::ArchiveMessage() const +{ + return fArchive; +} + + +bool +BUnarchiver::IsArchiveManaged(BMessage* archive) +{ + // managed child archives will return here + if (BManagerBase::ManagerPointer(archive)) + return true; + + // managed top level archives return here + int32 dummy; + if (archive->FindInt32(kArchiveCountField, &dummy) == B_OK) + return true; + + return false; +} + + +BMessage* +BUnarchiver::PrepareArchive(BMessage*& archive) +{ + // this check allows PrepareArchive to be + // called on new or old-style archives + if (BUnarchiver::IsArchiveManaged(archive)) { + BUnarchiveManager* manager = BManagerBase::UnarchiveManager(archive); + if (!manager) + manager = new BUnarchiveManager(archive); + manager->Acquire(); + } + return archive; +} + + +void +BUnarchiver::RegisterArchivable(BArchivable* archivable) +{ + _CallDebuggerIfManagerNull(); + fManager->RegisterArchivable(archivable); +} + + +void +BUnarchiver::_CallDebuggerIfManagerNull() +{ + if (!fManager) + debugger("BUnarchiver used with legacy or unprepared archive."); +} + + +// #pragma mark - + + BArchivable* instantiate_object(BMessage* archive, image_id* _id) { @@ -475,3 +744,61 @@ return find_instantiation_func(name, signature); } +// BArchivable binary compatability +#if __GNUC__ == 2 + +extern "C" status_t +_ReservedArchivable1__11BArchivable(BArchivable* archivable, + const BMessage* archive) +{ + // AllUnarchived + perform_data_all_unarchived performData; + performData.archive = archive; + + archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData); + return performData.return_value; +} + +extern "C" status_t +_ReservedArchivable2__11BArchivable(BArchivable* archivable, + BMessage* archive) +{ + // AllArchived + perform_data_all_archived performData; + performData.archive = archive; + + archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData); + return performData.return_value; +} + +#elif __GNUC__ > 2 + +extern "C" status_t +_ZN11BArchivable20_ReservedArchivable1Ev(BArchivable* archivable, + const BMessage* archive) +{ + // AllUnarchived + perform_data_all_unarchived performData; + performData.archive = archive; + + archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData); + return performData.return_value; +} + +extern "C" status_t +_ZN11BArchivable20_ReservedArchivable2Ev(BArchivable* archivable, + BMessage* archive) +{ + // AllArchived + perform_data_all_archived performData; + performData.archive = archive; + + archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData); + return performData.return_value; +} + +#endif // _GNUC__ > 2 + +void BArchivable::_ReservedArchivable3() {} + + Added: haiku/trunk/src/kits/support/ArchivingManagers.cpp =================================================================== --- haiku/trunk/src/kits/support/ArchivingManagers.cpp (rev 0) +++ haiku/trunk/src/kits/support/ArchivingManagers.cpp 2010-07-08 14:54:25 UTC (rev 37431) @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2010, Haiku, Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alex Wilson (yourpalal2@xxxxxxxxx) + */ + + +#include <syslog.h> +#include <typeinfo> + +#include "ArchivingManagers.h" + + +namespace BPrivate { +namespace Archiving { + const char* kArchiveCountField = "_managed_archive_count"; + const char* kArchivableField = "_managed_archivable"; + const char* kTokenField = "_managed_token"; +} } + + +using namespace BPrivate::Archiving; + + +BArchiveManager* +BManagerBase::ArchiveManager(const BMessage* archive) +{ + BManagerBase* manager = ManagerPointer(archive); + if (!manager) + return NULL; + + if (manager->fType == ARCHIVE_MANAGER) + return static_cast<BArchiveManager*>(manager); + + debugger("Overlapping managed unarchive/archive sessions."); + return NULL; +} + + +BUnarchiveManager* +BManagerBase::UnarchiveManager(const BMessage* archive) +{ + BManagerBase* manager = ManagerPointer(archive); + if (!manager) + return NULL; + + if (manager->fType == UNARCHIVE_MANAGER) + return static_cast<BUnarchiveManager*>(manager); + + debugger("More calls to BUnarchiver::PrepareMessage()" + " than BUnarchivers created."); + + return NULL; +} + + +// #pragma mark - + + +struct BArchiveManager::ArchiveInfo { + ArchiveInfo() + : + token(-1), + archive(NULL) + { + } + + + ~ArchiveInfo() + { + delete archive; + } + + + int32 token; + BMessage* archive; +}; + + +BArchiveManager::BArchiveManager(const BArchiver* creator) + : + BManagerBase(creator->ArchiveMessage(), BManagerBase::ARCHIVE_MANAGER), + fTokenMap(), + fCreator(creator) +{ +} + + +BArchiveManager::~BArchiveManager() +{ + fTopLevelArchive->AddInt32(kArchiveCountField, fTokenMap.size()); +} + + +status_t +BArchiveManager::GetTokenForArchivable(BArchivable* archivable, int32& _token) +{ + if (!archivable) { + _token = -42; + return B_OK; + } + + TokenMap::iterator it = fTokenMap.find(archivable); + + if (it == fTokenMap.end()) + return B_ENTRY_NOT_FOUND; + + _token = it->second.token; + return B_OK; +} + +status_t +BArchiveManager::ArchiveObject(BArchivable* archivable, bool deep) +{ + if (IsArchived(archivable)){ + debugger("BArchivable requested to be archived" + " was previously archived."); + } + + ArchiveInfo& info = fTokenMap[archivable]; + + info.archive = new BMessage(); + info.token = fTokenMap.size() - 1; + + MarkArchive(info.archive); + status_t err = archivable->Archive(info.archive, deep); + + if (err != B_OK) + fTokenMap.erase(archivable); + // info.archive gets deleted here + + return err; +} + + +bool +BArchiveManager::IsArchived(BArchivable* archivable) +{ + if (!archivable) + return true; + + return (fTokenMap.find(archivable) != fTokenMap.end()); +} + + +status_t +BArchiveManager::ArchiverLeaving(const BArchiver* archiver) +{ + if (archiver == fCreator) { + + // first, we must sort the objects into the order they were archived in + typedef std::pair<BMessage*, const BArchivable*> archivePair ; + archivePair pairs[fTokenMap.size()]; + + for(TokenMap::iterator it = fTokenMap.begin(), end = fTokenMap.end(); + it != end; it++) { + + ArchiveInfo& info = it->second; + pairs[info.token].first = info.archive; + pairs[info.token].second = it->first; + + // make sure fTopLevelArchive isn't deleted + if (info.archive == fTopLevelArchive) + info.archive = NULL; + } + + status_t err = B_ERROR; + int32 count = fTokenMap.size(); + for (int32 i = 0; i < count; i++) { + + const archivePair& pair = pairs[i]; + err = pair.second->AllArchived(pair.first); + + if (err == B_OK && i > 0) { + err = fTopLevelArchive->AddMessage(kArchivableField, + pair.first); + } + + if (err != B_OK) { + syslog(LOG_ERR, "AllArchived failed for object of type %s.", + typeid(*pairs[i].second).name()); + break; + } + } + + delete this; + return err; + } + + return B_OK; +} + + +void +BArchiveManager::RegisterArchivable(const BArchivable* archivable) +{ + if (fTokenMap.size() == 0) { + ArchiveInfo& info = fTokenMap[archivable]; + info.archive = fTopLevelArchive; + info.token = 0; + } +} + + +// #pragma mark - + + +struct BUnarchiveManager::ArchiveInfo { + ArchiveInfo() + : + archivable(NULL), + archive() + { + } + + bool + operator<(const ArchiveInfo& other) + { + return archivable < other.archivable; + } + + BArchivable* archivable; + BMessage archive; +}; + + +// #pragma mark - + +BUnarchiveManager::BUnarchiveManager(BMessage* archive) + : + BManagerBase(archive, BManagerBase::UNARCHIVE_MANAGER), + fObjects(NULL), + fObjectCount(0), + fTokenInProgress(0), + fRefCount(0) +{ + archive->FindInt32(kArchiveCountField, &fObjectCount); + fObjects = new ArchiveInfo[fObjectCount]; + + // fObjects[0] is a placeholder for the object that started + // this unarchiving session. + for (int32 i = 0; i < fObjectCount - 1; i++) { + BMessage* into = &fObjects[i + 1].archive; + status_t err = archive->FindMessage(kArchivableField, i, into); + MarkArchive(into); + + if (err != B_OK) + syslog(LOG_ERR, "Failed to find managed archivable"); + } +} + + +BUnarchiveManager::~BUnarchiveManager() +{ + delete[] fObjects; +} + + +status_t +BUnarchiveManager::ArchivableForToken(BArchivable** _archivable, int32 token) +{ + if (!_archivable || token > fObjectCount) + return B_BAD_VALUE; + + if (token < 0) { + *_archivable = NULL; + return B_OK; + } + + status_t err = B_OK; + if (!fObjects[token].archivable) { + if (fRefCount > 0) + err = _InstantiateObjectForToken(token); + else { + syslog(LOG_ERR, "Object requested from AllUnarchived()" + " was not previously instantiated"); + err = B_ERROR; + } + } + + *_archivable = fObjects[token].archivable; + return err; +} + + +bool +BUnarchiveManager::IsInstantiated(int32 token) +{ + if (token < 0 || token >= fObjectCount) + return false; + return fObjects[token].archivable; +} + + +void +BUnarchiveManager::RegisterArchivable(BArchivable* archivable) +{ + if (!archivable) + debugger("Cannot register NULL pointer"); [... truncated: 224 lines follow ...]