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