diff --git a/headers/private/storage/mime/Database.h b/headers/private/storage/mime/Database.h index d59d858079..60674a6b3d 100644 --- a/headers/private/storage/mime/Database.h +++ b/headers/private/storage/mime/Database.h @@ -1,4 +1,11 @@ -// mime/Database.h +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Database.cpp + Database class declarations +*/ #ifndef _MIME_DATABASE_H #define _MIME_DATABASE_H diff --git a/headers/private/storage/mime/InstalledTypes.h b/headers/private/storage/mime/InstalledTypes.h index d00fe2b3f5..c2a0654277 100644 --- a/headers/private/storage/mime/InstalledTypes.h +++ b/headers/private/storage/mime/InstalledTypes.h @@ -1,4 +1,11 @@ -// mime/InstalledTypes.h +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file InstalledTypes.h + InstalledTypes class declarations +*/ #ifndef _MIME_INSTALLED_TYPES_H #define _MIME_INSTALLED_TYPES_H @@ -24,15 +31,29 @@ public: status_t GetInstalledTypes(const char *supertype, BMessage *types); status_t GetInstalledSupertypes(BMessage *types); - void AddType(const char *type); - void AddSupertype(const char *type); - void AddSubtype(const char *super, const char *sub); + status_t AddType(const char *type); + status_t RemoveType(const char *type); private: - void FillMessageWithTypes(BMessage *msg); + status_t AddSupertype(const char *super, std::map::iterator &i); + status_t AddSubtype(const char *super, const char *sub); + status_t AddSubtype(Supertype &super, const char *sub); + + status_t RemoveSupertype(const char *super); + status_t RemoveSubtype(const char *super, const char *sub); + + void Unset(); + void ClearCachedMessages(); + + status_t CreateMessageWithTypes(BMessage **result) const; + status_t CreateMessageWithSupertypes(BMessage **result) const; void FillMessageWithSupertypes(BMessage *msg); + + status_t BuildInstalledTypesList(); std::map fSupertypes; BMessage *fCachedMessage; + BMessage *fCachedSupertypesMessage; + bool fHaveDoneFullBuild; }; } // namespace Mime diff --git a/headers/private/storage/mime/Supertype.h b/headers/private/storage/mime/Supertype.h index 8479a9b333..8d691e5d2b 100644 --- a/headers/private/storage/mime/Supertype.h +++ b/headers/private/storage/mime/Supertype.h @@ -1,4 +1,11 @@ -// mime/Supertype.h +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Supertype.h + Supertype class declarations +*/ #ifndef _MIME_SUPERTYPE_H #define _MIME_SUPERTYPE_H @@ -16,15 +23,24 @@ namespace Mime { class Supertype { public: - Supertype(const char *super); + Supertype(const char *super = NULL); ~Supertype(); + + status_t GetInstalledSubtypes(BMessage *types); - void AddSubtype(const char *sub); - void FillMessageWithTypes(BMessage *msg); + status_t AddSubtype(const char *sub); + status_t RemoveSubtype(const char *sub); + + void SetName(const char *super); + const char* GetName(); + + status_t FillMessageWithTypes(BMessage &msg) const; private: + status_t CreateMessageWithTypes(BMessage **result) const; + std::set fSubtypes; BMessage *fCachedMessage; - std::string fType; + std::string fName; }; } // namespace Mime diff --git a/headers/private/storage/mime/database_access.h b/headers/private/storage/mime/database_access.h index 869002c517..9f0120817f 100644 --- a/headers/private/storage/mime/database_access.h +++ b/headers/private/storage/mime/database_access.h @@ -1,4 +1,11 @@ -// mime/database_access.h +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file database_access.h + Mime database atomic read function declarations +*/ #ifndef _MIME_DATABASE_ACCESS_H #define _MIME_DATABASE_ACCESS_H diff --git a/headers/private/storage/mime/database_support.h b/headers/private/storage/mime/database_support.h index 2910ff6173..ae79261341 100644 --- a/headers/private/storage/mime/database_support.h +++ b/headers/private/storage/mime/database_support.h @@ -1,4 +1,11 @@ -// mime/database_support.h +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file database_support.h + Private mime database function and constant declarations +*/ #ifndef _MIME_DATABASE_SUPPORT_H #define _MIME_DATABASE_SUPPORT_H @@ -49,6 +56,10 @@ extern const int32 kPreferredAppType; extern const int32 kSnifferRuleType; extern const int32 kSupportedTypesType; +// Message fields +extern const char *kTypesField; +extern const char *kSupertypesField; + std::string type_to_filename(const char *type); status_t open_type(const char *type, BNode *result); diff --git a/src/kits/storage/mime/Database.cpp b/src/kits/storage/mime/Database.cpp index b70d8edfc7..eaf4580d17 100644 --- a/src/kits/storage/mime/Database.cpp +++ b/src/kits/storage/mime/Database.cpp @@ -1,4 +1,11 @@ -// mime/Database.cpp +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Database.cpp + Database class implementation +*/ #include #include @@ -103,6 +110,8 @@ Database::Install(const char *type) bool didCreate = false; BNode node; err = open_or_create_type(type, &node, &didCreate); + if (didCreate) + fInstalledTypes.AddType(type); } } return err; @@ -124,8 +133,10 @@ Database::Delete(const char *type) err = entry.SetTo(type_to_filename(type).c_str()); if (!err) err = entry.Remove(); - if (!err) + if (!err) { + fInstalledTypes.RemoveType(type); err = SendDeleteNotification(type); + } return err; } @@ -288,8 +299,8 @@ Database::SetIconForType(const char *type, const char *fileType, const void *dat ssize_t err = (type && data) ? B_OK : B_BAD_VALUE; std::string attr; - int32 attrType; - int32 attrSize; + int32 attrType = 0; + size_t attrSize = 0; // Figure out what kind of data we *should* have if (!err) { @@ -329,7 +340,7 @@ Database::SetIconForType(const char *type, const char *fileType, const void *dat if (!err) err = node.WriteAttr(attr.c_str(), attrType, 0, data, attrSize); if (err >= 0) - err = err == attrSize ? B_OK : B_FILE_ERROR; + err = err == (ssize_t)attrSize ? B_OK : B_FILE_ERROR; return err; } @@ -374,22 +385,19 @@ Database::SetSupportedTypes(const char *type, const BMessage *types) status_t Database::GetInstalledSupertypes(BMessage *supertypes) { -// return fInstalledTypes.GetInstalledSupertypes(supertypes); - return B_ERROR; + return fInstalledTypes.GetInstalledSupertypes(supertypes); } status_t Database::GetInstalledTypes(BMessage *types) { -// return fInstalledTypes.GetInstalledTypes(types); - return B_ERROR; + return fInstalledTypes.GetInstalledTypes(types); } status_t Database::GetInstalledTypes(const char *supertype, BMessage *subtypes) { -// return fInstalledTypes.GetInstalledTypes(supertype, subtypes); - return B_ERROR; + return fInstalledTypes.GetInstalledTypes(supertype, subtypes); } status_t diff --git a/src/kits/storage/mime/InstalledTypes.cpp b/src/kits/storage/mime/InstalledTypes.cpp index aeca70e028..9b7b04077b 100644 --- a/src/kits/storage/mime/InstalledTypes.cpp +++ b/src/kits/storage/mime/InstalledTypes.cpp @@ -1,9 +1,22 @@ -// mime/InstalledTypes.cpp +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file InstalledTypes.cpp + InstalledTypes class implementation +*/ #include "mime/InstalledTypes.h" +#include +#include #include +#include +#include +#include +#include #include #define DBG(x) x @@ -14,195 +27,350 @@ namespace BPrivate { namespace Storage { namespace Mime { +/*! + \class InstalledTypes + \brief Installed types information for the entire database +*/ + +// Constructor +//! Constructs a new InstalledTypes object InstalledTypes::InstalledTypes() : fCachedMessage(NULL) + , fCachedSupertypesMessage(NULL) + , fHaveDoneFullBuild(false) { } +// Destructor +//! Destroys the InstalledTypes object InstalledTypes::~InstalledTypes() { + delete fCachedSupertypesMessage; delete fCachedMessage; } -/* -MimeDatabaseBackend::MimeDatabaseBackend() - : fCachedInstalledTypesMessage(NULL) - , fCachedInstalledSupertypesMessage(NULL) +// GetInstalledTypes +/*! \brief Returns a list of all currently installed types in the + pre-allocated \c BMessage pointed to by \c types. + + See \c BMimeType::GetInstalledTypes(BMessage*) for more information. +*/ +status_t +InstalledTypes::GetInstalledTypes(BMessage *types) { -} - -MimeDatabaseBackend::~MimeDatabaseBackend() -{ - delete fCachedInstalledTypesMessage; - delete fCachedInstalledSupertypesMessage; -} - -status_t -MimeDatabaseBackend::GetInstalledTypes(BMessage *types) -{ - DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(1)\n")); status_t err = types ? B_OK : B_BAD_VALUE; + // See if we need to do our initial build still + if (!err && !fHaveDoneFullBuild) { + err = BuildInstalledTypesList(); + } + // See if we need to fill up a new message + if (!err && !fCachedMessage) { + err = CreateMessageWithTypes(&fCachedMessage); + } + // If we get this far, there a cached message waiting if (!err) { - if (!fCachedInstalledTypesMessage) { - if (fInstalledTypes.begin() == fInstalledTypes.end()) - err = BuildInstalledTypesList(&fCachedInstalledTypesMessage); - else - err = BuildInstalledTypesMessage(&fCachedInstalledTypesMessage); + *types = *fCachedMessage; + } + return err; +} + +// GetInstalledTypes +/*! \brief Returns a list of all currently installed types of the given + supertype in the pre-allocated \c BMessage pointed to by \c types. + + See \c BMimeType::GetInstalledTypes(const char*, BMessage*) for more + information. +*/ +status_t +InstalledTypes::GetInstalledTypes(const char *supertype, BMessage *types) +{ + status_t err = supertype && types ? B_OK : B_BAD_VALUE; + // Verify the supertype is valid *and* is a supertype + BMimeType mime; + BMimeType super; + // Make sure the supertype is valid + if (!err) + err = mime.SetTo(supertype); + // Make sure it's really a supertype + if (!err && !mime.IsSupertypeOnly()) + err = B_BAD_VALUE; + // See if we need to do our initial build still + if (!err && !fHaveDoneFullBuild) { + err = BuildInstalledTypesList(); + } + // Ask the appropriate supertype for its list + if (!err) { + std::map::iterator i = fSupertypes.find(supertype); + if (i != fSupertypes.end()) + err = i->second.GetInstalledSubtypes(types); + else + err = B_NAME_NOT_FOUND; + } + return err; +} + +// GetInstalledSupertypes +/*! \brief Returns a list of all currently installed supertypes in the + pre-allocated \c BMessage pointed to by \c types. + + See \c BMimeType::GetInstalledSupertypes() for more information. +*/ +status_t +InstalledTypes::GetInstalledSupertypes(BMessage *types) +{ + status_t err = types ? B_OK : B_BAD_VALUE; + // See if we need to do our initial build still + if (!err && !fHaveDoneFullBuild) { + err = BuildInstalledTypesList(); + } + // See if we need to fill up a new message + if (!err && !fCachedSupertypesMessage) { + err = CreateMessageWithSupertypes(&fCachedSupertypesMessage); + } + // If we get this far, there's a cached message waiting + if (!err) { + *types = *fCachedSupertypesMessage; + } + return err; +} + +// AddType +/*! \brief Adds the given type to the appropriate lists of installed types. + + If cached messages exist, the type is simply appended to the end of + the current type list. +*/ +status_t +InstalledTypes::AddType(const char *type) +{ + status_t err; + if (fHaveDoneFullBuild) { + BMimeType mime(type); + BMimeType super; + err = type ? mime.InitCheck() : B_BAD_VALUE; + if (!err) { + // Find the / in the string, if one exists + uint i; + size_t len = strlen(type); + for (i = 0; i < len; i++) { + if (type[i] == '/') + break; + } + if (i == len) { + // Supertype only + std::map::iterator i; + err = AddSupertype(type, i); + } else { + // Copy the supertype + char super[B_PATH_NAME_LENGTH+1]; + strncpy(super, type, i); + super[i] = 0; + + // Get a pointer to the subtype + const char *sub = &(type[i+1]); + + // Add the subtype (which will add the supertype if necessary) + err = AddSubtype(super, sub); + } } - *types = *fCachedInstalledTypesMessage; + } else { + err = B_OK; } - DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(1) done\n")); - return err; + return err; } +// RemoveType +/*! \brief Removes the given type from the appropriate installed types lists. + + Any corresponding cached messages are invalidated. +*/ status_t -MimeDatabaseBackend::GetInstalledTypes(const char *supertype, BMessage *types) +InstalledTypes::RemoveType(const char *type) { - DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(2)\n")); - status_t err = supertype && types && BMimeType::IsValid(supertype) ? B_OK : B_BAD_VALUE; - - // Types are not case sensitive, so we always use lowercase - char lowertype[B_PATH_NAME_LENGTH+1]; - BPrivate::Storage::to_lower(supertype, lowertype); - installed_subtypes_info *info; - - // See if we need to build the main list - if (!err && fSupertypesMap.empty()) - err = BuildInstalledTypesList(); - // See if the supertype even exists - if (!err) { - std::map::iterator i = fSupertypesMap.find(supertype); - err = i != fSupertypesMap.end() ? B_OK : B_BAD_VALUE; - if (!err) - info = &(i->second); - } - // Make sure there's a cached message waiting for us - if (!err && !info->cached_message) - err = BuildInstalledTypesMessage(info->subtypes, &(info->cached_message)); - // Copy the message into the result - if (!err) - *types = *info->cached_message; - DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(2) done\n")); - return err; -} - -status_t -MimeDatabaseBackend::GetInstalledSupertypes(BMessage *types) -{ - DBG(OUT("MimeDatabaseBackend::GetInstalledSupertypes()\n")); - status_t err = types ? B_OK : B_BAD_VALUE; - - // See if we need to build the main list - if (!err && fSupertypesMap.empty()) - err = BuildInstalledTypesList(); - // Make sure there's a cached message waiting for us - if (!err && !fCachedInstalledSupertypesMessage) - err = BuildInstalledSupertypesMessage(fSupertypesMap, &fCachedInstalledSupertypesMessage); - // Copy the message into the result - if (!err) - *types = *fCachedInstalledSupertypesMessage; - DBG(OUT("MimeDatabaseBackend::GetInstalledSupertypes() done\n")); - return err; -} - -status_t -MimeDatabaseBackend::GetSupportingApps(const char *type, BMessage *signatures) -{ - return B_ERROR; // not implemented -} - -void -MimeDatabaseBackend::InstallType(const char *type) -{ - DBG(OUT("MimeDatabaseBackend::InstallType()\n")); - if (fInstalledTypes.empty()) - return; - // Remove any cached messages - if (fCachedInstalledTypesMessage) { - delete fCachedInstalledTypesMessage; - fCachedInstalledTypesMessage = NULL; - } - if (fCachedInstalledSupertypesMessage) { - delete fCachedInstalledSupertypesMessage; - fCachedInstalledSupertypesMessage = NULL; - } - char lowertype[B_PATH_NAME_LENGTH+1]; - char supertype[B_PATH_NAME_LENGTH+1]; - Storage::to_lower(type, lowertype); - fInstalledTypes.insert(lowertype); - BMimeType mime(lowertype); - BMimeType super; - status_t err = mime.InitCheck(); - if (!err) - err = mime.GetSupertype(&super); - if (!err) { - Storage::to_lower(super.Type(), supertype); - installed_subtypes_info &info = fSupertypesMap[supertype]; - delete info.cached_message; - info.cached_message = NULL; - info.subtypes.insert(lowertype); - } - DBG(OUT("MimeDatabaseBackend::InstallType() done\n")); -} - -void -MimeDatabaseBackend::DeleteType(const char *type) -{ - if (fInstalledTypes.empty()) - return; - printf("fuCK\n"); - // Remove any cached messages - if (fCachedInstalledTypesMessage) { - delete fCachedInstalledTypesMessage; - fCachedInstalledTypesMessage = NULL; - } - printf("fuCK\n"); - if (fCachedInstalledSupertypesMessage) { - delete fCachedInstalledSupertypesMessage; - fCachedInstalledSupertypesMessage = NULL; - } - printf("fuCK\n"); - char lowertype[B_PATH_NAME_LENGTH+1]; - char supertype[B_PATH_NAME_LENGTH+1]; - printf("fuCK\n"); - Storage::to_lower(type, lowertype); - fInstalledTypes.erase(lowertype); - printf("fuCK\n"); - BMimeType mime(lowertype); - BMimeType super; - printf("fuCK\n"); - status_t err = mime.InitCheck(); - printf("fuCK\n"); - if (!err) - err = mime.GetSupertype(&super); - printf("fuCK\n"); - if (!err) { - Storage::to_lower(super.Type(), supertype); - installed_subtypes_info &info = fSupertypesMap[supertype]; - printf("fuCK\n"); - delete info.cached_message; - printf("fuCK\n"); - info.cached_message = NULL; - printf("fuCK\n"); - info.subtypes.erase(lowertype); - } - printf("fuCK\n"); -} - -// BuildInstalledTypesList() -//! Builds an initial installed types list and (optionally) an installed types BMessage -status_t -MimeDatabaseBackend::BuildInstalledTypesList(BMessage **types) -{ - BMessage *msg; - if (types) { - *types = new BMessage; - msg = *types; + status_t err; + if (fHaveDoneFullBuild) { + BMimeType mime(type); + BMimeType super; + err = type ? mime.InitCheck() : B_BAD_VALUE; + if (!err) { + // Find the / in the string, if one exists + uint i; + size_t len = strlen(type); + for (i = 0; i < len; i++) { + if (type[i] == '/') + break; + } + if (i == len) { + // Supertype only + err = RemoveSupertype(type); + } else { + // Copy the supertype + char super[B_PATH_NAME_LENGTH+1]; + strncpy(super, type, i); + super[i] = 0; + + // Get a pointer to the subtype + const char *sub = &(type[i+1]); + + // Remove the subtype + err = RemoveSubtype(super, sub); + } + } } else - msg = NULL; + err = B_OK; + return err; +} +// AddSupertype +/*! \brief Adds the given supertype to the supertype map. + \return + - B_OK: success, even if the supertype already existed in the map + - "error code": failure +*/ +status_t +InstalledTypes::AddSupertype(const char *super, std::map::iterator &i) +{ + status_t err = super ? B_OK : B_BAD_VALUE; + if (!err) { + i = fSupertypes.find(super); + if (i == fSupertypes.end()) { + Supertype &supertype = fSupertypes[super]; + supertype.SetName(super); + if (fCachedMessage) + err = fCachedMessage->AddString(kTypesField, super); + if (!err && fCachedSupertypesMessage) + err = fCachedSupertypesMessage->AddString(kSupertypesField, super); + } + } + return err; +} + +// AddSubtype +/*! \brief Adds the given subtype to the given supertype's lists of installed types. + + If the supertype does not yet exist, it is created. + + \param super The supertype + \param sub The subtype (subtype only; no "supertype/subtype" types please) + \return + - B_OK: success + - B_NAME_IN_USE: The subtype already exists in the subtype list + - "error code": failure +*/ +status_t +InstalledTypes::AddSubtype(const char *super, const char *sub) +{ + status_t err = super && sub ? B_OK : B_BAD_VALUE; + if (!err) { + std::map::iterator i; + err = AddSupertype(super, i); + if (!err) + err = AddSubtype(i->second, sub); + } + return err; +} + +// AddSubtype +/*! \brief Adds the given subtype to the given supertype's lists of installed types. + + \param super The supertype object + \param sub The subtype (subtype only; no "supertype/subtype" types please) + \return + - B_OK: success + - B_NAME_IN_USE: The subtype already exists in the subtype list + - "error code": failure +*/ +status_t +InstalledTypes::AddSubtype(Supertype &super, const char *sub) +{ + status_t err = sub ? B_OK : B_BAD_VALUE; + if (!err) + err = super.AddSubtype(sub); + if (!err && fCachedMessage) { + char type[B_PATH_NAME_LENGTH+1]; + sprintf(type, "%s/%s", super.GetName(), sub); + err = fCachedMessage->AddString("types", type); + } + return err; +} + +// RemoveSupertype +/*! \brief Removes the given supertype and any corresponding subtypes. +*/ +status_t +InstalledTypes::RemoveSupertype(const char *super) +{ + status_t err = super ? B_OK : B_BAD_VALUE; + if (!err) + err = fSupertypes.erase(super) == 1 ? B_OK : B_NAME_NOT_FOUND; + if (!err) + ClearCachedMessages(); + return err; +} + +// RemoveSubtype +/*! \brief Removes the given subtype from the given supertype. +*/ +status_t +InstalledTypes::RemoveSubtype(const char *super, const char *sub) +{ + status_t err = super && sub ? B_OK : B_BAD_VALUE; + if (!err) { + std::map::iterator i = fSupertypes.find(super); + if (i != fSupertypes.end()) { + err = i->second.RemoveSubtype(sub); + if (!err) + ClearCachedMessages(); + } else + err = B_NAME_NOT_FOUND; + } + return err; + +} + +// Unset +// Clears any cached messages and empties the supertype map +void +InstalledTypes::Unset() +{ + ClearCachedMessages(); + fSupertypes.clear(); +} + +// ClearCachedMessages +//! Frees any cached messages and sets their pointers to NULL +void +InstalledTypes::ClearCachedMessages() +{ + delete fCachedSupertypesMessage; + delete fCachedMessage; + fCachedSupertypesMessage = NULL; + fCachedMessage = NULL; +} + +// BuildInstalledTypesList +/*! \brief Reads through the database and builds a complete set of installed types lists. + + An initial set of cached messages are also created. +*/ +status_t +InstalledTypes::BuildInstalledTypesList() +{ + status_t err = B_OK; + Unset(); + + // Create empty "cached messages" so proper messages + // will be built up as we add new types + try { + fCachedMessage = new BMessage(); + fCachedSupertypesMessage = new BMessage(); + } catch (std::bad_alloc) { + err = B_NO_MEMORY; + } + BDirectory root; - status_t err = root.SetTo(MimeDatabase::kDatabaseDir.c_str()); + if (!err) + err = root.SetTo(kDatabaseDir.c_str()); if (!err) { root.Rewind(); while (true) { @@ -223,12 +391,12 @@ MimeDatabaseBackend::BuildInstalledTypesList(BMessage **types) // Make sure our string is all lowercase BPrivate::Storage::to_lower(supertype); - // Add this supertype - fInstalledTypes.insert(supertype); - fSupertypesMap[supertype] = installed_subtypes_info(); - installed_subtypes_info &info = fSupertypesMap[supertype]; - if (msg) - msg->AddString("types", supertype); + // Add this supertype + std::map::iterator i; + if (AddSupertype(supertype, i) != B_OK) + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding supertype '%s': 0x%lx\n", + supertype, err)); + Supertype &supertypeRef = fSupertypes[supertype]; // Now iterate through this supertype directory and add // all of its subtypes @@ -246,167 +414,90 @@ MimeDatabaseBackend::BuildInstalledTypesList(BMessage **types) } else { // Get the subtype's name char subtype[B_PATH_NAME_LENGTH+1]; - char mimetype[B_PATH_NAME_LENGTH+1]; if (subEntry.GetName(subtype) == B_OK) { BPrivate::Storage::to_lower(subtype); - sprintf(mimetype, "%s/%s", supertype, subtype); // Add the subtype - if (BMimeType::IsValid(mimetype)) { - fInstalledTypes.insert(mimetype); - info.subtypes.insert(mimetype); - if (msg) - msg->AddString("types", mimetype); - } + if (AddSubtype(supertypeRef, subtype) != B_OK) { + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding subtype '%s/%s': 0x%lx\n", + supertype, subtype, err)); + } } } } } else { - DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): " + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): " "Failed opening supertype directory '%s'\n", supertype)); } - } + } } } } else { - DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): " + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): " "Failed opening mime database directory '%s'\n", - MimeDatabase::kDatabaseDir.c_str())); + kDatabaseDir.c_str())); } + fHaveDoneFullBuild = true; return err; + } +// CreateMessageWithTypes +/*! \brief Allocates a new BMessage into the BMessage pointer pointed to by \c result + and fills it with a complete list of installed types. +*/ status_t -MimeDatabaseBackend::BuildInstalledTypesMessage(BMessage **result) +InstalledTypes::CreateMessageWithTypes(BMessage **result) const { status_t err = result ? B_OK : B_BAD_VALUE; // Alloc the message if (!err) { - *result = new BMessage; - if (!(*result)) + try { + *result = new BMessage(); + } catch (std::bad_alloc) { err = B_NO_MEMORY; - } - // Fill with types - if (!err) { - BMessage &msg = **result; - std::set::const_iterator i; - for (i = fInstalledTypes.begin(); i != fInstalledTypes.end(); i++) - msg.AddString("types", (*i).c_str()); - } - return err; -} - -status_t -MimeDatabaseBackend::BuildInstalledTypesMessage(const std::set &set, BMessage **result) -{ - status_t err = result ? B_OK : B_BAD_VALUE; - // Alloc the message - if (!err) { - *result = new BMessage; - if (!(*result)) - err = B_NO_MEMORY; - } - // Fill with types - if (!err) { - BMessage &msg = **result; - std::set::const_iterator i; - for (i = set.begin(); i != set.end(); i++) - msg.AddString("types", (*i).c_str()); - } - return err; -} - -status_t -MimeDatabaseBackend::BuildInstalledSupertypesMessage(const std::map &map, BMessage **result) -{ - status_t err = result ? B_OK : B_BAD_VALUE; - // Alloc the message - if (!err) { - *result = new BMessage; - if (!(*result)) - err = B_NO_MEMORY; - } - // Fill with types - if (!err) { - BMessage &msg = **result; - std::map::const_iterator i; - for (i = map.begin(); i != map.end(); i++) - msg.AddString("super_types", (i->first).c_str()); - } - return err; -} - - -status_t -MimeDatabaseBackend::BuildInstalledTypesList(const char *supertype, BMessage **types) -{ - return B_ERROR; - // I'm not going to work on this function anymore until we - // get to optimization, as BuildInstalledTypesList(Bmessage**) - // handles this already (just not as efficiently if we only - // want to build the types for a single supertype). I have - // no idea if this function works, as I've never tried it. - - BMessage *msg; - if (types) { - *types = new BMessage; - msg = *types; - } else - msg = NULL; - - status_t err = supertype && BMimeType::IsValid(supertype) ? B_OK : B_BAD_VALUE; - - // Check that this entry is both a directory and a valid MIME string - if (!err) - { - // Make sure our string is all lowercase - BPrivate::Storage::to_lower(supertype); - - // Clear any previous subtype info struct - fSupertypesMap[supertype] = installed_subtypes_info(); - installed_subtypes_info &info = fSupertypesMap[supertype]; - - // Iterate through the supertype directory and add - // all of its subtypes - BDirectory super; - if (super.SetTo((MimeDatabase::kDatabaseDir + supertype).c_str()) == B_OK) { - super.Rewind(); - while (true) { - BEntry entry; - err = super.GetNextEntry(&entry); - if (err) { - // If we've come to the end of list, it's not an error - if (err == B_ENTRY_NOT_FOUND) - err = B_OK; - break; - } else { - // Get the subtype's name - char subtype[B_PATH_NAME_LENGTH+1]; - char mimetype[B_PATH_NAME_LENGTH+1]; - if (entry.GetName(subtype) == B_OK) { - BPrivate::Storage::to_lower(subtype); - sprintf(mimetype, "%s/%s", supertype, subtype); - - // Add the subtype - if (BMimeType::IsValid(mimetype)) { - fInstalledTypes.insert(mimetype); - info.subtypes.insert(mimetype); - if (msg) - msg->AddString("types", mimetype); - } - } - } - } - } else { - DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): " - "Failed opening supertype directory '%s'\n", - supertype)); } } + // Fill with types + if (!err) { + BMessage &msg = **result; + std::map::const_iterator i; + for (i = fSupertypes.begin(); i != fSupertypes.end() && !err; i++) { + err = msg.AddString(kTypesField, i->first.c_str()); + if (!err) + err = i->second.FillMessageWithTypes(msg); + } + } + return err; } -*/ +// CreateMessageWithSupertypes +/*! \brief Allocates a new BMessage into the BMessage pointer pointed to by \c result + and fills it with a complete list of installed supertypes. +*/ +status_t +InstalledTypes::CreateMessageWithSupertypes(BMessage **result) const +{ + status_t err = result ? B_OK : B_BAD_VALUE; + // Alloc the message + if (!err) { + try { + *result = new BMessage(); + } catch (std::bad_alloc) { + err = B_NO_MEMORY; + } + } + // Fill with types + if (!err) { + BMessage &msg = **result; + std::map::const_iterator i; + for (i = fSupertypes.begin(); i != fSupertypes.end() && !err; i++) { + err = msg.AddString(kSupertypesField, i->first.c_str()); + } + } + return err; +} } // namespace Mime } // namespace Storage diff --git a/src/kits/storage/mime/Supertype.cpp b/src/kits/storage/mime/Supertype.cpp index 610ca15f42..ff3a807664 100644 --- a/src/kits/storage/mime/Supertype.cpp +++ b/src/kits/storage/mime/Supertype.cpp @@ -1,12 +1,20 @@ -// mime/Supertype.cpp +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Supertype.cpp + Supertype class implementation +*/ #include "mime/Supertype.h" #include +#include +#include #include - #define DBG(x) x //#define DBG(x) #define OUT printf @@ -15,17 +23,145 @@ namespace BPrivate { namespace Storage { namespace Mime { +/*! + \class Supertype + \brief Installed types information for a single supertype +*/ + +// Constructor +//! Constructs a new Supertype object Supertype::Supertype(const char *super) : fCachedMessage(NULL) - , fType(super) + , fName(super ? super : "") { } +// Destructor +//! Destroys the Supertype object Supertype::~Supertype() { delete fCachedMessage; } +// GetInstalledSubtypes +/*! \brief Returns a list of the installeds subtypes for this supertype + in the pre-allocated \c BMessage pointed to by \c types. +*/ +status_t +Supertype::GetInstalledSubtypes(BMessage *types) +{ + status_t err = types ? B_OK : B_BAD_VALUE; + // See if we need to fill up a new message + if (!err && !fCachedMessage) { + err = CreateMessageWithTypes(&fCachedMessage); + } + // If we get this far, there's a cached message waiting + if (!err) { + *types = *fCachedMessage; + } + return err; +} + +// AddSubtype +/*! \brief Adds the given subtype to the subtype list and the cached message, + if one exists. + \param sub The subtype to add (do not include the supertype) + \return + - B_OK: success + - B_NAME_IN_USE: The subtype already exists in the subtype list + - "error code": failure +*/ +status_t +Supertype::AddSubtype(const char *sub) +{ + status_t err = sub ? B_OK : B_BAD_VALUE; + if (!err) + err = fSubtypes.insert(sub).second ? B_OK : B_NAME_IN_USE; + if (!err && fCachedMessage) { + char type[B_PATH_NAME_LENGTH+1]; + sprintf(type, "%s/%s", fName.c_str(), sub); + err = fCachedMessage->AddString("types", type); + } + return err; +} + +// RemoveSubtype +/*! \brief Removes the given subtype from the subtype list and invalidates the + cached message, if one exists. + \param sub The subtype to remove (do not include the supertype) +*/ +status_t +Supertype::RemoveSubtype(const char *sub) +{ + status_t err = sub ? B_OK : B_BAD_VALUE; + if (!err) + err = fSubtypes.erase(sub) == 1 ? B_OK : B_NAME_NOT_FOUND; + if (!err && fCachedMessage) { + delete fCachedMessage; + fCachedMessage = NULL; + } + return err; +} + +// SetName +//! Sets the supertype's name +void +Supertype::SetName(const char *super) +{ + if (super) + fName = super; +} + +// GetName +//! Returns the supertype's name +const char* +Supertype::GetName() +{ + return fName.c_str(); +} + +// FillMessageWithTypes +//! Adds the supertype's subtypes to the given message +/*! Each subtype is added as another item in the message's \c Mime::kTypesField + field. The complete type ("supertype/subtype") is added. The supertype itself + is not added to the message. +*/ +status_t +Supertype::FillMessageWithTypes(BMessage &msg) const +{ + status_t err = B_OK; + std::set::const_iterator i; + for (i = fSubtypes.begin(); i != fSubtypes.end() && !err; i++) { + char type[B_PATH_NAME_LENGTH+1]; + sprintf(type, "%s/%s", fName.c_str(), (*i).c_str()); + err = msg.AddString(kTypesField, type); + } + return err; +} + +// CreateMessageWithTypes +/*! \brief Allocates a new BMessage into the BMessage pointer pointed to by \c result + and fills it with the supertype's subtypes. + + See \c Supertype::FillMessageWithTypes() for more information. +*/ +status_t +Supertype::CreateMessageWithTypes(BMessage **result) const +{ + status_t err = result ? B_OK : B_BAD_VALUE; + // Alloc the message + if (!err) { + try { + *result = new BMessage(); + } catch (std::bad_alloc) { + err = B_NO_MEMORY; + } + } + // Fill with types + if (!err) + err = FillMessageWithTypes(**result); + return err; +} } // namespace Mime } // namespace Storage diff --git a/src/kits/storage/mime/database_access.cpp b/src/kits/storage/mime/database_access.cpp index ec5c386fe0..a30c6ea821 100644 --- a/src/kits/storage/mime/database_access.cpp +++ b/src/kits/storage/mime/database_access.cpp @@ -1,4 +1,11 @@ -// mime/Database.cpp +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file database_access.cpp + Mime database atomic read functions +*/ #include #include @@ -202,10 +209,9 @@ get_icon_for_type(const char *type, const char *fileType, BBitmap *icon, attr_info info; ssize_t err; BNode node; - uint32 attrType; - size_t attrSize; + uint32 attrType = 0; + ssize_t attrSize = 0; BRect bounds; - char *buffer; err = type && icon ? B_OK : B_BAD_VALUE; @@ -249,7 +255,6 @@ get_icon_for_type(const char *type, const char *fileType, BBitmap *icon, if (!err) { bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); char *buffer = NULL; - ssize_t read; if (otherColorSpace) { // other color space than stored in attribute buffer = new(nothrow) char[attrSize]; @@ -376,7 +381,7 @@ get_icon_data(const BBitmap *icon, icon_size which, void **data, int32 *dataSize // Set each pixel individually, since SetBits() for B_RGB32 takes // 24-bit rgb pixel data... char *bgra = (char*)icon->Bits(); - for (uint32 i = 0; i*4+3 < icon->BitsLength(); bgra += 4, i++) { + for (int32 i = 0; i*4+3 < icon->BitsLength(); bgra += 4, i++) { char rgb[3]; rgb[0] = bgra[2]; // red rgb[1] = bgra[1]; // green diff --git a/src/kits/storage/mime/database_support.cpp b/src/kits/storage/mime/database_support.cpp index b0738df1a9..a6e400aefa 100644 --- a/src/kits/storage/mime/database_support.cpp +++ b/src/kits/storage/mime/database_support.cpp @@ -1,4 +1,11 @@ -// database_support.cpp +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file database_support.cpp + Private mime database functions and constants +*/ #include #include @@ -68,6 +75,9 @@ const int32 kPreferredAppType = 'MSIG'; const int32 kSnifferRuleType = B_STRING_TYPE; const int32 kSupportedTypesType = B_MESSAGE_TYPE; +// Message fields +const char *kTypesField = "types"; +const char *kSupertypesField = "super_types"; // type_to_filename @@ -119,7 +129,7 @@ open_or_create_type(const char *type, BNode *result, bool *didCreate) // Figure out what type of node we need to create // + Supertype == directory // + Non-supertype == file - int32 pos = typeLower.find_first_of('/'); + uint32 pos = typeLower.find_first_of('/'); if (pos == std::string::npos) { // Supertype == directory BDirectory parent(kDatabaseDir.c_str()); @@ -237,7 +247,7 @@ write_mime_attr(const char *type, const char *attr, const void *data, if (bytes < B_OK) err = bytes; else - err = (bytes != len ? B_FILE_ERROR : B_OK); + err = (bytes != (ssize_t)len ? B_FILE_ERROR : B_OK); } return err; } @@ -270,7 +280,7 @@ write_mime_attr_message(const char *type, const char *attr, const BMessage *msg, if (!err) err = node.WriteAttr(attr, B_MESSAGE_TYPE, 0, data.Buffer(), data.BufferLength()); if (err >= 0) - err = err == data.BufferLength() ? B_OK : B_FILE_ERROR; + err = err == (ssize_t)data.BufferLength() ? B_OK : B_FILE_ERROR; return err; }