2 * Copyright 2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Oliver Tappe <zooey@hirschkaefer.de>
7 * Ingo Weinhold <ingo_weinhold@gmx.de>
11 #include <package/PackageInfoSet.h>
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
)
43 PackageInfo
* info
= this;
44 while (info
!= NULL
) {
45 PackageInfo
* next
= info
->listNext
;
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
> {
96 DeleteAllPackageInfos();
99 static PackageMap
* Create()
101 PackageMap
* map
= new(std::nothrow
) PackageMap
;
102 if (map
== NULL
|| map
->Init() != B_OK
) {
110 PackageMap
* Clone() const
112 PackageMap
* newMap
= Create();
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
)
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
;
137 status_t
AddNewPackageInfo(const BPackageInfo
& oldInfo
)
139 PackageInfo
* info
= new(std::nothrow
) PackageInfo(oldInfo
);
142 ObjectDeleter
<PackageInfo
> infoDeleter(info
);
144 status_t error
= info
->InitCheck();
148 AddPackageInfo(infoDeleter
.Detach());
153 void DeleteAllPackageInfos()
155 PackageInfo
* info
= Clear(true);
156 while (info
!= NULL
) {
157 PackageInfo
* next
= info
->hashNext
;
163 uint32
CountPackageInfos() const
173 // #pragma mark - Iterator
176 BPackageInfoSet::Iterator::Iterator(const PackageMap
* map
)
179 fNextInfo(map
!= NULL
? map
->GetIterator().Next() : NULL
)
185 BPackageInfoSet::Iterator::HasNext() const
187 return fNextInfo
!= NULL
;
192 BPackageInfoSet::Iterator::Next()
194 BPackageInfo
* result
= fNextInfo
;
196 if (fNextInfo
!= NULL
) {
197 if (fNextInfo
->listNext
!= NULL
) {
199 fNextInfo
= fNextInfo
->listNext
;
201 // get next in hash table
202 PackageMap::Iterator iterator
203 = fMap
->GetIterator(fNextInfo
->Name());
205 fNextInfo
= iterator
.Next();
213 // #pragma mark - BPackageInfoSet
216 BPackageInfoSet::BPackageInfoSet()
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();
240 BPackageInfoSet::AddInfo(const BPackageInfo
& info
)
245 return fPackageMap
->AddNewPackageInfo(info
);
250 BPackageInfoSet::MakeEmpty()
252 if (fPackageMap
== NULL
|| fPackageMap
->CountPackageInfos() == 0)
255 // If our map is shared, just set it to NULL.
256 if (fPackageMap
->CountReferences() != 1) {
257 fPackageMap
->ReleaseReference();
262 // Our map is not shared -- make it empty.
263 fPackageMap
->DeleteAllPackageInfos();
268 BPackageInfoSet::CountInfos() const
270 if (fPackageMap
== NULL
)
273 return fPackageMap
->CountPackageInfos();
277 BPackageInfoSet::Iterator
278 BPackageInfoSet::GetIterator() const
280 return Iterator(fPackageMap
);
285 BPackageInfoSet::operator=(const BPackageInfoSet
& other
)
287 if (other
.fPackageMap
== fPackageMap
)
290 if (fPackageMap
!= NULL
)
291 fPackageMap
->ReleaseReference();
293 fPackageMap
= other
.fPackageMap
;
295 if (fPackageMap
!= NULL
)
296 fPackageMap
->AcquireReference();
303 BPackageInfoSet::_CopyOnWrite()
305 if (fPackageMap
== NULL
) {
306 fPackageMap
= PackageMap::Create();
307 return fPackageMap
!= NULL
;
310 if (fPackageMap
->CountReferences() == 1)
313 PackageMap
* newMap
= fPackageMap
->Clone();
317 fPackageMap
->ReleaseReference();
318 fPackageMap
= newMap
;
323 } // namespace BPackageKit