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
40namespace 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*/
58template<typename Value,
59		 typename ElementOrder = VectorSetOrder::Ascending<Value> >
60class VectorSet {
61private:
62	typedef Vector<Value>							ElementVector;
63
64public:
65	typedef typename ElementVector::Iterator		Iterator;
66	typedef typename ElementVector::ConstIterator	ConstIterator;
67
68private:
69	static const size_t				kDefaultChunkSize = 10;
70	static const size_t				kMaximalChunkSize = 1024 * 1024;
71
72public:
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
98private:
99	int32 _FindInsertionIndex(const Value &value, bool &exists) const;
100
101private:
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
150status_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
170int32
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
201inline
202int32
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
213inline
214bool
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
224void
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
239inline
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
255inline
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
271inline
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
287inline
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
303inline
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
319inline
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
454int32
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
476namespace 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*/
483template<typename Value>
484class Ascending {
485public:
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*/
501template<typename Value>
502class Descending {
503public:
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