libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
list.h
Go to the documentation of this file.
1
8#pragma once
9
10#include <promeki/config.h>
11#if PROMEKI_ENABLE_CORE
12#include <cstddef>
13#include <vector>
14#include <initializer_list>
15#include <functional>
16#include <algorithm>
17#include <stdexcept>
18#include <promeki/function.h>
19#include <promeki/namespace.h>
20#include <promeki/result.h>
21#include <promeki/sharedptr.h>
22
23PROMEKI_NAMESPACE_BEGIN
24
51template <typename T> class List {
52 PROMEKI_SHARED_FINAL(List)
53 public:
55 using Ptr = SharedPtr<List>;
56
58 using Data = typename std::vector<T>;
59
61 using Iterator = typename std::vector<T>::iterator;
62
64 using ConstIterator = typename std::vector<T>::const_iterator;
65
67 using RevIterator = typename std::vector<T>::reverse_iterator;
68
70 using ConstRevIterator = typename std::vector<T>::const_reverse_iterator;
71
73 using TestFunc = Function<bool(const T &)>;
74
76 List() = default;
77
82 explicit List(size_t size) : d(size) {}
83
89 List(size_t size, const T &defaultValue) : d(size, defaultValue) {}
90
92 List(const List &other) : d(other.d) {}
93
95 List(List &&other) noexcept : d(std::move(other.d)) {}
96
101 List(std::initializer_list<T> initList) : d(initList) {}
102
113 List(const T *first, const T *last) : d(first, last) {}
114
116 ~List() = default;
117
119 List &operator=(const List &other) {
120 d = other.d;
121 return *this;
122 }
123
125 List &operator=(List &&other) noexcept {
126 d = std::move(other.d);
127 return *this;
128 }
129
135 List &operator=(std::initializer_list<T> initList) {
136 d = initList;
137 return *this;
138 }
139
148 template <typename InputIt> void assign(InputIt first, InputIt last) {
149 d.assign(first, last);
150 return;
151 }
152
158 void assign(size_t count, const T &value) {
159 d.assign(count, value);
160 return;
161 }
162
168 List &operator+=(const T &item) {
169 pushToBack(item);
170 return *this;
171 }
172
178 List &operator+=(T &&item) {
179 pushToBack(std::move(item));
180 return *this;
181 }
182
188 List &operator+=(const List &list) {
189 pushToBack(list);
190 return *this;
191 }
192
198 List &operator+=(List &&list) {
199 pushToBack(std::move(list));
200 return *this;
201 }
202
204 Iterator begin() noexcept { return d.begin(); }
205
207 ConstIterator begin() const noexcept { return d.cbegin(); }
208
210 ConstIterator cbegin() const noexcept { return d.cbegin(); }
211
213 ConstIterator constBegin() const noexcept { return d.cbegin(); }
214
216 RevIterator rbegin() noexcept { return d.rbegin(); }
217
219 RevIterator revBegin() noexcept { return d.rbegin(); }
220
222 ConstRevIterator crbegin() const noexcept { return d.crbegin(); }
223
225 ConstRevIterator constRevBegin() const noexcept { return d.crbegin(); }
226
228 Iterator end() noexcept { return d.end(); }
229
231 ConstIterator end() const noexcept { return d.cend(); }
232
234 ConstIterator cend() const noexcept { return d.cend(); }
235
237 ConstIterator constEnd() const noexcept { return d.cend(); }
238
240 RevIterator rend() noexcept { return d.rend(); }
241
243 RevIterator revEnd() noexcept { return d.rend(); }
244
246 ConstRevIterator crend() const noexcept { return d.crend(); }
247
249 ConstRevIterator constRevEnd() const noexcept { return d.crend(); }
250
259 T &at(size_t index) {
260 if (index >= d.size()) throw std::logic_error("List::at index out of range");
261 return d[index];
262 }
263
265 const T &at(size_t index) const {
266 if (index >= d.size()) throw std::logic_error("List::at index out of range");
267 return d[index];
268 }
269
275 T &operator[](size_t index) { return d[index]; }
276
278 const T &operator[](size_t index) const { return d[index]; }
279
281 T &front() { return d.front(); }
282
284 const T &front() const { return d.front(); }
285
287 T &back() { return d.back(); }
288
290 const T &back() const { return d.back(); }
291
293 T *data() noexcept { return d.data(); }
294
296 const T *data() const noexcept { return d.data(); }
297
299 bool isEmpty() const noexcept { return d.empty(); }
300
302 size_t size() const noexcept { return d.size(); }
303
305 size_t maxSize() const noexcept { return d.max_size(); }
306
311 void reserve(size_t newCapacity) { d.reserve(newCapacity); }
312
314 size_t capacity() const noexcept { return d.capacity(); }
315
317 void shrink() {
318 d.shrink_to_fit();
319 return;
320 }
321
323 void clear() noexcept {
324 d.clear();
325 return;
326 }
327
334 Iterator insert(ConstIterator pos, const T &value) { return d.insert(pos, value); }
335
342 Iterator insert(ConstIterator pos, T &&value) { return d.insert(pos, std::move(value)); }
343
350 Iterator insert(size_t pos, const T &value) { return d.insert(constBegin() + pos, value); }
351
358 Iterator insert(size_t pos, T &&value) { return d.insert(constBegin() + pos, std::move(value)); }
359
367 template <typename... Args> Iterator emplace(ConstIterator pos, Args &&...args) {
368 return d.emplace(pos, std::forward<Args>(args)...);
369 }
370
378 template <typename... Args> Iterator emplace(size_t pos, Args &&...args) {
379 return d.emplace(constBegin() + pos, std::forward<Args>(args)...);
380 }
381
387 Iterator remove(ConstIterator pos) { return d.erase(pos); }
388
395 Iterator erase(ConstIterator first, ConstIterator last) { return d.erase(first, last); }
396
402 Iterator remove(size_t index) { return d.erase(d.begin() + index); }
403
408 void removeIf(TestFunc func) {
409 d.erase(std::remove_if(d.begin(), d.end(), func), d.end());
410 return;
411 }
412
418 bool removeFirst(const T &value) {
419 bool ret = false;
420 for (auto item = begin(); item != end(); ++item) {
421 if (*item == value) {
422 remove(item);
423 ret = true;
424 break;
425 }
426 }
427 return ret;
428 }
429
434 void pushToBack(const T &value) {
435 d.push_back(value);
436 return;
437 }
438
443 void pushToBack(const List<T> &list) {
444 d.insert(d.end(), list.d.begin(), list.d.end());
445 return;
446 }
447
459 void pushToBack(const T *first, const T *last) {
460 d.insert(d.end(), first, last);
461 return;
462 }
463
468 void pushToBack(T &&value) {
469 d.push_back(std::move(value));
470 return;
471 }
472
477 void pushToBack(List<T> &&list) {
478 d.insert(d.end(), std::make_move_iterator(list.d.begin()),
479 std::make_move_iterator(list.d.end()));
480 return;
481 }
482
489 template <typename... Args> T &emplaceToBack(Args &&...args) {
490 return d.emplace_back(std::forward<Args>(args)...);
491 }
492
494 void popFromBack() {
495 d.pop_back();
496 return;
497 }
498
507 void resize(size_t newSize) {
508 d.resize(newSize);
509 return;
510 }
511
517 void resize(size_t newSize, const T &value) {
518 d.resize(newSize, value);
519 return;
520 }
521
526 void swap(List<T> &other) noexcept {
527 d.swap(other.d);
528 return;
529 }
530
537 bool set(size_t index, const T &val) {
538 if (index >= size()) return false;
539 d[index] = val;
540 return true;
541 }
542
547 List<T> sort() const {
548 auto ret = *this;
549 std::sort(ret.begin(), ret.end());
550 return ret;
551 }
552
559 template <typename Compare> List<T> sort(Compare comp) const {
560 auto ret = *this;
561 std::sort(ret.begin(), ret.end(), comp);
562 return ret;
563 }
564
568 void sortInPlace() { std::sort(d.begin(), d.end()); }
569
575 template <typename Compare> void sortInPlace(Compare comp) { std::sort(d.begin(), d.end(), comp); }
576
581 List<T> reverse() const {
582 auto ret = *this;
583 std::reverse(ret.begin(), ret.end());
584 return ret;
585 }
586
591 List<T> unique() const {
592 auto ret = sort();
593 ret.d.erase(std::unique(ret.begin(), ret.end()), ret.end());
594 return ret;
595 }
596
602 template <typename Func> void forEach(Func &&func) const {
603 for (const auto &item : d) func(item);
604 return;
605 }
606
612 bool contains(const T &val) const {
613 for (const auto &item : d) {
614 if (item == val) return true;
615 }
616 return false;
617 }
618
625 Result<size_t> indexOf(const T &value) const {
626 for (size_t i = 0; i < d.size(); ++i) {
627 if (d[i] == value) return makeResult<size_t>(i);
628 }
629 return makeError<size_t>(Error::NotFound);
630 }
631
638 Result<size_t> lastIndexOf(const T &value) const {
639 for (size_t i = d.size(); i > 0; --i) {
640 size_t idx = i - 1;
641 if (d[idx] == value) return makeResult<size_t>(idx);
642 }
643 return makeError<size_t>(Error::NotFound);
644 }
645
651 size_t count(const T &value) const {
652 size_t n = 0;
653 for (const auto &item : d) {
654 if (item == value) ++n;
655 }
656 return n;
657 }
658
665 List<T> mid(size_t pos, size_t length) const {
666 List<T> ret;
667 size_t end = pos + length;
668 if (end > d.size()) end = d.size();
669 if (pos >= d.size()) return ret;
670 ret.reserve(end - pos);
671 for (size_t i = pos; i < end; ++i) ret.pushToBack(d[i]);
672 return ret;
673 }
674
676 friend bool operator==(const List<T> &lhs, const List<T> &rhs) { return lhs.d == rhs.d; }
677
679 friend bool operator!=(const List<T> &lhs, const List<T> &rhs) { return lhs.d != rhs.d; }
680
682 friend bool operator<(const List<T> &lhs, const List<T> &rhs) { return lhs.d < rhs.d; }
683
685 friend bool operator>(const List<T> &lhs, const List<T> &rhs) { return lhs.d > rhs.d; }
686
688 friend bool operator<=(const List<T> &lhs, const List<T> &rhs) { return lhs.d <= rhs.d; }
689
691 friend bool operator>=(const List<T> &lhs, const List<T> &rhs) { return lhs.d >= rhs.d; }
692
693 private:
694 Data d;
695};
696
697PROMEKI_NAMESPACE_END
698
699#endif // PROMEKI_ENABLE_CORE