xref: /haiku/src/kits/package/PackageInfoSet.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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