mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Use vector instead of custom linked list.
This commit is contained in:
parent
58d86af399
commit
2862070348
@ -1070,7 +1070,7 @@ void AddSpecialBoxSearchController::addChatsContacts() {
|
|||||||
auto result = (const Dialogs::List*)nullptr;
|
auto result = (const Dialogs::List*)nullptr;
|
||||||
for (const auto &word : wordList) {
|
for (const auto &word : wordList) {
|
||||||
const auto found = list->filtered(word[0]);
|
const auto found = list->filtered(word[0]);
|
||||||
if (found->isEmpty()) {
|
if (found->empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!result || result->size() > found->size()) {
|
if (!result || result->size() > found->size()) {
|
||||||
|
@ -952,7 +952,7 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
|||||||
if (!_chatsIndexed->isEmpty()) {
|
if (!_chatsIndexed->isEmpty()) {
|
||||||
for (fi = fb; fi != fe; ++fi) {
|
for (fi = fb; fi != fe; ++fi) {
|
||||||
auto found = _chatsIndexed->filtered(fi->at(0));
|
auto found = _chatsIndexed->filtered(fi->at(0));
|
||||||
if (found->isEmpty()) {
|
if (found->empty()) {
|
||||||
toFilter = nullptr;
|
toFilter = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ PositionChange Entry::adjustByPosInChatList(
|
|||||||
not_null<IndexedList*> indexed) {
|
not_null<IndexedList*> indexed) {
|
||||||
const auto lnk = mainChatListLink(list);
|
const auto lnk = mainChatListLink(list);
|
||||||
const auto movedFrom = lnk->pos();
|
const auto movedFrom = lnk->pos();
|
||||||
indexed->adjustByPos(chatListLinks(list));
|
indexed->adjustByDate(chatListLinks(list));
|
||||||
const auto movedTo = lnk->pos();
|
const auto movedTo = lnk->pos();
|
||||||
return { movedFrom, movedTo };
|
return { movedFrom, movedTo };
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ Row *IndexedList::addByName(Key key) {
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
Row *result = _list.addByName(key);
|
const auto result = _list.addByName(key);
|
||||||
for (const auto ch : key.entry()->chatListFirstLetters()) {
|
for (const auto ch : key.entry()->chatListFirstLetters()) {
|
||||||
auto j = _index.find(ch);
|
auto j = _index.find(ch);
|
||||||
if (j == _index.cend()) {
|
if (j == _index.cend()) {
|
||||||
@ -54,13 +54,13 @@ Row *IndexedList::addByName(Key key) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexedList::adjustByPos(const RowsByLetter &links) {
|
void IndexedList::adjustByDate(const RowsByLetter &links) {
|
||||||
for (const auto [ch, row] : links) {
|
for (const auto [ch, row] : links) {
|
||||||
if (ch == QChar(0)) {
|
if (ch == QChar(0)) {
|
||||||
_list.adjustByPos(row);
|
_list.adjustByDate(row);
|
||||||
} else {
|
} else {
|
||||||
if (auto it = _index.find(ch); it != _index.cend()) {
|
if (auto it = _index.find(ch); it != _index.cend()) {
|
||||||
it->second->adjustByPos(row);
|
it->second->adjustByDate(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,6 +118,8 @@ void IndexedList::peerNameChanged(
|
|||||||
void IndexedList::adjustByName(
|
void IndexedList::adjustByName(
|
||||||
Key key,
|
Key key,
|
||||||
const base::flat_set<QChar> &oldLetters) {
|
const base::flat_set<QChar> &oldLetters) {
|
||||||
|
Expects(_sortMode == SortMode::Name);
|
||||||
|
|
||||||
const auto mainRow = _list.adjustByName(key);
|
const auto mainRow = _list.adjustByName(key);
|
||||||
if (!mainRow) return;
|
if (!mainRow) return;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
|
|
||||||
RowsByLetter addToEnd(Key key);
|
RowsByLetter addToEnd(Key key);
|
||||||
Row *addByName(Key key);
|
Row *addByName(Key key);
|
||||||
void adjustByPos(const RowsByLetter &links);
|
void adjustByDate(const RowsByLetter &links);
|
||||||
void moveToTop(Key key);
|
void moveToTop(Key key);
|
||||||
|
|
||||||
// row must belong to this indexed list all().
|
// row must belong to this indexed list all().
|
||||||
@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
// Part of List interface is duplicated here for all() list.
|
// Part of List interface is duplicated here for all() list.
|
||||||
int size() const { return all().size(); }
|
int size() const { return all().size(); }
|
||||||
bool isEmpty() const { return all().isEmpty(); }
|
bool isEmpty() const { return all().empty(); }
|
||||||
bool contains(Key key) const { return all().contains(key); }
|
bool contains(Key key) const { return all().contains(key); }
|
||||||
Row *getRow(Key key) const { return all().getRow(key); }
|
Row *getRow(Key key) const { return all().getRow(key); }
|
||||||
Row *rowAtY(int32 y, int32 h) const { return all().rowAtY(y, h); }
|
Row *rowAtY(int32 y, int32 h) const { return all().rowAtY(y, h); }
|
||||||
|
@ -1648,7 +1648,7 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) {
|
|||||||
if (!_dialogs->isEmpty()) {
|
if (!_dialogs->isEmpty()) {
|
||||||
for (fi = fb; fi != fe; ++fi) {
|
for (fi = fb; fi != fe; ++fi) {
|
||||||
auto found = _dialogs->filtered(fi->at(0));
|
auto found = _dialogs->filtered(fi->at(0));
|
||||||
if (found->isEmpty()) {
|
if (found->empty()) {
|
||||||
toFilter = nullptr;
|
toFilter = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1661,7 +1661,7 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) {
|
|||||||
if (!_contactsNoDialogs->isEmpty()) {
|
if (!_contactsNoDialogs->isEmpty()) {
|
||||||
for (fi = fb; fi != fe; ++fi) {
|
for (fi = fb; fi != fe; ++fi) {
|
||||||
auto found = _contactsNoDialogs->filtered(fi->at(0));
|
auto found = _contactsNoDialogs->filtered(fi->at(0));
|
||||||
if (found->isEmpty()) {
|
if (found->empty()) {
|
||||||
toFilterContacts = nullptr;
|
toFilterContacts = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2020,13 +2020,9 @@ void DialogsInner::peerSearchReceived(
|
|||||||
if (alreadyAdded(peer)) {
|
if (alreadyAdded(peer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto prev = nullptr, next = nullptr;
|
|
||||||
const auto position = 0;
|
|
||||||
auto row = std::make_unique<Dialogs::Row>(
|
auto row = std::make_unique<Dialogs::Row>(
|
||||||
peer->owner().history(peer),
|
peer->owner().history(peer),
|
||||||
prev,
|
_filterResults.size());
|
||||||
next,
|
|
||||||
position);
|
|
||||||
const auto [i, ok] = _filterResultsGlobal.emplace(
|
const auto [i, ok] = _filterResultsGlobal.emplace(
|
||||||
peer,
|
peer,
|
||||||
std::move(row));
|
std::move(row));
|
||||||
|
@ -14,225 +14,137 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
|
|
||||||
List::List(SortMode sortMode)
|
List::List(SortMode sortMode) : _sortMode(sortMode) {
|
||||||
: _last(std::make_unique<Row>(nullptr))
|
|
||||||
, _begin(_last.get())
|
|
||||||
, _end(_last.get())
|
|
||||||
, _sortMode(sortMode)
|
|
||||||
, _current(_last.get()) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::adjustCurrent(int32 y, int32 h) const {
|
List::const_iterator List::cfind(Row *value) const {
|
||||||
if (isEmpty()) return;
|
return value
|
||||||
|
? (cbegin() + value->pos())
|
||||||
int32 pos = (y > 0) ? (y / h) : 0;
|
: cend();
|
||||||
while (_current->_pos > pos && _current != _begin) {
|
|
||||||
_current = _current->_prev;
|
|
||||||
}
|
|
||||||
while (_current->_pos + 1 <= pos && _current->_next != _end) {
|
|
||||||
_current = _current->_next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row *List::addToEnd(Key key) {
|
not_null<Row*> List::addToEnd(Key key) {
|
||||||
const auto result = new Row(key, _end->_prev, _end, _end->_pos);
|
if (const auto result = getRow(key)) {
|
||||||
_end->_pos++;
|
return result;
|
||||||
if (_begin == _end) {
|
|
||||||
_begin = _current = result;
|
|
||||||
} else {
|
|
||||||
_end->_prev->_next = result;
|
|
||||||
}
|
}
|
||||||
_rowByKey.emplace(key, result);
|
const auto result = _rowByKey.emplace(
|
||||||
++_count;
|
key,
|
||||||
_end->_prev = result;
|
std::make_unique<Row>(key, _rows.size())
|
||||||
|
).first->second.get();
|
||||||
|
_rows.push_back(result);
|
||||||
if (_sortMode == SortMode::Date) {
|
if (_sortMode == SortMode::Date) {
|
||||||
adjustByPos(result);
|
adjustByDate(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool List::insertBefore(Row *row, Row *before) {
|
|
||||||
if (row == before) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_current == row) {
|
|
||||||
_current = row->_prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto updateTill = row->_prev;
|
|
||||||
remove(row);
|
|
||||||
|
|
||||||
// insert row
|
|
||||||
row->_next = before; // update row
|
|
||||||
row->_prev = before->_prev;
|
|
||||||
row->_next->_prev = row; // update row->next
|
|
||||||
if (row->_prev) { // update row->prev
|
|
||||||
row->_prev->_next = row;
|
|
||||||
} else {
|
|
||||||
_begin = row;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update pos
|
|
||||||
for (auto n = row; n != updateTill; n = n->_next) {
|
|
||||||
n->_next->_pos++;
|
|
||||||
row->_pos--;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool List::insertAfter(Row *row, Row *after) {
|
|
||||||
if (row == after) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_current == row) {
|
|
||||||
_current = row->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto updateFrom = row->_next;
|
|
||||||
remove(row);
|
|
||||||
|
|
||||||
// insert row
|
|
||||||
row->_prev = after; // update row
|
|
||||||
row->_next = after->_next;
|
|
||||||
row->_prev->_next = row; // update row->prev
|
|
||||||
row->_next->_prev = row; // update row->next
|
|
||||||
|
|
||||||
// update pos
|
|
||||||
for (auto n = updateFrom; n != row; n = n->_next) {
|
|
||||||
n->_pos--;
|
|
||||||
row->_pos++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Row *List::adjustByName(Key key) {
|
Row *List::adjustByName(Key key) {
|
||||||
if (_sortMode != SortMode::Name) return nullptr;
|
Expects(_sortMode == SortMode::Name);
|
||||||
|
|
||||||
const auto i = _rowByKey.find(key);
|
const auto row = getRow(key);
|
||||||
if (i == _rowByKey.cend()) return nullptr;
|
if (!row) {
|
||||||
|
|
||||||
const auto row = i->second;
|
|
||||||
const auto name = key.entry()->chatListName();
|
|
||||||
auto change = row;
|
|
||||||
while (change->_prev
|
|
||||||
&& change->_prev->entry()->chatListName().compare(name, Qt::CaseInsensitive) < 0) {
|
|
||||||
change = change->_prev;
|
|
||||||
}
|
|
||||||
if (!insertBefore(row, change)) {
|
|
||||||
while (change->_next != _end
|
|
||||||
&& change->_next->entry()->chatListName().compare(name, Qt::CaseInsensitive) < 0) {
|
|
||||||
change = change->_next;
|
|
||||||
}
|
|
||||||
insertAfter(row, change);
|
|
||||||
}
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
Row *List::addByName(Key key) {
|
|
||||||
if (_sortMode != SortMode::Name) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
adjustByName(row);
|
||||||
const auto row = addToEnd(key);
|
|
||||||
auto change = row;
|
|
||||||
const auto name = key.entry()->chatListName();
|
|
||||||
while (change->_prev
|
|
||||||
&& change->_prev->entry()->chatListName().compare(name, Qt::CaseInsensitive) > 0) {
|
|
||||||
change = change->_prev;
|
|
||||||
}
|
|
||||||
if (!insertBefore(row, change)) {
|
|
||||||
while (change->_next != _end
|
|
||||||
&& change->_next->entry()->chatListName().compare(name, Qt::CaseInsensitive) < 0) {
|
|
||||||
change = change->_next;
|
|
||||||
}
|
|
||||||
insertAfter(row, change);
|
|
||||||
}
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::adjustByPos(Row *row) {
|
not_null<Row*> List::addByName(Key key) {
|
||||||
if (_sortMode != SortMode::Date || !_begin) return;
|
Expects(_sortMode == SortMode::Name);
|
||||||
|
|
||||||
Row *change = row;
|
const auto row = addToEnd(key);
|
||||||
if (change != _begin && _begin->sortKey() < row->sortKey()) {
|
adjustByName(key);
|
||||||
change = _begin;
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::adjustByName(not_null<Row*> row) {
|
||||||
|
Expects(row->pos() >= 0 && row->pos() < _rows.size());
|
||||||
|
|
||||||
|
const auto &name = row->entry()->chatListName();
|
||||||
|
const auto index = row->pos();
|
||||||
|
const auto i = _rows.begin() + index;
|
||||||
|
const auto before = std::find_if(i + 1, _rows.end(), [&](Row *row) {
|
||||||
|
const auto &greater = row->entry()->chatListName();
|
||||||
|
return greater.compare(name, Qt::CaseInsensitive) >= 0;
|
||||||
|
});
|
||||||
|
if (before != i + 1) {
|
||||||
|
rotate(i, i + 1, before);
|
||||||
|
} else if (i != _rows.begin()) {
|
||||||
|
const auto from = std::make_reverse_iterator(i);
|
||||||
|
const auto after = std::find_if(from, _rows.rend(), [&](Row *row) {
|
||||||
|
const auto &less = row->entry()->chatListName();
|
||||||
|
return less.compare(name, Qt::CaseInsensitive) <= 0;
|
||||||
|
}).base();
|
||||||
|
if (after != i) {
|
||||||
|
rotate(after, i, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::adjustByDate(not_null<Row*> row) {
|
||||||
|
Expects(_sortMode == SortMode::Date);
|
||||||
|
|
||||||
|
const auto key = row->sortKey();
|
||||||
|
const auto index = row->pos();
|
||||||
|
const auto i = _rows.begin() + index;
|
||||||
|
const auto before = std::find_if(i + 1, _rows.end(), [&](Row *row) {
|
||||||
|
return (row->sortKey() <= key);
|
||||||
|
});
|
||||||
|
if (before != i + 1) {
|
||||||
|
rotate(i, i + 1, before);
|
||||||
} else {
|
} else {
|
||||||
while (change->_prev && change->_prev->sortKey() < row->sortKey()) {
|
const auto from = std::make_reverse_iterator(i);
|
||||||
change = change->_prev;
|
const auto after = std::find_if(from, _rows.rend(), [&](Row *row) {
|
||||||
|
return (row->sortKey() >= key);
|
||||||
|
}).base();
|
||||||
|
if (after != i) {
|
||||||
|
rotate(after, i, i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!insertBefore(row, change)) {
|
|
||||||
if (change->_next != _end && _end->_prev->sortKey() > row->sortKey()) {
|
|
||||||
change = _end->_prev;
|
|
||||||
} else {
|
|
||||||
while (change->_next != _end && change->_next->sortKey() > row->sortKey()) {
|
|
||||||
change = change->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insertAfter(row, change);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool List::moveToTop(Key key) {
|
bool List::moveToTop(Key key) {
|
||||||
auto i = _rowByKey.find(key);
|
const auto i = _rowByKey.find(key);
|
||||||
if (i == _rowByKey.cend()) {
|
if (i == _rowByKey.cend()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const auto index = i->second->pos();
|
||||||
insertBefore(i->second, _begin);
|
const auto begin = _rows.begin();
|
||||||
|
rotate(begin, begin + index, begin + index + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void List::rotate(
|
||||||
|
std::vector<not_null<Row*>>::iterator first,
|
||||||
|
std::vector<not_null<Row*>>::iterator middle,
|
||||||
|
std::vector<not_null<Row*>>::iterator last) {
|
||||||
|
std::rotate(first, middle, last);
|
||||||
|
|
||||||
|
auto count = (last - first);
|
||||||
|
auto index = (first - _rows.begin());
|
||||||
|
while (count--) {
|
||||||
|
(*first++)->_pos = index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool List::del(Key key, Row *replacedBy) {
|
bool List::del(Key key, Row *replacedBy) {
|
||||||
auto i = _rowByKey.find(key);
|
auto i = _rowByKey.find(key);
|
||||||
if (i == _rowByKey.cend()) {
|
if (i == _rowByKey.cend()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto row = i->second;
|
const auto row = i->second.get();
|
||||||
if (App::main()) {
|
if (App::main()) {
|
||||||
emit App::main()->dialogRowReplaced(row, replacedBy);
|
emit App::main()->dialogRowReplaced(row, replacedBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row == _current) {
|
const auto index = row->pos();
|
||||||
_current = row->_next;
|
_rows.erase(_rows.begin() + index);
|
||||||
|
for (auto i = index, count = int(_rows.size()); i != count; ++i) {
|
||||||
|
_rows[i]->_pos = i;
|
||||||
}
|
}
|
||||||
for (auto change = row->_next; change != _end; change = change->_next) {
|
|
||||||
--change->_pos;
|
|
||||||
}
|
|
||||||
--_end->_pos;
|
|
||||||
remove(row);
|
|
||||||
delete row;
|
|
||||||
--_count;
|
|
||||||
_rowByKey.erase(i);
|
_rowByKey.erase(i);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::remove(Row *row) {
|
|
||||||
row->_next->_prev = row->_prev; // update row->next
|
|
||||||
if (row->_prev) { // update row->prev
|
|
||||||
row->_prev->_next = row->_next;
|
|
||||||
} else {
|
|
||||||
_begin = row->_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void List::clear() {
|
|
||||||
while (_begin != _end) {
|
|
||||||
_current = _begin;
|
|
||||||
_begin = _begin->_next;
|
|
||||||
delete _current;
|
|
||||||
}
|
|
||||||
_current = _begin;
|
|
||||||
_rowByKey.clear();
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
List::~List() {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Dialogs
|
} // namespace Dialogs
|
||||||
|
@ -21,105 +21,62 @@ public:
|
|||||||
List &operator=(const List &other) = delete;
|
List &operator=(const List &other) = delete;
|
||||||
|
|
||||||
int size() const {
|
int size() const {
|
||||||
return _count;
|
return _rows.size();
|
||||||
}
|
}
|
||||||
bool isEmpty() const {
|
bool empty() const {
|
||||||
return size() == 0;
|
return _rows.empty();
|
||||||
}
|
}
|
||||||
bool contains(Key key) const {
|
bool contains(Key key) const {
|
||||||
return _rowByKey.find(key) != _rowByKey.end();
|
return _rowByKey.find(key) != _rowByKey.end();
|
||||||
}
|
}
|
||||||
Row *getRow(Key key) const {
|
Row *getRow(Key key) const {
|
||||||
const auto i = _rowByKey.find(key);
|
const auto i = _rowByKey.find(key);
|
||||||
return (i == _rowByKey.end()) ? nullptr : i->second.get();
|
return (i != _rowByKey.end()) ? i->second.get() : nullptr;
|
||||||
}
|
}
|
||||||
Row *rowAtY(int32 y, int32 h) const {
|
Row *rowAtY(int y, int h) const {
|
||||||
auto i = cfind(y, h);
|
const auto i = cfind(y, h);
|
||||||
if (i == cend() || (*i)->pos() != ((y > 0) ? (y / h) : 0)) {
|
if (i == cend() || (*i)->pos() != ((y > 0) ? (y / h) : 0)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return *i;
|
return *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Row *addToEnd(Key key);
|
not_null<Row*> addToEnd(Key key);
|
||||||
Row *adjustByName(Key key);
|
Row *adjustByName(Key key);
|
||||||
Row *addByName(Key key);
|
not_null<Row*> addByName(Key key);
|
||||||
bool moveToTop(Key key);
|
bool moveToTop(Key key);
|
||||||
void adjustByPos(Row *row);
|
void adjustByDate(not_null<Row*> row);
|
||||||
bool del(Key key, Row *replacedBy = nullptr);
|
bool del(Key key, Row *replacedBy = nullptr);
|
||||||
void remove(Row *row);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
class const_iterator {
|
using const_iterator = std::vector<not_null<Row*>>::const_iterator;
|
||||||
public:
|
|
||||||
using value_type = Row*;
|
|
||||||
using pointer = Row**;
|
|
||||||
using reference = Row*&;
|
|
||||||
|
|
||||||
explicit const_iterator(Row *p) : _p(p) {
|
|
||||||
}
|
|
||||||
inline Row* operator*() const { return _p; }
|
|
||||||
inline Row* const* operator->() const { return &_p; }
|
|
||||||
inline bool operator==(const const_iterator &other) const { return _p == other._p; }
|
|
||||||
inline bool operator!=(const const_iterator &other) const { return !(*this == other); }
|
|
||||||
inline const_iterator &operator++() { _p = next(_p); return *this; }
|
|
||||||
inline const_iterator operator++(int) { const_iterator result(*this); ++(*this); return result; }
|
|
||||||
inline const_iterator &operator--() { _p = prev(_p); return *this; }
|
|
||||||
inline const_iterator operator--(int) { const_iterator result(*this); --(*this); return result; }
|
|
||||||
inline const_iterator operator+(int j) const { const_iterator result = *this; return result += j; }
|
|
||||||
inline const_iterator operator-(int j) const { const_iterator result = *this; return result -= j; }
|
|
||||||
inline const_iterator &operator+=(int j) { if (j < 0) return (*this -= (-j)); while (j--) ++*this; return *this; }
|
|
||||||
inline const_iterator &operator-=(int j) { if (j < 0) return (*this += (-j)); while (j--) --*this; return *this; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Row *_p;
|
|
||||||
friend class List;
|
|
||||||
|
|
||||||
};
|
|
||||||
friend class const_iterator;
|
|
||||||
using iterator = const_iterator;
|
using iterator = const_iterator;
|
||||||
|
|
||||||
const_iterator cbegin() const { return const_iterator(_begin); }
|
const_iterator cbegin() const { return _rows.cbegin(); }
|
||||||
const_iterator cend() const { return const_iterator(_end); }
|
const_iterator cend() const { return _rows.cend(); }
|
||||||
const_iterator begin() const { return cbegin(); }
|
const_iterator begin() const { return cbegin(); }
|
||||||
const_iterator end() const { return cend(); }
|
const_iterator end() const { return cend(); }
|
||||||
iterator begin() { return iterator(_begin); }
|
iterator begin() { return cbegin(); }
|
||||||
iterator end() { return iterator(_end); }
|
iterator end() { return cend(); }
|
||||||
const_iterator cfind(Row *value) const { return value ? const_iterator(value) : cend(); }
|
const_iterator cfind(Row *value) const;
|
||||||
const_iterator find(Row *value) const { return cfind(value); }
|
const_iterator find(Row *value) const { return cfind(value); }
|
||||||
iterator find(Row *value) { return value ? iterator(value) : end(); }
|
iterator find(Row *value) { return cfind(value); }
|
||||||
const_iterator cfind(int y, int h) const {
|
const_iterator cfind(int y, int h) const {
|
||||||
adjustCurrent(y, h);
|
const auto index = std::max(y, 0) / h;
|
||||||
return iterator(_current);
|
return _rows.begin() + std::min(index, size());
|
||||||
}
|
}
|
||||||
const_iterator find(int y, int h) const { return cfind(y, h); }
|
const_iterator find(int y, int h) const { return cfind(y, h); }
|
||||||
iterator find(int y, int h) {
|
iterator find(int y, int h) { return cfind(y, h); }
|
||||||
adjustCurrent(y, h);
|
|
||||||
return iterator(_current);
|
|
||||||
}
|
|
||||||
|
|
||||||
~List();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void adjustCurrent(int y, int h) const;
|
void adjustByName(not_null<Row*> row);
|
||||||
bool insertBefore(Row *row, Row *before);
|
void rotate(
|
||||||
bool insertAfter(Row *row, Row *after);
|
std::vector<not_null<Row*>>::iterator first,
|
||||||
static Row *next(Row *row) {
|
std::vector<not_null<Row*>>::iterator middle,
|
||||||
return row->_next;
|
std::vector<not_null<Row*>>::iterator last);
|
||||||
}
|
|
||||||
static Row *prev(Row *row) {
|
|
||||||
return row->_prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Row> _last;
|
SortMode _sortMode = SortMode();
|
||||||
Row *_begin;
|
std::vector<not_null<Row*>> _rows;
|
||||||
Row *_end;
|
std::map<Key, std::unique_ptr<Row>> _rowByKey;
|
||||||
SortMode _sortMode;
|
|
||||||
int _count = 0;
|
|
||||||
|
|
||||||
std::map<Key, not_null<Row*>> _rowByKey;
|
|
||||||
|
|
||||||
mutable Row *_current; // cache
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,11 +42,7 @@ class Row : public RippleRow {
|
|||||||
public:
|
public:
|
||||||
explicit Row(std::nullptr_t) {
|
explicit Row(std::nullptr_t) {
|
||||||
}
|
}
|
||||||
Row(Key key, Row *prev, Row *next, int pos)
|
Row(Key key, int pos) : _id(key), _pos(pos) {
|
||||||
: _id(key)
|
|
||||||
, _prev(prev)
|
|
||||||
, _next(next)
|
|
||||||
, _pos(pos) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key() const {
|
Key key() const {
|
||||||
@ -73,8 +69,6 @@ private:
|
|||||||
friend class List;
|
friend class List;
|
||||||
|
|
||||||
Key _id;
|
Key _id;
|
||||||
Row *_prev = nullptr;
|
|
||||||
Row *_next = nullptr;
|
|
||||||
int _pos = 0;
|
int _pos = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user