Evo C++ Library v0.5.1
sublist.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_sublist_h
9 #define INCL_evo_sublist_h
10 
11 #include "impl/container.h"
12 #include "impl/iter.h"
13 
14 namespace evo {
17 
19 
144 template<class T,class TSize=SizeT>
145 struct SubList : public ListBase<T,TSize> {
148 
150  typedef TSize Size;
151  typedef Size Key;
152  typedef T Value;
153  typedef T Item;
154  typedef typename DataCopy<T>::PassType ItemVal;
155 
159 
160  // Iterator support types
162  typedef Key IterKey;
163  typedef T IterItem;
167 
170  data_ = NULL;
171  size_ = 0;
172  }
173 
180  SubList(const ThisType& data) {
181  data_ = data.data_;
182  size_ = data.size_;
183  }
184 
191  SubList(const ListBaseType& data) {
192  data_ = data.data_;
193  size_ = data.size_;
194  }
195 
204  SubList(const ListBaseType& data, Key index, Size size=ALL) {
205  if (data.data_ == NULL) {
206  data_ = NULL;
207  size_ = 0;
208  } else {
209  if (index > data.size_)
210  index = data.size_;
211  const Size max_size = data.size_ - index;
212  data_ = (Item*)data.data_ + index;
213  size_ = (size > max_size ? max_size : size);
214  }
215  }
216 
223  SubList(const ListBaseType* data) {
224  if (data == NULL) {
225  data_ = NULL;
226  size_ = 0;
227  } else {
228  data_ = data->data_;
229  size_ = data->size_;
230  }
231  }
232 
237  SubList(const Item* data, Size size) {
238  data_ = (Item*)data;
239  size_ = size;
240  }
241 
256  SubList(const Item* data, ValNull v, ItemVal term=0) {
257  EVO_PARAM_UNUSED(v);
258  data_ = (Item*)data;
259  size_ = 0;
260  if (data != NULL)
261  while (!(data[size_] == term))
262  ++size_;
263  }
264 
265 #if defined(EVO_CPP11)
266 
269  SubList(ThisType&& src) {
270  ::memcpy(this, &src, sizeof(ThisType));
271  }
272 
277  ThisType& operator=(ThisType&& src) {
278  ::memcpy(this, &src, sizeof(ThisType));
279  return *this;
280  }
281 #endif
282 
288  const ThisType& asconst() const {
289  return *this;
290  }
291 
292  // SET
293 
298  ThisType& operator=(const ThisType& src) {
299  ::memcpy(this, &src, sizeof(ThisType));
300  return *this;
301  }
302 
307  ThisType& operator=(const ValNull& val) {
308  EVO_PARAM_UNUSED(val);
309  data_ = NULL;
310  size_ = 0;
311  return *this;
312  }
313 
318  ThisType& operator=(const ValEmpty& val) {
319  EVO_PARAM_UNUSED(val);
320  data_ = NULL;
321  size_ = 0;
322  return *this;
323  }
324 
332  ThisType& operator=(const ListBaseType& data) {
333  data_ = data.data_;
334  size_ = data.size_;
335  return *this;
336  }
337 
345  ThisType& operator=(const ListBaseType* data) {
346  if (data == NULL) {
347  data_ = NULL;
348  size_ = 0;
349  } else {
350  data_ = data->data_;
351  size_ = data->size_;
352  }
353  return *this;
354  }
355 
361  ThisType& clear() {
362  if (size_ > 0) {
363  data_ = EVO_PEMPTY;
364  size_ = 0;
365  }
366  return *this;
367  }
368 
372  ThisType& set() {
373  data_ = NULL;
374  size_ = 0;
375  return *this;
376  }
377 
385  ThisType& set(const ListBaseType& data) {
386  data_ = data.data_;
387  size_ = data.size_;
388  return *this;
389  }
390 
400  ThisType& set(const ListBaseType& data, Key index, Key size=ALL) {
401  if (data.data_ == NULL) {
402  data_ = NULL;
403  size_ = 0;
404  } else {
405  if (index > data.size_)
406  index = data.size_;
407  const Size max_size = data.size_ - index;
408  data_ = (Item*)data.data_ + index;
409  size_ = (size > max_size ? max_size : size);
410  }
411  return *this;
412  }
413 
421  ThisType& set(const ListBaseType* data) {
422  if (data == NULL)
423  set();
424  else
425  set(*data);
426  return *this;
427  }
428 
433  ThisType& set(const Item* data, Size size) {
434  data_ = (Item*)data;
435  size_ = size;
436  return *this;
437  }
438 
450  ThisType& set2(const ListBaseType& data, Key index1, Key index2) {
451  if (data.data_ == NULL) {
452  data_ = NULL;
453  size_ = 0;
454  } else {
455  if (index1 > data.size_)
456  index1 = data.size_;
457  data_ = (Item*)data.data_ + index1;
458  if (index2 > data.size_)
459  size_ = data.size_ - index1;
460  else if (index2 <= index1)
461  size_ = 0;
462  else
463  size_ = index2 - index1;
464  }
465  return *this;
466  }
467 
471  ThisType& setempty()
472  { data_ = EVO_PEMPTY; size_ = 0; return *this; }
473 
474  // INFO
475 
477  bool null() const
478  { return (data_ == NULL); }
479 
481  bool empty() const
482  { return (size_ == 0); }
483 
485  Size size() const
486  { return size_; }
487 
494  bool shared() const
495  { return false; }
496 
502  const Item* data() const
503  { return data_; }
504 
511  const Item& operator[](Key index) const {
512  assert( index < size_ );
513  return data_[index];
514  }
515 
522  const Item& item(Key index) const {
523  assert( index < size_ );
524  return data_[index];
525  }
526 
528  const Item* first() const
529  { return (size_ > 0 ? data_ : NULL); }
530 
532  const Item* last() const
533  { return (size_ > 0 ? data_+size_-1 : NULL); }
534 
536  Key iend(Size offset=0) const
537  { return (offset >= size_ ? END : size_ - 1 - offset); }
538 
540  ulong hash(ulong seed=0) const
541  { return DataHash<Item>::hash(data_, size_, seed); }
542 
543  // COMPARE
544 
546  int compare(const ListBaseType& data) const {
547  int result;
548  if (data_ == NULL)
549  result = (data.data_ != NULL ? -1 : 0);
550  else if (data.data_ == NULL)
551  result = 1;
552  else
553  result = DataCompare<Item>::compare(data_, size_, data.data_, data.size_);
554  return result;
555  }
556 
558  bool operator==(const ListBaseType& data) const {
559  bool result;
560  if (data_ == NULL)
561  result = (data.data_ == NULL);
562  else if (data.data_ == NULL)
563  result = false;
564  else
565  result = (DataCompare<Item>::compare(data_, size_, data.data_, data.size_) == 0);
566  return result;
567  }
568 
570  bool operator!=(const ListBaseType& data) const {
571  bool result;
572  if (data_ == NULL)
573  result = (data.data_ != NULL);
574  else if (data.data_ == NULL)
575  result = true;
576  else
577  result = (DataCompare<Item>::compare(data_, size_, data.data_, data.size_) != 0);
578  return result;
579  }
580 
582  bool starts(ItemVal item) const
583  { return (size_ > 0 && *data_ == item); }
584 
586  bool starts(const Item* items, Size size) const
587  { return (size > 0 && size_ >= size && DataEqual<Item>::equal(data_, items, size)); }
588 
590  bool starts(const ListBaseType& items) const
591  { return (items.size_ > 0 && size_ >= items.size_ && DataEqual<Item>::equal(data_, items.data_, items.size_)); }
592 
594  bool ends(ItemVal item) const
595  { return (size_ > 0 && data_[size_-1] == item); }
596 
598  bool ends(const Item* items, Size size) const
599  { return (size > 0 && size_ >= size && DataEqual<Item>::equal(data_+size_-size, items, size)); }
600 
602  bool ends(const ListBaseType& items) const
603  { return (items.size_ > 0 && size_ >= items.size_ && DataEqual<Item>::equal(data_+size_-items.size_, items.data_, items.size_)); }
604 
605  // FIND
606 
613  Iter cbegin() const
614  { return Iter(*this); }
615 
623  Iter cend() const
624  { return Iter(); }
625 
632  Iter begin() const
633  { return Iter(*this); }
634 
642  Iter end() const
643  { return Iter(); }
644 
646  Key find(ItemVal item, Key start=0, Key end=END) const {
647  if (end > size_)
648  end = size_;
649  for (; start<end; ++start)
650  if (data_[start] == item)
651  return start;
652  return (Key)NONE;
653  }
654 
656  Key findr(ItemVal item, Key start=0, Key end=END) const {
657  if (end > size_)
658  end = size_;
659  while (end>start)
660  if (data_[--end] == item)
661  return end;
662  return (Key)NONE;
663  }
664 
666  Key findany(const Item* items, Size count, Key start=0, Key end=END) const {
667  Size j;
668  if (end > size_)
669  end = size_;
670  for (; start<end; ++start)
671  for (j=0; j<count; ++j)
672  if (data_[start] == items[j])
673  return start;
674  return (Key)NONE;
675  }
676 
678  Key findanyr(const Item* items, Size count, Key start=0, Key end=END) const {
679  Size j;
680  if (end > size_)
681  end = size_;
682  while (end>start) {
683  --end;
684  for (j=0; j<count; ++j)
685  if (data_[end] == items[j])
686  return end;
687  }
688  return (Key)NONE;
689  }
690 
692  bool contains(ItemVal item) const {
693  bool result = false;
694  for (Key i=0; i<size_; ++i)
695  if (data_[i] == item)
696  { result = true; break; }
697  return result;
698  }
699 
701  bool contains(const Item* data, Size size) const {
702  bool result = false;
703  if (size > 0 && size_ >= size) {
704  const Size end = size_ - size;
705  for (Key i=0; i<=end; ++i)
706  if (DataEqual<Item>::equal(data_+i, data, size))
707  { result = true; break; }
708  }
709  return result;
710  }
711 
713  bool contains(const ListBaseType& data) const {
714  bool result = false;
715  if (data.size_ > 0 && size_ >= data.size_) {
716  const Size end = size_ - data.size_;
717  for (Key i=0; i<=end; ++i)
718  if (DataEqual<Item>::equal(data_+i, data.data_, data.size_))
719  { result = true; break; }
720  }
721  return result;
722  }
723 
724  // SPLIT
725 
727  template<class T1,class T2>
728  bool splitat(Key index, T1& left, T2& right) const {
729  bool result = false;
730  if (index >= size_) {
731  left.set(*this);
732  right.set();
733  } else {
734  left.set(*this, 0, index);
735  right.set(*this, index+1, size_-index-1);
736  result = true;
737  }
738  return result;
739  }
740 
742  template<class T1>
743  bool splitat(Key index, T1& left) const {
744  bool result = false;
745  if (index >= size_)
746  left.set(*this);
747  else {
748  left.set(*this, 0, index);
749  result = true;
750  }
751  return result;
752  }
753 
755  template<class T2>
756  bool splitat(Key index, ValNull left, T2& right) const {
757  EVO_PARAM_UNUSED(left);
758  bool result = false;
759  if (index >= size_)
760  right.set();
761  else {
762  right.set(*this, index+1, size_-index-1);
763  result = true;
764  }
765  return result;
766  }
767 
769  bool splitat_setl(Key index) {
770  bool result = false;
771  if (index < size_) {
772  set(data_, index);
773  result = true;
774  }
775  return result;
776  }
777 
779  template<class T2>
780  bool splitat_setl(Key index, T2& right) {
781  bool result = false;
782  if (index >= size_) {
783  right.set();
784  } else {
785  right.set(*this, index+1, size_-index-1);
786  set(data_, index);
787  result = true;
788  }
789  return result;
790  }
791 
793  bool splitat_setr(Key index) {
794  bool result = false;
795  if (index >= size_)
796  set();
797  else {
798  set(data_+index+1, size_-index-1);
799  result = true;
800  }
801  return result;
802  }
803 
805  template<class T1>
806  bool splitat_setr(Key index, T1& left) {
807  bool result = false;
808  if (index >= size_) {
809  left.set(*this);
810  set();
811  } else {
812  left.set(*this, 0, index);
813  set(data_+index+1, size_-index-1);
814  result = true;
815  }
816  return result;
817  }
818 
819  // TRIM
820 
822  ThisType& triml(Size size) {
823  if (size < size_) {
824  size_ -= size;
825  data_ += size;
826  } else if (size_ > 0) {
827  data_ = EVO_PEMPTY;
828  size_ = 0;
829  }
830  return *this;
831  }
832 
834  ThisType& trimr(Size size) {
835  if (size < size_) {
836  size_ -= size;
837  } else if (size_ > 0) {
838  data_ = EVO_PEMPTY;
839  size_ = 0;
840  }
841  return *this;
842  }
843 
845  ThisType& truncate(Size size) {
846  if (size < size_) {
847  if (size == 0)
848  data_ = EVO_PEMPTY;
849  size_ = size;
850  }
851  return *this;
852  }
853 
854  // SLICE
855 
863  ThisType& slice(Key index) {
864  if (index < size_) {
865  data_ += index;
866  size_ -= index;
867  } else if (size_ > 0) {
868  data_ = EVO_PEMPTY;
869  size_ = 0;
870  }
871  return *this;
872  }
873 
882  ThisType& slice(Key index, Size size) {
883  if (index < size_) {
884  data_ += index;
885  const Size maxsize = size_ - index;
886  if (size > maxsize)
887  size_ = maxsize;
888  else
889  size_ = size;
890  } else if (size_ > 0) {
891  data_ = EVO_PEMPTY;
892  size_ = 0;
893  }
894  return *this;
895  }
896 
906  ThisType& slice2(Key index1, Key index2)
907  { return slice(index1, (index1 < index2 ? index2-index1 : 0)); }
908 
909  // UNSHARE
910 
917  ThisType& unshare()
918  { return *this; }
919 
920  // SWAP
921 
925  void swap(ThisType& list)
926  { EVO_IMPL_CONTAINER_SWAP(this, &list, ThisType); }
927 
928  // INTERNAL
929 
930  // Iterator support methods
932  void iterInitMutable()
933  { }
934  const IterItem* iterFirst(IterKey& key) const
935  { key = 0; return data_; }
936  const IterItem* iterNext(IterKey& key) const {
937  const IterItem* result = NULL;
938  if (key != END) {
939  if (++key < size_)
940  result = data_ + key;
941  else
942  key = END;
943  }
944  return result;
945  }
946  const IterItem* iterNext(Size count, IterKey& key) const {
947  const IterItem* result = NULL;
948  if (key != END) {
949  if ( (key+=count) < size_ )
950  result = data_ + key;
951  else
952  key = END;
953  }
954  return result;
955  }
956  const IterItem* iterLast(IterKey& key) const {
957  const IterItem* result = NULL;
958  if (size_ > 0) {
959  key = size_ - 1;
960  result = data_ + key;
961  }
962  return result;
963  }
964  const IterItem* iterPrev(IterKey& key) const {
965  const IterItem* result = NULL;
966  if (key != END) {
967  if (key > 0)
968  result = data_ + --key;
969  else
970  key = END;
971  }
972  return result;
973  }
974  const IterItem* iterPrev(Size count, IterKey& key) const {
975  const IterItem* result = NULL;
976  if (key != END) {
977  if (key > 0 && count <= key)
978  result = data_ + (key-=count);
979  else
980  key = END;
981  }
982  return result;
983  }
984  Size iterCount() const
985  { return size_; }
986  const IterItem* iterSet(IterKey key) const {
987  const IterItem* result = NULL;
988  if (key < size_)
989  result = data_ + key;
990  return result;
991  }
993 };
994 
996 
997 }
998 #endif
Iter end() const
Get iterator at end (const).
Definition: sublist.h:642
SubList(const ListBaseType &data, Key index, Size size=ALL)
Copy constructor to reference source data.
Definition: sublist.h:204
bool splitat_setr(Key index)
Split at index and set as right sublist.
Definition: sublist.h:793
bool splitat(Key index, T1 &left) const
Split into left sublist at index.
Definition: sublist.h:743
Size size() const
Get size.
Definition: sublist.h:485
bool contains(const ListBaseType &data) const
Check if contains given data.
Definition: sublist.h:713
IteratorRa< ThisType >::Const Iter
Iterator (const) - IteratorRa.
Definition: sublist.h:166
T Value
Value type (same as Item)
Definition: sublist.h:152
bool starts(const ListBaseType &items) const
Check if this starts with given items.
Definition: sublist.h:590
bool contains(ItemVal item) const
Check whether contains given item.
Definition: sublist.h:692
ValEmpty
Special empty value type, pass as vEMPTY.
Definition: sys.h:1101
ThisType & operator=(const ValEmpty &val)
Assignment operator sets as null.
Definition: sublist.h:318
Key findany(const Item *items, Size count, Key start=0, Key end=END) const
Find first occurrence of any given items with forward search.
Definition: sublist.h:666
Key find(ItemVal item, Key start=0, Key end=END) const
Find first occurrence of item with forward search.
Definition: sublist.h:646
SubList< T, Size > ThisType
This list type.
Definition: sublist.h:156
#define EVO_CONTAINER_TYPE
Identify current class/struct as an EvoContainer.
Definition: meta.h:482
Key findanyr(const Item *items, Size count, Key start=0, Key end=END) const
Find last occurrence of any given items with reverse search.
Definition: sublist.h:678
bool splitat_setl(Key index)
Split at index and set as left sublist.
Definition: sublist.h:769
bool splitat(Key index, T1 &left, T2 &right) const
Split into left/right sublists at index.
Definition: sublist.h:728
int compare(const ListBaseType &data) const
Comparison.
Definition: sublist.h:546
const Item & operator[](Key index) const
Get item at position.
Definition: sublist.h:511
Size Key
Key type (item index)
Definition: sublist.h:151
Random access iterator.
Definition: iter.h:904
ValNull
Unique null value type and value (vNULL).
Definition: sys.h:1096
SubList(const ListBaseType *data)
Copy constructor to reference source data from pointer.
Definition: sublist.h:223
SubList(ThisType &&src)
Move constructor (C++11).
Definition: sublist.h:269
const Item * first() const
Get first item (const).
Definition: sublist.h:528
SubList(const ThisType &data)
Copy constructor to reference source data.
Definition: sublist.h:180
ThisType & slice(Key index)
Slice beginning items.
Definition: sublist.h:863
bool operator==(const ListBaseType &data) const
Equality operator.
Definition: sublist.h:558
bool contains(const Item *data, Size size) const
Check if contains given data.
Definition: sublist.h:701
SubList()
Default constructor sets as null.
Definition: sublist.h:169
SubList(const ListBaseType &data)
Copy constructor to reference source data.
Definition: sublist.h:191
ThisType & operator=(const ThisType &src)
Assignment operator.
Definition: sublist.h:298
ThisType & set2(const ListBaseType &data, Key index1, Key index2)
Set as reference to subset of source data using start/end positions.
Definition: sublist.h:450
const Item * data() const
Get data pointer.
Definition: sublist.h:502
bool starts(ItemVal item) const
Check if this starts with given item.
Definition: sublist.h:582
void swap(ThisType &list)
Swap with another sublist.
Definition: sublist.h:925
Iter cend() const
Get iterator at end (const).
Definition: sublist.h:623
ThisType & operator=(const ListBaseType *data)
Assignment operator sets as reference to source data from pointer.
Definition: sublist.h:345
ThisType & clear()
Clear by removing all items.
Definition: sublist.h:361
bool ends(const ListBaseType &items) const
Check if this ends with given items.
Definition: sublist.h:602
ThisType & setempty()
Set as empty but not null.
Definition: sublist.h:471
#define EVO_PEMPTY
Special pointer value for empty but not NULL (used in containers).
Definition: type.h:1858
bool shared() const
Get whether shared (false).
Definition: sublist.h:494
Data equality helper.
Definition: container.h:712
ThisType & operator=(const ValNull &val)
Assignment operator sets as null.
Definition: sublist.h:307
TSize Size
List size integer type.
Definition: sublist.h:150
Key findr(ItemVal item, Key start=0, Key end=END) const
Find last occurrence of item with reverse search.
Definition: sublist.h:656
Evo implementation detail: Container iterators.
const ThisType & asconst() const
Explicitly use a const reference to this.
Definition: sublist.h:288
T Item
Item type (same as Value)
Definition: sublist.h:153
ThisType & unshare()
Make data unique – no-op.
Definition: sublist.h:917
static const EndT END
Special integer value for indicating end of items or no item.
Definition: type.h:1846
const Item & item(Key index) const
Get item at position.
Definition: sublist.h:522
static const EndT ALL
Special integer value for indicating all items or all remaining items.
Definition: type.h:1839
bool operator!=(const ListBaseType &data) const
Inequality operator.
Definition: sublist.h:570
Evo container foundation types and macros.
static ulong hash(const T *data, ulong size, ulong seed=0)
Compute hash value from data.
Definition: container.h:899
bool starts(const Item *items, Size size) const
Check if starts with given items.
Definition: sublist.h:586
bool splitat(Key index, ValNull left, T2 &right) const
Split into right sublist at index.
Definition: sublist.h:756
ThisType & operator=(const ListBaseType &data)
Assignment operator sets as reference to source data.
Definition: sublist.h:332
ListBase< T, Size > ListBaseType
List base type for any Evo list
Definition: sublist.h:158
Evo C++ Library namespace.
Definition: alg.h:11
static const EndT NONE
Special integer value for indicating no item or unknown item.
Definition: type.h:1832
ulong hash(ulong seed=0) const
Get data hash value.
Definition: sublist.h:540
DataCopy< T >::PassType ItemVal
Item type as parameter (POD types passed by value, otherwise by const-ref)
Definition: sublist.h:154
Iter cbegin() const
Get iterator at first item (const).
Definition: sublist.h:613
bool ends(ItemVal item) const
Check if this ends with given item.
Definition: sublist.h:594
static int compare(const T *data1, ulong size1, const T *data2, ulong size2)
Compare data.
Definition: container.h:769
ThisType & triml(Size size)
Trim left (beginning) items.
Definition: sublist.h:822
T * data_
Data pointer, NULL if null.
Definition: sys.h:979
AddConst< T >::Type & PassType
Most efficient type for passing as parameter (const-reference or POD value).
Definition: container.h:551
bool splitat_setr(Key index, T1 &left)
Split at index, set as right sublist, and save left sublist.
Definition: sublist.h:806
SubList(const Item *data, Size size)
Constructor to reference data pointer.
Definition: sublist.h:237
Reference and access existing list data.
Definition: sublist.h:145
SubList< T, Size > SubListType
SubList base type
Definition: sublist.h:157
SubList(const Item *data, ValNull v, ItemVal term=0)
Constructor to reference terminated data pointer.
Definition: sublist.h:256
ThisType & slice2(Key index1, Key index2)
Slice to given subset using start/end positions.
Definition: sublist.h:906
ThisType & slice(Key index, Size size)
Slice to given subset.
Definition: sublist.h:882
bool splitat_setl(Key index, T2 &right)
Split at index, set as left sublist, and save right sublist.
Definition: sublist.h:780
TSize size_
Data size as item count, 0 if empty or null.
Definition: sys.h:980
Iter begin() const
Get iterator at first item (const).
Definition: sublist.h:632
ThisType & truncate(Size size)
Truncate to given size.
Definition: sublist.h:845
bool ends(const Item *items, Size size) const
Check if this ends with given items.
Definition: sublist.h:598
ThisType & trimr(Size size)
Trim right (ending) items.
Definition: sublist.h:834
ThisType & operator=(ThisType &&src)
Move assignment operator (C++11).
Definition: sublist.h:277
Base for all Evo list types (used internally).
Definition: sys.h:976
Key iend(Size offset=0) const
Get index from last item using offset.
Definition: sublist.h:536
bool empty() const
Get whether empty.
Definition: sublist.h:481
const Item * last() const
Get last item (const).
Definition: sublist.h:532
#define EVO_PARAM_UNUSED(NAME)
Mark function parameter as unused to suppress "unreferenced parameter" compiler warnings on it...
Definition: sys.h:427
bool null() const
Get whether null.
Definition: sublist.h:477