1/* 2 * Copyright 2011, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe <zooey@hirschkaefer.de> 7 * Ingo Weinhold <ingo_weinhold@gmx.de> 8 */ 9 10 11#include <package/PackageInfoSet.h> 12 13#include <new> 14 15#include <util/OpenHashTable.h> 16 17#include <package/PackageInfo.h> 18 19 20namespace BPackageKit { 21 22 23// #pragma mark - PackageInfo 24 25 26struct BPackageInfoSet::PackageInfo : public BPackageInfo { 27 PackageInfo* hashNext; 28 PackageInfo* listNext; 29 30 PackageInfo(const BPackageInfo& other) 31 : 32 BPackageInfo(other), 33 listNext(NULL) 34 { 35 } 36}; 37 38 39// #pragma mark - PackageInfoHashDefinition 40 41 42struct BPackageInfoSet::PackageInfoHashDefinition { 43 typedef const char* KeyType; 44 typedef PackageInfo ValueType; 45 46 size_t HashKey(const char* key) const 47 { 48 return BString::HashValue(key); 49 } 50 51 size_t Hash(const PackageInfo* value) const 52 { 53 return value->Name().HashValue(); 54 } 55 56 bool Compare(const char* key, const PackageInfo* value) const 57 { 58 return value->Name() == key; 59 } 60 61 PackageInfo*& GetLink(PackageInfo* value) const 62 { 63 return value->hashNext; 64 } 65}; 66 67 68// #pragma mark - PackageMap 69 70 71struct BPackageInfoSet::PackageMap 72 : public BOpenHashTable<PackageInfoHashDefinition> { 73 74 PackageMap() 75 : 76 fCount(0) 77 { 78 } 79 80 ~PackageMap() 81 { 82 PackageInfo* info = Clear(true); 83 while (info != NULL) { 84 PackageInfo* next = info->hashNext; 85 delete info; 86 info = next; 87 } 88 } 89 90 void AddPackageInfo(PackageInfo* info) 91 { 92 if (PackageInfo* oldInfo = Lookup(info->Name())) { 93 info->listNext = oldInfo->listNext; 94 oldInfo->listNext = info; 95 } else 96 Insert(info); 97 98 fCount++; 99 } 100 101 uint32 CountPackageInfos() const 102 { 103 return fCount; 104 } 105 106private: 107 uint32 fCount; 108}; 109 110 111// #pragma mark - Iterator 112 113 114BPackageInfoSet::Iterator::Iterator() 115 : 116 fSet(NULL), 117 fNextInfo(NULL) 118{ 119} 120 121 122BPackageInfoSet::Iterator::Iterator(const BPackageInfoSet* set) 123 : 124 fSet(set), 125 fNextInfo(fSet->fPackageMap->GetIterator().Next()) 126{ 127} 128 129bool 130BPackageInfoSet::Iterator::HasNext() const 131{ 132 return fNextInfo != NULL; 133} 134 135 136const BPackageInfo* 137BPackageInfoSet::Iterator::Next() 138{ 139 BPackageInfo* result = fNextInfo; 140 141 if (fNextInfo != NULL) { 142 if (fNextInfo->listNext != NULL) { 143 // get next in list 144 fNextInfo = fNextInfo->listNext; 145 } else { 146 // get next in hash table 147 PackageMap::Iterator iterator 148 = fSet->fPackageMap->GetIterator(fNextInfo->Name()); 149 iterator.Next(); 150 fNextInfo = iterator.Next(); 151 } 152 } 153 154 return result; 155} 156 157 158// #pragma mark - BPackageInfoSet 159 160 161BPackageInfoSet::BPackageInfoSet() 162 : 163 fPackageMap(new(std::nothrow) PackageMap) 164{ 165} 166 167 168BPackageInfoSet::~BPackageInfoSet() 169{ 170 MakeEmpty(); 171 delete fPackageMap; 172} 173 174 175status_t 176BPackageInfoSet::Init() 177{ 178 return fPackageMap->Init(); 179} 180 181 182status_t 183BPackageInfoSet::AddInfo(const BPackageInfo& _info) 184{ 185 if (fPackageMap == NULL) 186 return B_NO_INIT; 187 188 PackageInfo* info = new(std::nothrow) PackageInfo(_info); 189 if (info == NULL) 190 return B_NO_MEMORY; 191 192 status_t error = info->InitCheck(); 193 if (error != B_OK) { 194 delete info; 195 return error; 196 } 197 198 if (PackageInfo* oldInfo = fPackageMap->Lookup(info->Name())) { 199 // TODO: Check duplicates? 200 info->listNext = oldInfo->listNext; 201 oldInfo->listNext = info; 202 } else 203 fPackageMap->Insert(info); 204 205 return B_OK; 206} 207 208 209void 210BPackageInfoSet::MakeEmpty() 211{ 212 if (fPackageMap == NULL) 213 return; 214 215 PackageInfo* info = fPackageMap->Clear(true); 216 while (info != NULL) { 217 PackageInfo* next = info->hashNext; 218 delete info; 219 info = next; 220 } 221} 222 223 224uint32 225BPackageInfoSet::CountInfos() const 226{ 227 if (fPackageMap == NULL) 228 return 0; 229 230 return fPackageMap->CountPackageInfos(); 231} 232 233 234BPackageInfoSet::Iterator 235BPackageInfoSet::GetIterator() const 236{ 237 return Iterator(this); 238} 239 240 241} // namespace BPackageKit 242