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 20 namespace BPackageKit { 21 22 23 // #pragma mark - PackageInfo 24 25 26 struct 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 42 struct 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 71 struct 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 106 private: 107 uint32 fCount; 108 }; 109 110 111 // #pragma mark - Iterator 112 113 114 BPackageInfoSet::Iterator::Iterator() 115 : 116 fSet(NULL), 117 fNextInfo(NULL) 118 { 119 } 120 121 122 BPackageInfoSet::Iterator::Iterator(const BPackageInfoSet* set) 123 : 124 fSet(set), 125 fNextInfo(fSet->fPackageMap->GetIterator().Next()) 126 { 127 } 128 129 bool 130 BPackageInfoSet::Iterator::HasNext() const 131 { 132 return fNextInfo != NULL; 133 } 134 135 136 const BPackageInfo* 137 BPackageInfoSet::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 161 BPackageInfoSet::BPackageInfoSet() 162 : 163 fPackageMap(new(std::nothrow) PackageMap) 164 { 165 } 166 167 168 BPackageInfoSet::~BPackageInfoSet() 169 { 170 MakeEmpty(); 171 delete fPackageMap; 172 } 173 174 175 status_t 176 BPackageInfoSet::Init() 177 { 178 return fPackageMap->Init(); 179 } 180 181 182 status_t 183 BPackageInfoSet::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 209 void 210 BPackageInfoSet::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 224 uint32 225 BPackageInfoSet::CountInfos() const 226 { 227 if (fPackageMap == NULL) 228 return 0; 229 230 return fPackageMap->CountPackageInfos(); 231 } 232 233 234 BPackageInfoSet::Iterator 235 BPackageInfoSet::GetIterator() const 236 { 237 return Iterator(this); 238 } 239 240 241 } // namespace BPackageKit 242