BPicture: Fix archive constructor.
[haiku.git] / src / kits / package / PackageInfoSet.cpp
blobf6d354e5bdb71a300b13b22f7787394c66cdc0c8
1 /*
2 * Copyright 2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Oliver Tappe <zooey@hirschkaefer.de>
7 * Ingo Weinhold <ingo_weinhold@gmx.de>
8 */
11 #include <package/PackageInfoSet.h>
13 #include <new>
15 #include <Referenceable.h>
17 #include <AutoDeleter.h>
19 #include <util/OpenHashTable.h>
21 #include <package/PackageInfo.h>
24 namespace BPackageKit {
27 // #pragma mark - PackageInfo
30 struct BPackageInfoSet::PackageInfo : public BPackageInfo {
31 PackageInfo* hashNext;
32 PackageInfo* listNext;
34 PackageInfo(const BPackageInfo& other)
36 BPackageInfo(other),
37 listNext(NULL)
41 void DeleteList()
43 PackageInfo* info = this;
44 while (info != NULL) {
45 PackageInfo* next = info->listNext;
46 delete info;
47 info = next;
53 // #pragma mark - PackageInfoHashDefinition
56 struct BPackageInfoSet::PackageInfoHashDefinition {
57 typedef const char* KeyType;
58 typedef PackageInfo ValueType;
60 size_t HashKey(const char* key) const
62 return BString::HashValue(key);
65 size_t Hash(const PackageInfo* value) const
67 return value->Name().HashValue();
70 bool Compare(const char* key, const PackageInfo* value) const
72 return value->Name() == key;
75 PackageInfo*& GetLink(PackageInfo* value) const
77 return value->hashNext;
82 // #pragma mark - PackageMap
85 struct BPackageInfoSet::PackageMap : public BReferenceable,
86 public BOpenHashTable<PackageInfoHashDefinition> {
88 PackageMap()
90 fCount(0)
94 ~PackageMap()
96 DeleteAllPackageInfos();
99 static PackageMap* Create()
101 PackageMap* map = new(std::nothrow) PackageMap;
102 if (map == NULL || map->Init() != B_OK) {
103 delete map;
104 return NULL;
107 return map;
110 PackageMap* Clone() const
112 PackageMap* newMap = Create();
113 if (newMap == NULL)
114 return NULL;
115 ObjectDeleter<PackageMap> newMapDeleter(newMap);
117 for (BPackageInfoSet::Iterator it(this); it.HasNext();) {
118 const BPackageInfo* info = it.Next();
119 if (newMap->AddNewPackageInfo(*info) != B_OK)
120 return NULL;
123 return newMapDeleter.Detach();
126 void AddPackageInfo(PackageInfo* info)
128 if (PackageInfo* oldInfo = Lookup(info->Name())) {
129 info->listNext = oldInfo->listNext;
130 oldInfo->listNext = info;
131 } else
132 Insert(info);
134 fCount++;
137 status_t AddNewPackageInfo(const BPackageInfo& oldInfo)
139 PackageInfo* info = new(std::nothrow) PackageInfo(oldInfo);
140 if (info == NULL)
141 return B_NO_MEMORY;
142 ObjectDeleter<PackageInfo> infoDeleter(info);
144 status_t error = info->InitCheck();
145 if (error != B_OK)
146 return error;
148 AddPackageInfo(infoDeleter.Detach());
150 return B_OK;
153 void DeleteAllPackageInfos()
155 PackageInfo* info = Clear(true);
156 while (info != NULL) {
157 PackageInfo* next = info->hashNext;
158 info->DeleteList();
159 info = next;
163 uint32 CountPackageInfos() const
165 return fCount;
168 private:
169 uint32 fCount;
173 // #pragma mark - Iterator
176 BPackageInfoSet::Iterator::Iterator(const PackageMap* map)
178 fMap(map),
179 fNextInfo(map != NULL ? map->GetIterator().Next() : NULL)
184 bool
185 BPackageInfoSet::Iterator::HasNext() const
187 return fNextInfo != NULL;
191 const BPackageInfo*
192 BPackageInfoSet::Iterator::Next()
194 BPackageInfo* result = fNextInfo;
196 if (fNextInfo != NULL) {
197 if (fNextInfo->listNext != NULL) {
198 // get next in list
199 fNextInfo = fNextInfo->listNext;
200 } else {
201 // get next in hash table
202 PackageMap::Iterator iterator
203 = fMap->GetIterator(fNextInfo->Name());
204 iterator.Next();
205 fNextInfo = iterator.Next();
209 return result;
213 // #pragma mark - BPackageInfoSet
216 BPackageInfoSet::BPackageInfoSet()
218 fPackageMap(NULL)
223 BPackageInfoSet::~BPackageInfoSet()
225 if (fPackageMap != NULL)
226 fPackageMap->ReleaseReference();
230 BPackageInfoSet::BPackageInfoSet(const BPackageInfoSet& other)
232 fPackageMap(other.fPackageMap)
234 if (fPackageMap != NULL)
235 fPackageMap->AcquireReference();
239 status_t
240 BPackageInfoSet::AddInfo(const BPackageInfo& info)
242 if (!_CopyOnWrite())
243 return B_NO_MEMORY;
245 return fPackageMap->AddNewPackageInfo(info);
249 void
250 BPackageInfoSet::MakeEmpty()
252 if (fPackageMap == NULL || fPackageMap->CountPackageInfos() == 0)
253 return;
255 // If our map is shared, just set it to NULL.
256 if (fPackageMap->CountReferences() != 1) {
257 fPackageMap->ReleaseReference();
258 fPackageMap = NULL;
259 return;
262 // Our map is not shared -- make it empty.
263 fPackageMap->DeleteAllPackageInfos();
267 uint32
268 BPackageInfoSet::CountInfos() const
270 if (fPackageMap == NULL)
271 return 0;
273 return fPackageMap->CountPackageInfos();
277 BPackageInfoSet::Iterator
278 BPackageInfoSet::GetIterator() const
280 return Iterator(fPackageMap);
284 BPackageInfoSet&
285 BPackageInfoSet::operator=(const BPackageInfoSet& other)
287 if (other.fPackageMap == fPackageMap)
288 return *this;
290 if (fPackageMap != NULL)
291 fPackageMap->ReleaseReference();
293 fPackageMap = other.fPackageMap;
295 if (fPackageMap != NULL)
296 fPackageMap->AcquireReference();
298 return *this;
302 bool
303 BPackageInfoSet::_CopyOnWrite()
305 if (fPackageMap == NULL) {
306 fPackageMap = PackageMap::Create();
307 return fPackageMap != NULL;
310 if (fPackageMap->CountReferences() == 1)
311 return true;
313 PackageMap* newMap = fPackageMap->Clone();
314 if (newMap == NULL)
315 return false;
317 fPackageMap->ReleaseReference();
318 fPackageMap = newMap;
319 return true;
323 } // namespace BPackageKit