Evo C++ Library v0.5.1
setlist.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_setlist_h
9 #define INCL_evo_setlist_h
10 
11 #include "set.h"
12 #include "list.h"
13 
14 namespace evo {
17 
19 
249 template<class TKey, class TCompare=Compare<TKey>, class TSize=SizeT>
250 class SetList : public Set<TKey,TSize> {
251 public:
253 #if defined(_MSC_VER) || defined(EVO_OLDCC) // avoid errors with older compilers and MSVC
254  typedef Set<TKey,TSize> SetBaseType;
255  typedef typename SetBaseType::Size Size;
256  typedef typename SetBaseType::Key Key;
257  typedef typename SetBaseType::Value Value;
258  typedef typename SetBaseType::Item Item;
259  typedef typename SetBaseType::IterKey IterKey;
260  typedef typename SetBaseType::IterItem IterItem;
261 #else
262  using typename Set<TKey,TSize>::SetBaseType;
263  using typename Set<TKey,TSize>::Size;
264  using typename Set<TKey,TSize>::Key;
265  using typename Set<TKey,TSize>::Value;
266  using typename Set<TKey,TSize>::Item;
267  using typename Set<TKey,TSize>::IterKey;
268  using typename Set<TKey,TSize>::IterItem;
269 #endif
271  typedef TCompare Compare;
272 
275 
278  { }
279 
286  SetList(const SetBaseType& src)
287  { set(src); }
288 
294  SetList(const ThisType& src) : data_(src.data_)
295  { SetBaseType::size_ = src.size_; }
296 
299  { }
300 
301 #if defined(EVO_CPP11)
302 
305  SetList(std::initializer_list<Value> init) : SetList() {
306  assert( init.size() < IntegerT<Size>::MAX );
307  capacitymin((Size)init.size());
308  for (const auto& val : init)
309  add(val);
310  }
311 
315  SetList(ThisType&& src) : data_(std::move(src.data_)) {
316  SetBaseType::size_ = src.SetBaseType::size_;
317  src.SetBaseType::size_ = 0;
318  }
319 
324  ThisType& operator=(ThisType&& src) {
325  data_ = std::move(src.data_);
326  SetBaseType::size_ = src.SetBaseType::size_;
327  src.SetBaseType::size_ = 0;
328  return *this;
329  }
330 #endif
331 
333  const ThisType& asconst() const {
334  return *this;
335  }
336 
337  // SET
338 
340  ThisType& operator=(const SetBaseType& src)
341  { set(src); return *this; }
342 
344  ThisType& operator=(const ThisType& src)
345  { set(src); return *this; }
346 
347  ThisType& set() {
348  data_.items.set();
349  SetBaseType::size_ = 0;
350  return *this;
351  }
352 
354  ThisType& set(const SetBaseType& src) {
355  clear();
356  for (typename SetBaseType::Iter iter(src); iter; ++iter)
357  add(*iter);
358  return *this;
359  }
360 
362  ThisType& set(const ThisType& src) {
363  ((Compare&)data_) = (const Compare&)src.data_;
364  data_.items.set(src.data_.items);
365  SetBaseType::size_ = src.size_;
366  return *this;
367  }
368 
369  ThisType& setempty() {
370  data_.items.setempty();
371  SetBaseType::size_ = 0;
372  return *this;
373  }
374 
375  ThisType& clear() {
376  data_.items.clear();
377  SetBaseType::size_ = 0;
378  return *this;
379  }
380 
381  // INFO
382 
383  bool null() const
384  { return data_.items.null(); }
385 
386  bool shared() const
387  { return data_.items.shared(); }
388 
389  Size capacity() const
390  { return data_.items.capacity(); }
391 
392  bool ordered() const
393  { return true; }
394 
395  // COMPARE
396 
400  const Compare& get_compare() const
401  { return data_; }
402 
406  Compare& get_compare()
407  { return data_; }
408 
409  using SetBaseType::operator==;
410  using SetBaseType::operator!=;
411 
413  bool operator==(const ThisType& set) const
414  { return (this == &set || data_.items == set.data_.items); }
415 
417  bool operator!=(const ThisType& set) const
418  { return (this != &set && data_.items != set.data_.items); }
419 
420  // FIND
421 
423  Iter cbegin() const
424  { return Iter(*this); }
425 
427  Iter cend() const
428  { return Iter(); }
429 
431  IterM begin()
432  { return IterM(*this); }
433 
435  Iter begin() const
436  { return Iter(*this); }
437 
439  IterM end()
440  { return IterM(); }
441 
443  Iter end() const
444  { return Iter(); }
445 
446  bool contains(const Value& value) const
447  { Size i = 0; return (search(i, value) != NULL); }
448 
450  Iter iter(const Value& value) const {
451  IterKey iterkey;
452  const Item* item = search(iterkey.a, value);
453  return (item != NULL ? Iter(*this, iterkey, (IterItem*)item) : Iter(*this, iterEND));
454  }
455 
466  Iter iter_lower(const Value& value) const {
467  IterKey iterkey;
468  const Item* item = search(iterkey.a, value);
469  if (item != NULL)
470  return Iter(*this, iterkey, (IterItem*)item);
471  if (iterkey.a < data_.items.size())
472  return Iter(*this, iterkey, (IterItem*)&data_.items.item(iterkey.a));
473  return Iter(*this, iterEND);
474  }
475 
486  IterM iter_lowerM(const Value& value) {
487  IterKey iterkey;
488  const Item* item = search(iterkey.a, value);
489  if (item != NULL)
490  return IterM(*this, iterkey, (IterItem*)item);
491  if (iterkey.a < data_.items.size())
492  return IterM(*this, iterkey, (IterItem*)&data_.items.item(iterkey.a));
493  return IterM(*this, iterEND);
494  }
495 
504  Iter iter_upper(const Value& value) const {
505  IterKey iterkey;
506  if (search(iterkey.a, value) != NULL)
507  ++iterkey.a;
508  if (iterkey.a < data_.items.size())
509  return Iter(*this, iterkey, (IterItem*)&data_.items.item(iterkey.a));
510  return Iter(*this, iterEND);
511  }
512 
521  IterM iter_upperM(const Value& value) {
522  IterKey iterkey;
523  if (search(iterkey.a, value) != NULL)
524  ++iterkey.a;
525  if (iterkey.a < data_.items.size())
526  return IterM(*this, iterkey, (IterItem*)&data_.items.item(iterkey.a));
527  return IterM(*this, iterEND);
528  }
529 
531  IterM iterM(const Value& value) {
532  IterKey iterkey;
533  const Item* item = search(iterkey.a, value);
534  return (item != NULL ? IterM(*this, iterkey, (IterItem*)item) : IterM(*this, iterEND));
535  }
536 
537  Value& get(const Value& value, bool* created=NULL) {
538  Item* item;
539  Size pos;
540  if ( (item=(Item*)search(pos, value)) == NULL) {
541  item = &(data_.items.itemM(data_.items.insert(pos, &value, 1)));
542  if (created != NULL)
543  *created = true;
545  } else if (created != NULL)
546  *created = false;
547  return *item;
548  }
549 
556  const Value& item(Size index) const
557  { return data_.items.item(index); }
558 
559  // INFO_SET
560 
561  ThisType& unshare()
562  { data_.items.unshare(); return *this; }
563 
564  ThisType& capacity(Size size)
565  { data_.items.capacity(size); return *this; }
566 
567  ThisType& capacitymin(Size min)
568  { data_.items.capacitymin(min); return *this; }
569 
571  ThisType& reserve(Size size)
572  { data_.items.reserve(size); return *this; }
573 
574  ThisType& compact()
575  { data_.items.compact(); return *this; }
576 
577  // ADD
578 
579  Value& add(const Value& item, bool update=false) {
580  bool created_val;
581  Value& upditem = get(item, &created_val);
582  if (!created_val && update)
583  upditem = item;
584  return upditem;
585  }
586 
587  // REMOVE
588 
589  bool remove(const Value& value) {
590  Size index;
591  if (search(index, value) != NULL) {
592  data_.items.remove(index);
594  return true;
595  }
596  return false;
597  }
598 
606  Size remove(const Value& value, Size count) {
607  Size index;
608  if (count > 0 && search(index, value) != NULL) {
609  count = data_.items.remove(index, count);
610  SetBaseType::size_ -= count;
611  return count;
612  }
613  return 0;
614  }
615 
616  bool remove(typename SetBaseType::IterM& iter, IteratorDir dir=iterNONE)
617  { return remove((IterM&)iter, dir); }
618 
620  bool remove(IterM& iter, IteratorDir dir=iterNONE) {
621  if (iter && this == &iter.getParent()) {
622  IterKey& iterkey = iter.getKey();
623  data_.items.remove(iterkey.a);
624  bool nextitem = false;
625  if (--SetBaseType::size_ > 0 && dir != iterNONE) {
626  if (dir == iterRV) {
627  if (iterkey.a > 0)
628  { --iterkey.a; nextitem = true; }
629  } else if (iterkey.a < data_.items.size())
630  nextitem = true;
631  }
632  if (nextitem)
633  iter.setData( (IterItem*)&data_.items.item(iterkey.a) );
634  else
635  iter = iterEND;
636  return true;
637  }
638  return false;
639  }
640 
649  Size removeat(Size index, Size count=1) {
650  assert( index < data_.items.size() );
651  count = data_.items.remove(index, count);
652  SetBaseType::size_ -= count;
653  return count;
654  }
655 
665  Size remove_range(IterM& start, Size count) {
666  if (count > 0 && start && this == &start.getParent()) {
667  count = data_.items.remove(start.index().a, count);
668  SetBaseType::size_ -= count;
669  if (start.index().a >= SetBaseType::size_)
670  start = iterEND;
671  return count;
672  }
673  return 0;
674  }
675 
685  Size remove_range(IterM& start, IterM& end) {
686  if (start && this == &start.getParent()) {
687  const Size index = start.index().a;
688  if (end) {
689  if (this == &end.getParent()) {
690  const Size end_index = end.index().a;
691  if (end_index > index) {
692  const Size count = data_.items.remove(index, end_index - index);
693  SetBaseType::size_ -= count;
694  end = iterEND;
695  return count;
696  }
697  }
698  } else {
699  const Size count = data_.items.remove(index, ALL);
700  SetBaseType::size_ -= count;
701  start = iterEND;
702  return count;
703  }
704  }
705  return 0;
706  }
707 
708  // INTERNAL
709 
710  // Iterator support methods
712  void iterInitMutable()
713  { data_.items.iterInitMutable(); }
714  const IterItem* iterFirst(IterKey& key) const
715  { return (IterItem*)data_.items.iterFirst(key.a); }
716  const IterItem* iterNext(IterKey& key) const
717  { return (IterItem*)data_.items.iterNext(key.a); }
718  const IterItem* iterNext(Size count, IterKey& key) const
719  { return (IterItem*)data_.items.iterNext(count, key.a); }
720  const IterItem* iterLast(IterKey& key) const
721  { return (IterItem*)data_.items.iterLast(key.a); }
722  const IterItem* iterPrev(IterKey& key) const
723  { return (IterItem*)data_.items.iterPrev(key.a); }
726 protected:
727  const Value* getiter(IterKey& iterkey, const Value& value) const
728  { return search(iterkey.a, value); }
729 
730 private:
731  // Use inheritance to reduce size bloat with empty Compare
732  struct Data : public TCompare {
733  using TCompare::operator();
734 
735  List<Item> items;
736 
737  Data()
738  { }
739  Data(const Data& data) : TCompare(data), items(data.items)
740  { }
741  #if defined(EVO_CPP11)
742  Data(Data&& data) : TCompare(std::move(data)), items(std::move(data.items))
743  { }
744 
745  Data& operator=(Data&& data) {
746  ((TCompare&)*this) = std::move((TCompare&)data);
747  items = std::move(data.items);
748  return *this;
749  }
750  #endif
751  };
752 
753  Data data_;
754 
755  const Value* search(Size& index, const Value& value) const {
756  int cmp;
757  Size left = 0, right = data_.items.size(), mid = 0;
758  while (left < right) {
759  mid = left + ((right - left) / 2);
760  const Value& item = data_.items.item(mid);
761  cmp = data_(value, item);
762  if (cmp < 0) {
763  right = mid;
764  } else if (cmp == 0) {
765  index = mid;
766  return &item;
767  } else
768  left = mid + 1;
769  }
770  index = left;
771  return NULL;
772  }
773 };
774 
776 
777 #if defined(INCL_evo_string_h) || defined(DOXYGEN)
778 
783 #endif
784 
786 
787 }
788 #endif
ThisType & operator=(ThisType &&src)
Move assignment operator (C++11).
Definition: setlist.h:324
Associative container with unique values for fast lookup.
Definition: set.h:119
~SetList()
Destructor.
Definition: setlist.h:298
IterM iter_lowerM(const Value &value)
Find first value greater or equal to given value (lower bound).
Definition: setlist.h:486
ThisType & operator=(const ThisType &src)
Assignment operator.
Definition: setlist.h:344
SetList()
Default constructor.
Definition: setlist.h:277
Evo Set interface.
#define EVO_CONTAINER_TYPE
Identify current class/struct as an EvoContainer.
Definition: meta.h:482
TKey Item
Item type (same as Value)
Definition: set.h:127
bool shared() const
Get whether shared.
Definition: setlist.h:386
Random access iterator.
Definition: iter.h:904
Set< TKey, TSize > SetBaseType
Set base type
Definition: set.h:123
IterM begin()
Get iterator at first item (mutable).
Definition: setlist.h:431
SetList(const SetBaseType &src)
Copy constructor.
Definition: setlist.h:286
IterM iter_upperM(const Value &value)
Find first value greater than given value (upper bound).
Definition: setlist.h:521
ThisType & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: setlist.h:561
Size size() const
Get set size (number of items).
Definition: set.h:230
TCompare Compare
Compare type to use
Definition: setlist.h:271
Iter iter(const Value &value) const
Find (lookup) iterator for given value (const).
Definition: setlist.h:450
Iter iter_lower(const Value &value) const
Find first value greater or equal to given value (lower bound) (const).
Definition: setlist.h:466
ThisType & capacity(Size size)
Set capacity for set (modifier).
Definition: setlist.h:564
ThisType & compact()
Reduce capacity to fit current size (modifier).
Definition: setlist.h:574
Iter iter_upper(const Value &value) const
Find first value greater than given value (upper bound) (const).
Definition: setlist.h:504
Basic integer type.
Definition: type.h:980
const Compare & get_compare() const
Get comparison object being used for comparisons (const).
Definition: setlist.h:400
IterM iterM(const Value &value)
Find (lookup) iterator for given value (mutable).
Definition: setlist.h:531
Size size_
Set size (number of items, automatically updated by concrete set members)
Definition: set.h:146
Size remove_range(IterM &start, IterM &end)
Remove range of values using iterators (mutable).
Definition: setlist.h:685
Size remove_range(IterM &start, Size count)
Remove range of values using iterator (mutable).
Definition: setlist.h:665
SetList< String > StrSetList
SetList using String values.
Definition: setlist.h:782
SetList(ThisType &&src)
Move constructor (C++11).
Definition: setlist.h:315
IterM end()
Get iterator at end.
Definition: setlist.h:439
String container.
Definition: string.h:674
bool contains(const Value &value) const
Get whether the set contains the given value.
Definition: setlist.h:446
Bidirectional iterator.
Definition: iter.h:611
Evo List container.
static const EndT ALL
Special integer value for indicating all items or all remaining items.
Definition: type.h:1839
bool operator==(const ThisType &set) const
Equality operator.
Definition: setlist.h:413
IteratorDir
Iterator direction value.
Definition: iter.h:27
Iter cend() const
Get iterator at end (const).
Definition: setlist.h:427
Iter cbegin() const
Get iterator at first item (const).
Definition: setlist.h:423
Reverse iterator direction.
Definition: iter.h:30
Evo C++ Library namespace.
Definition: alg.h:11
No iterator direction.
Definition: iter.h:28
Iter end() const
Get iterator at end (const).
Definition: setlist.h:443
ThisType & operator=(const SetBaseType &src)
Assignment operator.
Definition: setlist.h:340
bool null() const
Get whether set is null.
Definition: setlist.h:383
Size capacity() const
Get set capacity.
Definition: setlist.h:389
TKey Key
Key type (same as Value)
Definition: set.h:125
SizeT Size
Size type for size values (must be unsigned integer) – default: SizeT.
Definition: set.h:124
IteratorRa< ThisType >::Const Iter
Iterator (const) - IteratorRa.
Definition: setlist.h:273
ThisType & reserve(Size size)
Reserve space for new items.
Definition: setlist.h:571
Size removeat(Size index, Size count=1)
Remove value(s) at given position/index (mutable).
Definition: setlist.h:649
End iterator position.
Definition: iter.h:23
TKey Value
Value type.
Definition: set.h:126
ThisType & clear()
Clear by removing all items.
Definition: setlist.h:375
Set implemented as an ordered sequential array/list.
Definition: setlist.h:250
ThisType & capacitymin(Size min)
Set capacity to at least given minimum for set (modifier).
Definition: setlist.h:567
Value & add(const Value &item, bool update=false)
Add or update using given item.
Definition: setlist.h:579
Iter begin() const
Get iterator at first item (const).
Definition: setlist.h:435
const ThisType & asconst() const
Explicitly use a const reference to this.
Definition: setlist.h:333
SetList(std::initializer_list< Value > init)
Sequence constructor (C++11).
Definition: setlist.h:305
const Value * getiter(IterKey &iterkey, const Value &value) const
Used by base class to get data to initialize iterator.
Definition: setlist.h:727
SetList< TKey, TCompare, TSize > ThisType
This type.
Definition: setlist.h:270
const Value & item(Size index) const
Get item value at position (const).
Definition: setlist.h:556
T & min(T &a, T &b)
Returns lowest of given values.
Definition: alg.h:26
IteratorRa< ThisType > IterM
Iterator (mutable) - IteratorRa.
Definition: setlist.h:274
Compare & get_compare()
Get comparison object being used for comparisons.
Definition: setlist.h:406
SetList(const ThisType &src)
Copy constructor.
Definition: setlist.h:294
bool operator!=(const ThisType &set) const
Inequality operator.
Definition: setlist.h:417
bool ordered() const
Get whether set is ordered.
Definition: setlist.h:392
ThisType & setempty()
Set as empty but not null.
Definition: setlist.h:369