[CardDB] Sort power/toughness without splitting every comparison (#7607)

* [CardDB] Sort power/toughness without splitting every comparison

When the card database is sorted by the P/T column, lessThan() runs
O(n log n) times over the whole view, and each call split both strings
into a QStringList ("power/toughness") and then read the two elements
back. For the roughly 36k cards in the database that is millions of
list and string allocations, all for a value that contains at most one
separator.

The comparator now locates the single '/' with indexOf and passes the
two halves as QStringView to lessThanNumerically(), which is changed
from QString to QStringView. The numeric parsing, the "1+*" fallback and
the locale-aware tie-break are unchanged, and strings with no separator
or more than one still fall through to the plain string comparison,
exactly as split()-based size checks did before.

lessThanNumerically() also initializes its two bool out-parameters; they
were declared uninitialized, which only worked because toFloat() always
assigns them.

Compared old and new comparator over a corpus of 2024 power/toughness
strings (4096576 ordered pairs, including malformed values): zero
differences. Full build and ctest (628 tests) pass.

* Extract well-formedness checks in P/T comparator

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-10-23 10:34:13 +02:00 • committed by GitHub
parent e666a4978d
commit 4980f88a7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 29 additions and 23 deletions

View file

@ -14,6 +14,7 @@
#include <QSet>
#include <QSortFilterProxyModel>
#include <QString>
#include <QStringView>
#include <QTimer>
#include <libcockatrice/card/card_localization.h>
#include <libcockatrice/filters/filter_string.h>
@ -88,7 +89,7 @@ signals:
protected:
[[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
static int lessThanNumerically(const QString &left, const QString &right);
static int lessThanNumerically(QStringView left, QStringView right);
[[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
[[nodiscard]] bool rowMatchesCardName(CardInfoPtr info) const;