xref: /haiku/headers/private/kernel/util/VectorSet.h (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 // VectorSet.h
2 //
3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22 //
23 // Except as contained in this notice, the name of a copyright holder shall
24 // not be used in advertising or otherwise to promote the sale, use or other
25 // dealings in this Software without prior written authorization of the
26 // copyright holder.
27 
28 #ifndef _VECTOR_SET_H
29 #define _VECTOR_SET_H
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <SupportDefs.h>
35 
36 #include <util/kernel_cpp.h>
37 #include <Vector.h>
38 
39 // element orders
40 namespace VectorSetOrder {
41 	template<typename Value> class Ascending;
42 	template<typename Value> class Descending;
43 }
44 
45 // for convenience
46 #define _VECTOR_SET_TEMPLATE_LIST template<typename Value, \
47 										   typename ElementOrder>
48 #define _VECTOR_SET_CLASS_NAME VectorSet<Value, ElementOrder>
49 #define _VECTOR_SET_CLASS_TYPE typename VectorSet<Value, ElementOrder>
50 
51 /*!
52 	\class VectorSet
53 	\brief A generic vector-based set implementation.
54 
55 	The elements of the set are ordered according to the supplied
56 	compare function object. Default is ascending order.
57 */
58 template<typename Value,
59 		 typename ElementOrder = VectorSetOrder::Ascending<Value> >
60 class VectorSet {
61 private:
62 	typedef Vector<Value>							ElementVector;
63 
64 public:
65 	typedef typename ElementVector::Iterator		Iterator;
66 	typedef typename ElementVector::ConstIterator	ConstIterator;
67 
68 private:
69 	static const size_t				kDefaultChunkSize = 10;
70 	static const size_t				kMaximalChunkSize = 1024 * 1024;
71 
72 public:
73 	VectorSet(size_t chunkSize = kDefaultChunkSize);
74 // TODO: Copy constructor, assignment operator.
75 	~VectorSet();
76 
77 	status_t Insert(const Value &value, bool replace = true);
78 
79 	int32 Remove(const Value &value);
80 	Iterator Erase(const Iterator &iterator);
81 
82 	inline int32 Count() const;
83 	inline bool IsEmpty() const;
84 	void MakeEmpty();
85 
86 	inline Iterator Begin();
87 	inline ConstIterator Begin() const;
88 	inline Iterator End();
89 	inline ConstIterator End() const;
90 	inline Iterator Null();
91 	inline ConstIterator Null() const;
92 
93 	Iterator Find(const Value &value);
94 	ConstIterator Find(const Value &value) const;
95 	Iterator FindClose(const Value &value, bool less);
96 	ConstIterator FindClose(const Value &value, bool less) const;
97 
98 private:
99 	int32 _FindInsertionIndex(const Value &value, bool &exists) const;
100 
101 private:
102 	ElementVector	fElements;
103 	ElementOrder	fCompare;
104 };
105 
106 
107 // VectorSet
108 
109 // constructor
110 /*!	\brief Creates an empty set.
111 	\param chunkSize The granularity for the underlying vector's capacity,
112 		   i.e. the minimal number of elements the capacity grows or shrinks
113 		   when necessary.
114 */
115 _VECTOR_SET_TEMPLATE_LIST
116 _VECTOR_SET_CLASS_NAME::VectorSet(size_t chunkSize)
117 	: fElements(chunkSize)
118 {
119 }
120 
121 // destructor
122 /*!	\brief Frees all resources associated with the object.
123 
124 	The contained elements are destroyed. Note, that, if the element
125 	type is a pointer type, only the pointer is destroyed, not the object
126 	it points to.
127 */
128 _VECTOR_SET_TEMPLATE_LIST
129 _VECTOR_SET_CLASS_NAME::~VectorSet()
130 {
131 }
132 
133 // Insert
134 /*!	\brief Inserts a copy of the the supplied value.
135 
136 	If an element with the supplied value is already in the set, the
137 	operation will not fail, but return \c B_OK. \a replace specifies
138 	whether the element shall be replaced with the supplied in such a case.
139 	Otherwise \a replace is ignored.
140 
141 	\param value The value to be inserted.
142 	\param replace If the an element with this value does already exist and
143 		   \a replace is \c true, the element is replaced, otherwise left
144 		   untouched.
145 	\return
146 	- \c B_OK: Everything went fine.
147 	- \c B_NO_MEMORY: Insufficient memory for this operation.
148 */
149 _VECTOR_SET_TEMPLATE_LIST
150 status_t
151 _VECTOR_SET_CLASS_NAME::Insert(const Value &value, bool replace)
152 {
153 	bool exists = false;
154 	int32 index = _FindInsertionIndex(value, exists);
155 	if (exists) {
156 		if (replace)
157 			fElements[index] = value;
158 		return B_OK;
159 	}
160 	return fElements.Insert(value, index);
161 }
162 
163 // Remove
164 /*!	\brief Removes the element with the supplied value.
165 	\param value The value of the element to be removed.
166 	\return The number of removed occurrences, i.e. \c 1, if the set
167 			contained an element with the value, \c 0 otherwise.
168 */
169 _VECTOR_SET_TEMPLATE_LIST
170 int32
171 _VECTOR_SET_CLASS_NAME::Remove(const Value &value)
172 {
173 	bool exists = false;
174 	int32 index = _FindInsertionIndex(value, exists);
175 	if (!exists)
176 		return 0;
177 	fElements.Erase(index);
178 	return 1;
179 }
180 
181 // Erase
182 /*!	\brief Removes the element at the given position.
183 	\param iterator An iterator referring to the element to be removed.
184 	\return An iterator referring to the element succeeding the removed
185 			one (End(), if it was the last element that has been
186 			removed), or Null(), if \a iterator was an invalid iterator
187 			(in this case including End()).
188 */
189 _VECTOR_SET_TEMPLATE_LIST
190 _VECTOR_SET_CLASS_TYPE::Iterator
191 _VECTOR_SET_CLASS_NAME::Erase(const Iterator &iterator)
192 {
193 	return fElements.Erase(iterator);
194 }
195 
196 // Count
197 /*!	\brief Returns the number of elements the set contains.
198 	\return The number of elements the set contains.
199 */
200 _VECTOR_SET_TEMPLATE_LIST
201 inline
202 int32
203 _VECTOR_SET_CLASS_NAME::Count() const
204 {
205 	return fElements.Count();
206 }
207 
208 // IsEmpty
209 /*!	\brief Returns whether the set is empty.
210 	\return \c true, if the set is empty, \c false otherwise.
211 */
212 _VECTOR_SET_TEMPLATE_LIST
213 inline
214 bool
215 _VECTOR_SET_CLASS_NAME::IsEmpty() const
216 {
217 	return fElements.IsEmpty();
218 }
219 
220 // MakeEmpty
221 /*!	\brief Removes all elements from the set.
222 */
223 _VECTOR_SET_TEMPLATE_LIST
224 void
225 _VECTOR_SET_CLASS_NAME::MakeEmpty()
226 {
227 	fElements.MakeEmpty();
228 }
229 
230 // Begin
231 /*!	\brief Returns an iterator referring to the beginning of the set.
232 
233 	If the set is not empty, Begin() refers to its first element,
234 	otherwise it is equal to End() and must not be dereferenced!
235 
236 	\return An iterator referring to the beginning of the set.
237 */
238 _VECTOR_SET_TEMPLATE_LIST
239 inline
240 _VECTOR_SET_CLASS_TYPE::Iterator
241 _VECTOR_SET_CLASS_NAME::Begin()
242 {
243 	return fElements.Begin();
244 }
245 
246 // Begin
247 /*!	\brief Returns an iterator referring to the beginning of the set.
248 
249 	If the set is not empty, Begin() refers to its first element,
250 	otherwise it is equal to End() and must not be dereferenced!
251 
252 	\return An iterator referring to the beginning of the set.
253 */
254 _VECTOR_SET_TEMPLATE_LIST
255 inline
256 _VECTOR_SET_CLASS_TYPE::ConstIterator
257 _VECTOR_SET_CLASS_NAME::Begin() const
258 {
259 	return fElements.Begin();
260 }
261 
262 // End
263 /*!	\brief Returns an iterator referring to the end of the set.
264 
265 	The position identified by End() is the one succeeding the last
266 	element, i.e. it must not be dereferenced!
267 
268 	\return An iterator referring to the end of the set.
269 */
270 _VECTOR_SET_TEMPLATE_LIST
271 inline
272 _VECTOR_SET_CLASS_TYPE::Iterator
273 _VECTOR_SET_CLASS_NAME::End()
274 {
275 	return fElements.End();
276 }
277 
278 // End
279 /*!	\brief Returns an iterator referring to the end of the set.
280 
281 	The position identified by End() is the one succeeding the last
282 	element, i.e. it must not be dereferenced!
283 
284 	\return An iterator referring to the end of the set.
285 */
286 _VECTOR_SET_TEMPLATE_LIST
287 inline
288 _VECTOR_SET_CLASS_TYPE::ConstIterator
289 _VECTOR_SET_CLASS_NAME::End() const
290 {
291 	return fElements.End();
292 }
293 
294 // Null
295 /*!	\brief Returns an invalid iterator.
296 
297 	Null() is used as a return value, if something went wrong. It must
298 	neither be incremented or decremented nor dereferenced!
299 
300 	\return An invalid iterator.
301 */
302 _VECTOR_SET_TEMPLATE_LIST
303 inline
304 _VECTOR_SET_CLASS_TYPE::Iterator
305 _VECTOR_SET_CLASS_NAME::Null()
306 {
307 	return fElements.Null();
308 }
309 
310 // Null
311 /*!	\brief Returns an invalid iterator.
312 
313 	Null() is used as a return value, if something went wrong. It must
314 	neither be incremented or decremented nor dereferenced!
315 
316 	\return An invalid iterator.
317 */
318 _VECTOR_SET_TEMPLATE_LIST
319 inline
320 _VECTOR_SET_CLASS_TYPE::ConstIterator
321 _VECTOR_SET_CLASS_NAME::Null() const
322 {
323 	return fElements.Null();
324 }
325 
326 // Find
327 /*!	\brief Returns an iterator referring to the element with the
328 		   specified value.
329 	\param value The value of the element to be found.
330 	\return An iterator referring to the found element, or End(), if the
331 			set doesn't contain any element with the given value.
332 */
333 _VECTOR_SET_TEMPLATE_LIST
334 _VECTOR_SET_CLASS_TYPE::Iterator
335 _VECTOR_SET_CLASS_NAME::Find(const Value &value)
336 {
337 	bool exists = false;
338 	int32 index = _FindInsertionIndex(value, exists);
339 	if (!exists)
340 		return fElements.End();
341 	return fElements.IteratorForIndex(index);
342 }
343 
344 // Find
345 /*!	\brief Returns an iterator referring to the element with the
346 		   specified value.
347 	\param value The value of the element to be found.
348 	\return An iterator referring to the found element, or End(), if the
349 			set doesn't contain any element with the given value.
350 */
351 _VECTOR_SET_TEMPLATE_LIST
352 _VECTOR_SET_CLASS_TYPE::ConstIterator
353 _VECTOR_SET_CLASS_NAME::Find(const Value &value) const
354 {
355 	bool exists = false;
356 	int32 index = _FindInsertionIndex(value, exists);
357 	if (!exists)
358 		return fElements.End();
359 	return fElements.IteratorForIndex(index);
360 }
361 
362 // FindClose
363 /*!	\brief Returns an iterator referring to the element with a value closest
364 		   to the specified one.
365 
366 	If the set contains an element with the specified value, an iterator
367 	to it is returned. Otherwise \a less indicates whether an iterator to
368 	the directly smaller or greater element shall be returned.
369 
370 	If \a less is \c true and the first element in the set has a greater
371 	value than the specified one, End() is returned. Similarly, when \a less
372 	is \c false and the last element is smaller. Find() invoked on an empty
373 	set always returns End().
374 
375 	Note, that the element order used for the set is specified as template
376 	argument to the class. Default is ascending order. Descending order
377 	inverts the meaning of \a less, i.e. if \c true, greater values will
378 	be returned, since they are smaller ones according to the order.
379 
380 	\param value The value of the element to be found.
381 	\return An iterator referring to the found element, or End(), if the
382 			set doesn't contain any element with the given value or a close
383 			one according to \a less.
384 */
385 _VECTOR_SET_TEMPLATE_LIST
386 _VECTOR_SET_CLASS_TYPE::Iterator
387 _VECTOR_SET_CLASS_NAME::FindClose(const Value &value, bool less)
388 {
389 	bool exists = false;
390 	int32 index = _FindInsertionIndex(value, exists);
391 	// If not found, the index _FindInsertionIndex() returns will point to
392 	// an element with a greater value or to End(). So, no special handling
393 	// is needed for !less.
394 	if (exists || !less)
395 		return fElements.IteratorForIndex(index);
396 	// An element with a smaller value is desired. The previous one (if any)
397 	// will do.
398 	if (index > 0)
399 		return fElements.IteratorForIndex(index - 1);
400 	return fElements.End();
401 }
402 
403 // FindClose
404 /*!	\brief Returns an iterator referring to the element with a value closest
405 		   to the specified one.
406 
407 	If the set contains an element with the specified value, an iterator
408 	to it is returned. Otherwise \a less indicates whether an iterator to
409 	the directly smaller or greater element shall be returned.
410 
411 	If \a less is \c true and the first element in the set has a greater
412 	value than the specified one, End() is returned. Similarly, when \a less
413 	is \c false and the last element is smaller. Find() invoked on an empty
414 	set always returns End().
415 
416 	Note, that the element order used for the set is specified as template
417 	argument to the class. Default is ascending order. Descending order
418 	inverts the meaning of \a less, i.e. if \c true, greater values will
419 	be returned, since they are smaller ones according to the order.
420 
421 	\param value The value of the element to be found.
422 	\return An iterator referring to the found element, or End(), if the
423 			set doesn't contain any element with the given value or a close
424 			one according to \a less.
425 */
426 _VECTOR_SET_TEMPLATE_LIST
427 _VECTOR_SET_CLASS_TYPE::ConstIterator
428 _VECTOR_SET_CLASS_NAME::FindClose(const Value &value, bool less) const
429 {
430 	bool exists = false;
431 	int32 index = _FindInsertionIndex(value, exists);
432 	// If not found, the index _FindInsertionIndex() returns will point to
433 	// an element with a greater value or to End(). So, no special handling
434 	// is needed for !less.
435 	if (exists || !less)
436 		return fElements.IteratorForIndex(index);
437 	// An element with a smaller value is desired. The previous one (if any)
438 	// will do.
439 	if (index > 0)
440 		return fElements.IteratorForIndex(index - 1);
441 	return fElements.End();
442 }
443 
444 // _FindInsertionIndex
445 /*!	\brief Finds the index at which the element with the supplied value is
446 		   located or at which it would need to be inserted.
447 	\param value The value.
448 	\param exists Is set to \c true, if the set does already contain an
449 		   element with that value.
450 	\return The index at which the element with the supplied value is
451 			located or at which it would need to be inserted.
452 */
453 _VECTOR_SET_TEMPLATE_LIST
454 int32
455 _VECTOR_SET_CLASS_NAME::_FindInsertionIndex(const Value &value,
456 											bool &exists) const
457 {
458 	// binary search
459 	int32 lower = 0;
460 	int32 upper = Count();
461 	while (lower < upper) {
462 		int32 mid = (lower + upper) / 2;
463 		int cmp = fCompare(fElements[mid], value);
464 		if (cmp < 0)
465 			lower = mid + 1;
466 		else
467 			upper = mid;
468 	}
469 	exists = (lower < Count() && fCompare(value, fElements[lower]) == 0);
470 	return lower;
471 }
472 
473 
474 // element orders
475 
476 namespace VectorSetOrder {
477 
478 // Ascending
479 /*!	\brief A compare function object implying and ascending order.
480 
481 	The < operator must be defined on the template argument.
482 */
483 template<typename Value>
484 class Ascending {
485 public:
486 	inline int operator()(const Value &a, const Value &b) const
487 	{
488 		if (a < b)
489 			return -1;
490 		else if (b < a)
491 			return 1;
492 		return 0;
493 	}
494 };
495 
496 // Descending
497 /*!	\brief A compare function object implying and descending order.
498 
499 	The < operator must be defined on the template argument.
500 */
501 template<typename Value>
502 class Descending {
503 public:
504 	inline int operator()(const Value &a, const Value &b) const
505 	{
506 		if (a < b)
507 			return -1;
508 		else if (b < a)
509 			return 1;
510 		return 0;
511 	}
512 };
513 
514 }	// namespace VectorSetOrder
515 
516 #endif	// _VECTOR_SET_H
517