BRepositoryCache: Add iteration, etc.
* Remove InitCheck() and the initializing constructor. * Rename PackageCount() to CountPackages(). * Use BOpenHashTable instead of HashMap for the internal PackageMap. * Allow multiple packages with the same name. Equally named packages are in a singly linked list after the first package with that name. * Add an Iterator inner class and a GetIterator() method, so one can now iterate through the packages in the repository.
This commit is contained in:
@@ -15,14 +15,18 @@
|
|||||||
namespace BPackageKit {
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
class BPackageInfo;
|
||||||
|
|
||||||
|
|
||||||
class BRepositoryCache {
|
class BRepositoryCache {
|
||||||
|
public:
|
||||||
|
class Iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BRepositoryCache();
|
BRepositoryCache();
|
||||||
BRepositoryCache(const BEntry& entry);
|
|
||||||
virtual ~BRepositoryCache();
|
virtual ~BRepositoryCache();
|
||||||
|
|
||||||
status_t SetTo(const BEntry& entry);
|
status_t SetTo(const BEntry& entry);
|
||||||
status_t InitCheck() const;
|
|
||||||
|
|
||||||
const BRepositoryInfo& Info() const;
|
const BRepositoryInfo& Info() const;
|
||||||
const BEntry& Entry() const;
|
const BEntry& Entry() const;
|
||||||
@@ -30,14 +34,19 @@ public:
|
|||||||
|
|
||||||
void SetIsUserSpecific(bool isUserSpecific);
|
void SetIsUserSpecific(bool isUserSpecific);
|
||||||
|
|
||||||
uint32 PackageCount() const;
|
uint32 CountPackages() const;
|
||||||
|
Iterator GetIterator() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct PackageInfo;
|
||||||
|
struct PackageInfoHashDefinition;
|
||||||
struct PackageMap;
|
struct PackageMap;
|
||||||
|
struct RepositoryContentHandler;
|
||||||
|
struct StandardErrorOutput;
|
||||||
|
|
||||||
|
friend class Iterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t fInitStatus;
|
|
||||||
|
|
||||||
BEntry fEntry;
|
BEntry fEntry;
|
||||||
BRepositoryInfo fInfo;
|
BRepositoryInfo fInfo;
|
||||||
bool fIsUserSpecific;
|
bool fIsUserSpecific;
|
||||||
@@ -46,6 +55,25 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BRepositoryCache::Iterator {
|
||||||
|
public:
|
||||||
|
Iterator();
|
||||||
|
|
||||||
|
bool HasNext() const;
|
||||||
|
const BPackageInfo* Next();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator(const BRepositoryCache* cache);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class BRepositoryCache;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BRepositoryCache* fCache;
|
||||||
|
PackageInfo* fNextInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPackageKit
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ command_list_repos(int argc, const char* const* argv)
|
|||||||
repoCache.Info().Summary().String());
|
repoCache.Info().Summary().String());
|
||||||
printf("\t\tarch: %s\n", BPackageInfo::kArchitectureNames[
|
printf("\t\tarch: %s\n", BPackageInfo::kArchitectureNames[
|
||||||
repoCache.Info().Architecture()]);
|
repoCache.Info().Architecture()]);
|
||||||
printf("\t\tpkg-count: %lu\n", repoCache.PackageCount());
|
printf("\t\tpkg-count: %lu\n", repoCache.CountPackages());
|
||||||
printf("\t\torig-url: %s\n",
|
printf("\t\torig-url: %s\n",
|
||||||
repoCache.Info().OriginalBaseURL().String());
|
repoCache.Info().OriginalBaseURL().String());
|
||||||
printf("\t\torig-prio: %u\n", repoCache.Info().Priority());
|
printf("\t\torig-prio: %u\n", repoCache.Info().Priority());
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
|
||||||
#include <HashMap.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include <package/hpkg/ErrorOutput.h>
|
#include <package/hpkg/ErrorOutput.h>
|
||||||
#include <package/hpkg/PackageInfoAttributeValue.h>
|
#include <package/hpkg/PackageInfoAttributeValue.h>
|
||||||
@@ -36,14 +36,100 @@ using BPrivate::HashableString;
|
|||||||
using namespace BHPKG;
|
using namespace BHPKG;
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
// #pragma mark - PackageInfo
|
||||||
|
|
||||||
|
|
||||||
typedef ::BPrivate::HashMap<HashableString, BPackageInfo> PackageHashMap;
|
struct BRepositoryCache::PackageInfo : public BPackageInfo {
|
||||||
|
PackageInfo* hashNext;
|
||||||
|
PackageInfo* listNext;
|
||||||
|
|
||||||
struct RepositoryContentHandler : BRepositoryContentHandler {
|
PackageInfo(const BPackageInfo& other)
|
||||||
|
:
|
||||||
|
BPackageInfo(other),
|
||||||
|
listNext(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageInfoHashDefinition
|
||||||
|
|
||||||
|
|
||||||
|
struct BRepositoryCache::PackageInfoHashDefinition {
|
||||||
|
typedef const char* KeyType;
|
||||||
|
typedef PackageInfo ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const char* key) const
|
||||||
|
{
|
||||||
|
return BString::HashValue(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(const PackageInfo* value) const
|
||||||
|
{
|
||||||
|
return value->Name().HashValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const char* key, const PackageInfo* value) const
|
||||||
|
{
|
||||||
|
return value->Name() == key;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageInfo*& GetLink(PackageInfo* value) const
|
||||||
|
{
|
||||||
|
return value->hashNext;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageMap
|
||||||
|
|
||||||
|
|
||||||
|
struct BRepositoryCache::PackageMap
|
||||||
|
: public BOpenHashTable<PackageInfoHashDefinition> {
|
||||||
|
|
||||||
|
PackageMap()
|
||||||
|
:
|
||||||
|
fCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PackageMap()
|
||||||
|
{
|
||||||
|
PackageInfo* info = Clear(true);
|
||||||
|
while (info != NULL) {
|
||||||
|
PackageInfo* next = info->hashNext;
|
||||||
|
delete info;
|
||||||
|
info = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPackageInfo(PackageInfo* info)
|
||||||
|
{
|
||||||
|
if (PackageInfo* oldInfo = Lookup(info->Name())) {
|
||||||
|
info->listNext = oldInfo->listNext;
|
||||||
|
oldInfo->listNext = info;
|
||||||
|
} else
|
||||||
|
Insert(info);
|
||||||
|
|
||||||
|
fCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CountPackageInfos() const
|
||||||
|
{
|
||||||
|
return fCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - RepositoryContentHandler
|
||||||
|
|
||||||
|
|
||||||
|
struct BRepositoryCache::RepositoryContentHandler : BRepositoryContentHandler {
|
||||||
RepositoryContentHandler(BRepositoryInfo* repositoryInfo,
|
RepositoryContentHandler(BRepositoryInfo* repositoryInfo,
|
||||||
PackageHashMap* packageMap)
|
PackageMap* packageMap)
|
||||||
:
|
:
|
||||||
fRepositoryInfo(repositoryInfo),
|
fRepositoryInfo(repositoryInfo),
|
||||||
fPackageMap(packageMap)
|
fPackageMap(packageMap)
|
||||||
@@ -154,11 +240,21 @@ struct RepositoryContentHandler : BRepositoryContentHandler {
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (fPackageMap->ContainsKey(fPackageInfo.Name()))
|
PackageInfo* info = new(std::nothrow) PackageInfo(fPackageInfo);
|
||||||
return B_NAME_IN_USE;
|
if (info == NULL)
|
||||||
result = fPackageMap->Put(fPackageInfo.Name(), fPackageInfo);
|
return B_NO_MEMORY;
|
||||||
if (result != B_OK)
|
|
||||||
|
result = info->InitCheck();
|
||||||
|
if (result != B_OK) {
|
||||||
|
delete info;
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PackageInfo* oldInfo = fPackageMap->Lookup(info->Name())) {
|
||||||
|
info->listNext = oldInfo->listNext;
|
||||||
|
oldInfo->listNext = info;
|
||||||
|
} else
|
||||||
|
fPackageMap->Insert(info);
|
||||||
|
|
||||||
fPackageInfo.Clear();
|
fPackageInfo.Clear();
|
||||||
break;
|
break;
|
||||||
@@ -185,11 +281,14 @@ struct RepositoryContentHandler : BRepositoryContentHandler {
|
|||||||
private:
|
private:
|
||||||
BRepositoryInfo* fRepositoryInfo;
|
BRepositoryInfo* fRepositoryInfo;
|
||||||
BPackageInfo fPackageInfo;
|
BPackageInfo fPackageInfo;
|
||||||
PackageHashMap* fPackageMap;
|
PackageMap* fPackageMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class StandardErrorOutput : public BErrorOutput {
|
// #pragma mark - StandardErrorOutput
|
||||||
|
|
||||||
|
|
||||||
|
class BRepositoryCache::StandardErrorOutput : public BErrorOutput {
|
||||||
virtual void PrintErrorVarArgs(const char* format, va_list args)
|
virtual void PrintErrorVarArgs(const char* format, va_list args)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(stderr, format, args);
|
||||||
@@ -197,28 +296,61 @@ class StandardErrorOutput : public BErrorOutput {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // anonymous namespace
|
// #pragma mark - Iterator
|
||||||
|
|
||||||
|
|
||||||
struct BRepositoryCache::PackageMap : public PackageHashMap {
|
BRepositoryCache::Iterator::Iterator()
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BRepositoryCache::BRepositoryCache()
|
|
||||||
:
|
:
|
||||||
fInitStatus(B_NO_INIT),
|
fCache(NULL),
|
||||||
fIsUserSpecific(false),
|
fNextInfo(NULL)
|
||||||
fPackageMap(new (std::nothrow) PackageMap)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BRepositoryCache::BRepositoryCache(const BEntry& entry)
|
BRepositoryCache::Iterator::Iterator(const BRepositoryCache* cache)
|
||||||
|
:
|
||||||
|
fCache(cache),
|
||||||
|
fNextInfo(fCache->fPackageMap->GetIterator().Next())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BRepositoryCache::Iterator::HasNext() const
|
||||||
|
{
|
||||||
|
return fNextInfo != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BPackageInfo*
|
||||||
|
BRepositoryCache::Iterator::Next()
|
||||||
|
{
|
||||||
|
BPackageInfo* result = fNextInfo;
|
||||||
|
|
||||||
|
if (fNextInfo != NULL) {
|
||||||
|
if (fNextInfo->listNext != NULL) {
|
||||||
|
// get next in list
|
||||||
|
fNextInfo = fNextInfo->listNext;
|
||||||
|
} else {
|
||||||
|
// get next in hash table
|
||||||
|
PackageMap::Iterator iterator
|
||||||
|
= fCache->fPackageMap->GetIterator(fNextInfo->Name());
|
||||||
|
iterator.Next();
|
||||||
|
fNextInfo = iterator.Next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BRepositoryCache
|
||||||
|
|
||||||
|
|
||||||
|
BRepositoryCache::BRepositoryCache()
|
||||||
:
|
:
|
||||||
fIsUserSpecific(false),
|
fIsUserSpecific(false),
|
||||||
fPackageMap(new (std::nothrow) PackageMap)
|
fPackageMap(NULL)
|
||||||
{
|
{
|
||||||
fInitStatus = SetTo(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -228,13 +360,6 @@ BRepositoryCache::~BRepositoryCache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BRepositoryCache::InitCheck() const
|
|
||||||
{
|
|
||||||
return fInitStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const BEntry&
|
const BEntry&
|
||||||
BRepositoryCache::Entry() const
|
BRepositoryCache::Entry() const
|
||||||
{
|
{
|
||||||
@@ -266,14 +391,25 @@ BRepositoryCache::SetIsUserSpecific(bool isUserSpecific)
|
|||||||
status_t
|
status_t
|
||||||
BRepositoryCache::SetTo(const BEntry& entry)
|
BRepositoryCache::SetTo(const BEntry& entry)
|
||||||
{
|
{
|
||||||
|
// unset
|
||||||
|
if (fPackageMap != NULL) {
|
||||||
|
delete fPackageMap;
|
||||||
|
fPackageMap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fEntry.Unset();
|
||||||
|
|
||||||
|
// create the package map
|
||||||
|
fPackageMap = new (std::nothrow) PackageMap;
|
||||||
if (fPackageMap == NULL)
|
if (fPackageMap == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
status_t result = fPackageMap->InitCheck();
|
|
||||||
|
status_t result = fPackageMap->Init();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
// get cache file path
|
||||||
fEntry = entry;
|
fEntry = entry;
|
||||||
fPackageMap->Clear();
|
|
||||||
|
|
||||||
BPath repositoryCachePath;
|
BPath repositoryCachePath;
|
||||||
if ((result = entry.GetPath(&repositoryCachePath)) != B_OK)
|
if ((result = entry.GetPath(&repositoryCachePath)) != B_OK)
|
||||||
@@ -301,12 +437,19 @@ BRepositoryCache::SetTo(const BEntry& entry)
|
|||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
BRepositoryCache::PackageCount() const
|
BRepositoryCache::CountPackages() const
|
||||||
{
|
{
|
||||||
if (fPackageMap == NULL)
|
if (fPackageMap == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return fPackageMap->Size();
|
return fPackageMap->CountPackageInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRepositoryCache::Iterator
|
||||||
|
BRepositoryCache::GetIterator() const
|
||||||
|
{
|
||||||
|
return Iterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user