10#include <promeki/config.h>
11#if PROMEKI_ENABLE_CORE
14#include <initializer_list>
23PROMEKI_NAMESPACE_BEGIN
51template <
typename T>
class List {
52 PROMEKI_SHARED_FINAL(List)
55 using Ptr = SharedPtr<List>;
58 using Data =
typename std::vector<T>;
61 using Iterator =
typename std::vector<T>::iterator;
64 using ConstIterator =
typename std::vector<T>::const_iterator;
67 using RevIterator =
typename std::vector<T>::reverse_iterator;
70 using ConstRevIterator =
typename std::vector<T>::const_reverse_iterator;
73 using TestFunc = Function<bool(
const T &)>;
82 explicit List(
size_t size) : d(size) {}
89 List(
size_t size,
const T &defaultValue) : d(size, defaultValue) {}
92 List(
const List &other) : d(other.d) {}
95 List(List &&other) noexcept : d(std::move(other.d)) {}
101 List(std::initializer_list<T> initList) : d(initList) {}
113 List(
const T *first,
const T *last) : d(first, last) {}
119 List &operator=(
const List &other) {
125 List &operator=(List &&other)
noexcept {
126 d = std::move(other.d);
135 List &operator=(std::initializer_list<T> initList) {
148 template <
typename InputIt>
void assign(InputIt first, InputIt last) {
149 d.assign(first, last);
158 void assign(
size_t count,
const T &value) {
159 d.assign(count, value);
168 List &operator+=(
const T &item) {
178 List &operator+=(T &&item) {
179 pushToBack(std::move(item));
188 List &operator+=(
const List &list) {
198 List &operator+=(List &&list) {
199 pushToBack(std::move(list));
204 Iterator begin() noexcept {
return d.begin(); }
207 ConstIterator begin() const noexcept {
return d.cbegin(); }
210 ConstIterator cbegin() const noexcept {
return d.cbegin(); }
213 ConstIterator constBegin() const noexcept {
return d.cbegin(); }
216 RevIterator rbegin() noexcept {
return d.rbegin(); }
219 RevIterator revBegin() noexcept {
return d.rbegin(); }
222 ConstRevIterator crbegin() const noexcept {
return d.crbegin(); }
225 ConstRevIterator constRevBegin() const noexcept {
return d.crbegin(); }
228 Iterator end() noexcept {
return d.end(); }
231 ConstIterator end() const noexcept {
return d.cend(); }
234 ConstIterator cend() const noexcept {
return d.cend(); }
237 ConstIterator constEnd() const noexcept {
return d.cend(); }
240 RevIterator rend() noexcept {
return d.rend(); }
243 RevIterator revEnd() noexcept {
return d.rend(); }
246 ConstRevIterator crend() const noexcept {
return d.crend(); }
249 ConstRevIterator constRevEnd() const noexcept {
return d.crend(); }
259 T &at(
size_t index) {
260 if (index >= d.size())
throw std::logic_error(
"List::at index out of range");
265 const T &at(
size_t index)
const {
266 if (index >= d.size())
throw std::logic_error(
"List::at index out of range");
275 T &operator[](
size_t index) {
return d[index]; }
278 const T &operator[](
size_t index)
const {
return d[index]; }
281 T &front() {
return d.front(); }
284 const T &front()
const {
return d.front(); }
287 T &back() {
return d.back(); }
290 const T &back()
const {
return d.back(); }
293 T *data() noexcept {
return d.data(); }
296 const T *data() const noexcept {
return d.data(); }
299 bool isEmpty() const noexcept {
return d.empty(); }
302 size_t size() const noexcept {
return d.size(); }
305 size_t maxSize() const noexcept {
return d.max_size(); }
311 void reserve(
size_t newCapacity) { d.reserve(newCapacity); }
314 size_t capacity() const noexcept {
return d.capacity(); }
323 void clear() noexcept {
334 Iterator insert(ConstIterator pos,
const T &value) {
return d.insert(pos, value); }
342 Iterator insert(ConstIterator pos, T &&value) {
return d.insert(pos, std::move(value)); }
350 Iterator insert(
size_t pos,
const T &value) {
return d.insert(constBegin() + pos, value); }
358 Iterator insert(
size_t pos, T &&value) {
return d.insert(constBegin() + pos, std::move(value)); }
367 template <
typename... Args> Iterator emplace(ConstIterator pos, Args &&...args) {
368 return d.emplace(pos, std::forward<Args>(args)...);
378 template <
typename... Args> Iterator emplace(
size_t pos, Args &&...args) {
379 return d.emplace(constBegin() + pos, std::forward<Args>(args)...);
387 Iterator remove(ConstIterator pos) {
return d.erase(pos); }
395 Iterator erase(ConstIterator first, ConstIterator last) {
return d.erase(first, last); }
402 Iterator remove(
size_t index) {
return d.erase(d.begin() + index); }
408 void removeIf(TestFunc func) {
409 d.erase(std::remove_if(d.begin(), d.end(), func), d.end());
418 bool removeFirst(
const T &value) {
420 for (
auto item = begin(); item != end(); ++item) {
421 if (*item == value) {
434 void pushToBack(
const T &value) {
443 void pushToBack(
const List<T> &list) {
444 d.insert(d.end(), list.d.begin(), list.d.end());
459 void pushToBack(
const T *first,
const T *last) {
460 d.insert(d.end(), first, last);
468 void pushToBack(T &&value) {
469 d.push_back(std::move(value));
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()));
489 template <
typename... Args> T &emplaceToBack(Args &&...args) {
490 return d.emplace_back(std::forward<Args>(args)...);
507 void resize(
size_t newSize) {
517 void resize(
size_t newSize,
const T &value) {
518 d.resize(newSize, value);
526 void swap(List<T> &other)
noexcept {
537 bool set(
size_t index,
const T &val) {
538 if (index >= size())
return false;
547 List<T> sort()
const {
549 std::sort(ret.begin(), ret.end());
559 template <
typename Compare> List<T> sort(Compare comp)
const {
561 std::sort(ret.begin(), ret.end(), comp);
568 void sortInPlace() { std::sort(d.begin(), d.end()); }
575 template <
typename Compare>
void sortInPlace(Compare comp) { std::sort(d.begin(), d.end(), comp); }
581 List<T> reverse()
const {
583 std::reverse(ret.begin(), ret.end());
591 List<T> unique()
const {
593 ret.d.erase(std::unique(ret.begin(), ret.end()), ret.end());
602 template <
typename Func>
void forEach(Func &&func)
const {
603 for (
const auto &item : d) func(item);
612 bool contains(
const T &val)
const {
613 for (
const auto &item : d) {
614 if (item == val)
return true;
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);
629 return makeError<size_t>(Error::NotFound);
638 Result<size_t> lastIndexOf(
const T &value)
const {
639 for (
size_t i = d.size(); i > 0; --i) {
641 if (d[idx] == value)
return makeResult<size_t>(idx);
643 return makeError<size_t>(Error::NotFound);
651 size_t count(
const T &value)
const {
653 for (
const auto &item : d) {
654 if (item == value) ++n;
665 List<T> mid(
size_t pos,
size_t length)
const {
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]);
676 friend bool operator==(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d == rhs.d; }
679 friend bool operator!=(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d != rhs.d; }
682 friend bool operator<(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d < rhs.d; }
685 friend bool operator>(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d > rhs.d; }
688 friend bool operator<=(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d <= rhs.d; }
691 friend bool operator>=(
const List<T> &lhs,
const List<T> &rhs) {
return lhs.d >= rhs.d; }