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