mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-06 10:03:26 -08:00
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [CardDB] Avoid copying printing maps and property strings Reading a card's sets was a measured hotspot: `SetToPrintingsMap setMap = card->getSets();` copies the whole QMap, and then iterating it with a non-const iterator detaches and deep-copies every PrintingInfo, including its property hash, on first use. A micro-benchmark of that exact pattern (copy plus non-const iteration) came out about 19x slower than a const reference over the same data. The querier, the cache writer, the XML writer, the picture loader and the printing/set selection widgets now take `getSets()` by const reference and only use const iterators. The tests that iterate generated data are covered by the existing card database and picture loader suites. String accessors were also returning by value where the value lives in a hash that has already been materialized: - CardInfo::getProperty() and the legacy getCardType()/getColors()/ getManaCost()/getCmc()/getPowTough()/getLoyalty() accessors, - PrintingInfo::getProperty(), getUuid(), getFlavorName(), getArtist(), and getSet(), - ExactCard::getPrinting() and getCardPtr(), - CardSet::getShortName(), getLongName() and getSetType(). getPrinting() in particular copied a PrintingInfo on every call, and a copy of an unmaterialized PrintingInfo has to take the properties mutex. Callers that need an owned copy still get one; the rest just read. Other allocation removals in the same path: - LazyPropertiesHash::ensureMaterialized() checks an atomic flag before taking the mutex, so property reads after the first one do not lock. The flag is release-stored after materialization and acquire-loaded by readers/copies, preserving the existing locking for the first read. - CardSet::getCorrectedShortName() no longer rebuilds its QSet of reserved Windows file names on every call. - CardSet::getIsKnownIgnored() no longer formats the release date into a throwaway string just to check its length. - The querier builds its card-type/format count caches without `cards.values()` or a properties key list, reserves its result lists, and picks a random card without materializing `cards.keys()`. - The querier's pinned-printing path reuses the CardInfoPtr it already has instead of looking the card up again by name. - CardDatabaseCache/XML serialization copy the alt-name QSet by reference. - The picture loader compiles its !prop!/!set! regular expressions once instead of per URL template, and walks the transform map with an iterator instead of keys() plus operator[]. Full build and ctest (628 tests) pass. * [CardDB] Address review comments PrintingInfo is a value type: it is stored in QLists and returned by value from the querier, so a const-ref getter can hand out a reference into a temporary. Return the QStrings and the CardSetPtr by value again. The constFind lookup stays, so a property read still never materializes the lazy property hash - only the last shared-data refcount is paid. * [CardDB] Undo the const-ref QString return changes QString is implicitly shared, so returning by value costs only a refcount and avoids handing out references into a lazily materialized hash. The constFind lookups stay, so a property read still never materializes the hash. * [CardDB] Use QMap::asKeyValueRange() in transformUrl The range is a view over the map's own iterators and yields references to the stored key and value, so it keeps the no-allocation property of the manual const iteration. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
246 lines
7.4 KiB
C++
246 lines
7.4 KiB
C++
#ifndef COCKATRICE_CARD_SET_H
|
|
#define COCKATRICE_CARD_SET_H
|
|
|
|
#include <QDate>
|
|
#include <QList>
|
|
#include <QSharedPointer>
|
|
#include <QString>
|
|
|
|
class CardInfo;
|
|
class ICardSetPriorityController;
|
|
|
|
using CardInfoPtr = QSharedPointer<CardInfo>;
|
|
|
|
class CardSet;
|
|
|
|
using CardSetPtr = QSharedPointer<CardSet>;
|
|
|
|
/**
|
|
* @class CardSet
|
|
* @ingroup CardSets
|
|
*
|
|
* @brief A collection of cards grouped under a common identifier.
|
|
*
|
|
* A set serves both as metadata (identifier, title, category, release date, and priority)
|
|
* and as a container of all cards that belong to it. Each set can be enabled/disabled
|
|
* and marked as known/unknown depending on context.
|
|
*
|
|
* The class inherits from `QList<CardInfoPtr>`, so it can be iterated over directly
|
|
* to access its contents.
|
|
*
|
|
* Typical usage:
|
|
* - Query metadata such as identifier, category, or release date.
|
|
* - Enable or disable sets according to user preference.
|
|
* - Store and retrieve CardInfo objects associated with the set.
|
|
*/
|
|
class CardSet : public QList<CardInfoPtr>
|
|
{
|
|
public:
|
|
/**
|
|
* @enum Priority
|
|
* @brief Defines relative ordering and importance of sets.
|
|
*/
|
|
enum Priority
|
|
{
|
|
PriorityFallback = 0, ///< Used when no other priority is defined.
|
|
PriorityPrimary = 10, ///< Primary, canonical set.
|
|
PrioritySecondary = 20, ///< Secondary but relevant.
|
|
PriorityReprint = 30, ///< Duplicate or reprint category.
|
|
PriorityOther = 40, ///< Miscellaneous grouping.
|
|
PriorityLowest = 100, ///< Lowest sorting priority.
|
|
};
|
|
|
|
static const char *TOKENS_SETNAME; ///< Reserved identifier for token-like sets.
|
|
|
|
private:
|
|
ICardSetPriorityController *priorityController; ///< Interface to the card set priority controller.
|
|
QString shortName; ///< Short identifier for the set.
|
|
QString longName; ///< Full name for the set.
|
|
unsigned int sortKey; ///< Custom numeric sort key.
|
|
QDate releaseDate; ///< Release date, may be empty if unknown.
|
|
QString setType; ///< Type/category label for the set.
|
|
Priority priority; ///< Priority level for sorting and relevance.
|
|
bool enabled; ///< Whether the set is active/enabled.
|
|
bool isknown; ///< Whether the set is considered known.
|
|
|
|
public:
|
|
/**
|
|
* @brief Constructs a CardSet.
|
|
*
|
|
* @param priorityController Interface to a card set priority controller.
|
|
* @param _shortName Identifier string.
|
|
* @param _longName Full descriptive name.
|
|
* @param _setType Type/category string.
|
|
* @param _releaseDate Release date (optional).
|
|
* @param _priority Sorting/priority level.
|
|
*/
|
|
explicit CardSet(ICardSetPriorityController *priorityController,
|
|
const QString &_shortName = QString(),
|
|
const QString &_longName = QString(),
|
|
const QString &_setType = QString(),
|
|
const QDate &_releaseDate = QDate(),
|
|
const Priority _priority = PriorityFallback);
|
|
|
|
/**
|
|
* @brief Creates and returns a new shared CardSet instance.
|
|
*
|
|
* @param priorityController Interface to a card set priority controller.
|
|
* @param _shortName Identifier string.
|
|
* @param _longName Full descriptive name.
|
|
* @param _setType Type/category string.
|
|
* @param _releaseDate Release date (optional).
|
|
* @param _priority Sorting/priority level.
|
|
* @return A shared pointer to the new CardSet.
|
|
*/
|
|
static CardSetPtr newInstance(ICardSetPriorityController *priorityController,
|
|
const QString &_shortName = QString(),
|
|
const QString &_longName = QString(),
|
|
const QString &_setType = QString(),
|
|
const QDate &_releaseDate = QDate(),
|
|
const Priority _priority = PriorityFallback);
|
|
|
|
/**
|
|
* @brief Returns a safe, sanitized version of the short name.
|
|
*
|
|
* Intended for file paths or identifiers where only certain
|
|
* characters are allowed.
|
|
*
|
|
* @return Sanitized short name.
|
|
*/
|
|
[[nodiscard]] QString getCorrectedShortName() const;
|
|
|
|
/** @return Short identifier of the set. */
|
|
[[nodiscard]] QString getShortName() const
|
|
{
|
|
return shortName;
|
|
}
|
|
|
|
/** @return Descriptive name of the set. */
|
|
[[nodiscard]] QString getLongName() const
|
|
{
|
|
return longName;
|
|
}
|
|
|
|
/** @return Type/category string of the set. */
|
|
[[nodiscard]] QString getSetType() const
|
|
{
|
|
return setType;
|
|
}
|
|
|
|
/** @return Release date of the set. */
|
|
[[nodiscard]] QDate getReleaseDate() const
|
|
{
|
|
return releaseDate;
|
|
}
|
|
|
|
/** @return Priority level of the set. */
|
|
[[nodiscard]] Priority getPriority() const
|
|
{
|
|
return priority;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the full name of the set.
|
|
* @param _longName New full name.
|
|
*/
|
|
void setLongName(const QString &_longName)
|
|
{
|
|
longName = _longName;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the category/type of the set.
|
|
* @param _setType New category string.
|
|
*/
|
|
void setSetType(const QString &_setType)
|
|
{
|
|
setType = _setType;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the release date of the set.
|
|
* @param _releaseDate New release date.
|
|
*/
|
|
void setReleaseDate(const QDate &_releaseDate)
|
|
{
|
|
releaseDate = _releaseDate;
|
|
}
|
|
|
|
/**
|
|
* @brief Updates the priority of the set.
|
|
* @param _priority New priority value.
|
|
*/
|
|
|
|
void setPriority(const Priority _priority)
|
|
{
|
|
priority = _priority;
|
|
}
|
|
|
|
/**
|
|
* @brief Loads state values (enabled, known, sort key) from configuration.
|
|
*
|
|
* Reads external configuration and applies it to this set.
|
|
*/
|
|
void loadSetOptions();
|
|
|
|
void setSortKeyInMemory(unsigned int _sortKey)
|
|
{
|
|
sortKey = _sortKey;
|
|
}
|
|
void setEnabledInMemory(bool _enabled)
|
|
{
|
|
enabled = _enabled;
|
|
}
|
|
|
|
/** @return The sort key assigned to this set. */
|
|
[[nodiscard]] int getSortKey() const
|
|
{
|
|
return sortKey;
|
|
}
|
|
|
|
/**
|
|
* @brief Assigns a new sort key to this set.
|
|
* @param _sortKey The numeric key to use for sorting.
|
|
*/
|
|
void setSortKey(unsigned int _sortKey);
|
|
|
|
/** @return True if the set is enabled. */
|
|
[[nodiscard]] bool getEnabled() const
|
|
{
|
|
return enabled;
|
|
}
|
|
|
|
/**
|
|
* @brief Enables or disables the set.
|
|
* @param _enabled True to enable, false to disable.
|
|
*/
|
|
void setEnabled(bool _enabled);
|
|
|
|
/** @return True if the set is considered known. */
|
|
[[nodiscard]] bool getIsKnown() const
|
|
{
|
|
return isknown;
|
|
}
|
|
|
|
/**
|
|
* @brief Marks the set as known or unknown.
|
|
* @param _isknown True if known, false if unknown.
|
|
*/
|
|
void setIsKnown(bool _isknown);
|
|
void setIsKnownInMemory(bool _isknown)
|
|
{
|
|
isknown = _isknown;
|
|
}
|
|
|
|
/**
|
|
* @brief Determines whether the set has incomplete metadata and should be ignored.
|
|
*
|
|
* @return True if the long name, type, and release date are all empty.
|
|
*/
|
|
[[nodiscard]] bool getIsKnownIgnored() const
|
|
{
|
|
return longName.isEmpty() && setType.isEmpty() && !releaseDate.isValid();
|
|
}
|
|
};
|
|
|
|
#endif // COCKATRICE_CARD_SET_H
|