Skip to content

Commit

Permalink
Fix: make Mudlet binary map saves with Qt6 compatible with Qt5 builds (
Browse files Browse the repository at this point in the history
…Mudlet#7007)

#### Brief overview of PR changes/additions
`static_cast<qint32>(...)` all Qt container `size()`/`count()`s when
writing them to a binary map file.

#### Motivation for adding to Mudlet
The return type from a Qt "container" type (well in fact ALL classes)
`size()`/`count()` operation is now defined as `qsizetype` which just
happens to effectively be a `int64_t` (`qint64`, 8 bytes) unfortunately
in the past - for Qt5 it was an `int`, which for all the platforms we
compile Mudlet on corresponds to an `int32_t` (`qint32`, 4 bytes). The
differences in size means that writing them to a `QDataStream` produces
incompatible files. The simplest fix, given that we are not expecting
*any* value so produced to overflow the prior `int32_t` type is to
explicitly `static_cast` the values in all cases.

#### Other info (issues closed, discussion etc)
This will close Mudlet#7003

Signed-off-by: Stephen Lyons <[email protected]>
  • Loading branch information
SlySven authored Nov 27, 2023
1 parent 01789e4 commit c4a96ff
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/TArea.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class TArea

friend bool TMap::serialize(QDataStream&, int);
friend bool TMap::restore(QString, bool);
friend bool TMap::retrieveMapFileStats(QString, QString*, int*, int*, int*, int*);
friend bool TMap::retrieveMapFileStats(QString, QString*, int*, int*, qsizetype*, qsizetype*);

public:
TArea(TMap*, TRoomDB*);
Expand Down
26 changes: 16 additions & 10 deletions src/TMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ bool TMap::serialize(QDataStream& ofs, int saveVersion)
saveVersion = 0;
} else if (saveVersion > mMaxVersion) {
saveVersion = mMaxVersion;
const QString errMsg = tr("[ ERROR ] - The format version \"%1\" you are trying to save the map with is too new\n"
const QString errMsg = tr("[ ERROR ] - The format version \"%1\" you are trying to save the map with is too new\n"
"for this version of Mudlet. Supported are only formats up to version %2.")
.arg(QString::number(saveVersion), QString::number(mMaxVersion));
appendErrorMsgWithNoLf(errMsg, false);
Expand Down Expand Up @@ -1168,7 +1168,11 @@ bool TMap::serialize(QDataStream& ofs, int saveVersion)
ofs << mIsOnlyMapSymbolFontToBeUsed;
}

ofs << mpRoomDB->getAreaMap().size();
// Qt 6 changed the return type of QMap<T1, T2>::size() to qsizetype which
// is an int64 rather than the int32 of Qt5 - but we need to use the latter
// to retain compatibility:
ofs << static_cast<qint32>(mpRoomDB->getAreaMap().size());

// serialize area table
QMapIterator<int, TArea*> itAreaList(mpRoomDB->getAreaMap());
while (itAreaList.hasNext()) {
Expand Down Expand Up @@ -1212,7 +1216,7 @@ bool TMap::serialize(QDataStream& ofs, int saveVersion)
// Also we now have temporary labels, so we need to count the
// permanent ones first to use as the count for ones to store:
const auto permanentLabelsList{pA->getPermanentLabelIds()};
ofs << permanentLabelsList.size();
ofs << static_cast<qint32>(permanentLabelsList.size());
QListIterator<int> itMapLabelId(permanentLabelsList);
while (itMapLabelId.hasNext()) {
const auto labelID = itMapLabelId.next();
Expand Down Expand Up @@ -1255,14 +1259,15 @@ bool TMap::serialize(QDataStream& ofs, int saveVersion)
areasWithPermanentLabels.insert(itArea.key(), itArea.value());
}
}
ofs << areasWithPermanentLabels.count();
ofs << static_cast<qint32>(areasWithPermanentLabels.count());
QMapIterator<int, TArea*> itAreaWithLabels(areasWithPermanentLabels);
while (itAreaWithLabels.hasNext()) {
itAreaWithLabels.next();
auto pArea = itAreaWithLabels.value();
auto permanentLabelIdsList = pArea->getPermanentLabelIds();
// number of (permanent) labels in this area:
ofs << permanentLabelIdsList.size();
ofs << static_cast<qint32>(permanentLabelIdsList.size());

// only used to assign labels to the area:
ofs << itAreaWithLabels.key();
QListIterator<int> itPerminentMapLabelIds(permanentLabelIdsList);
Expand Down Expand Up @@ -1902,12 +1907,12 @@ bool TMap::restore(QString location, bool downloadIfNotFound)
// Reads the newest map file from the profile and retrieves some stats and data,
// including the current player room - was mRoomId in 12 to pre-18 map files and
// is in mRoomIdHash since then so that it can be reinserted into a map that is
// copied across (if the room STILL exists! This is to avoid a replacement map
// copied across (if the room STILL exists)! This is to avoid a replacement map
// (copied/shared) from one profile to another from repositioning the other
// player location. Though this is written as a member function it is intended
// also for use to retrieve details from maps from OTHER profiles, importantly
// it does (or should) NOT interact with this TMap instance...!
bool TMap::retrieveMapFileStats(QString profile, QString* latestFileName = nullptr, int* fileVersion = nullptr, int* roomId = nullptr, int* areaCount = nullptr, int* roomCount = nullptr)
bool TMap::retrieveMapFileStats(QString profile, QString* latestFileName = nullptr, int* fileVersion = nullptr, int* roomId = nullptr, qsizetype* areaCount = nullptr, qsizetype* roomCount = nullptr)
{
if (profile.isEmpty()) {
return false;
Expand Down Expand Up @@ -2008,13 +2013,14 @@ bool TMap::retrieveMapFileStats(QString profile, QString* latestFileName = nullp
}

if (otherProfileVersion >= 14) {
int areaSize;
ifs >> areaSize;
int readAreaSize;
ifs >> readAreaSize;
qsizetype areaSize = static_cast<qsizetype>(readAreaSize);
if (areaCount) {
*areaCount = areaSize;
}
// read each area
for (int i = 0; i < areaSize; i++) {
for (qsizetype i = 0; i < areaSize; ++i) {
TArea pA(nullptr, nullptr);
int areaID;
ifs >> areaID;
Expand Down
16 changes: 8 additions & 8 deletions src/TMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class TMap : public QObject
bool gotoRoom(int, int);
bool serialize(QDataStream&, int saveVersion = 0);
bool restore(QString location, bool downloadIfNotFound = true);
bool retrieveMapFileStats(QString, QString*, int*, int*, int*, int*);
bool retrieveMapFileStats(QString, QString*, int*, int*, qsizetype*, qsizetype*);
void initGraph();
QString connectExitStubByDirection(const int fromRoomId, const int dirType);
QString connectExitStubByToId(const int fromRoomId, const int toRoomId);
Expand Down Expand Up @@ -179,7 +179,7 @@ class TMap : public QObject

std::pair<bool, QString> writeJsonMapFile(const QString&);
std::pair<bool, QString> readJsonMapFile(const QString&, const bool translatableTexts = false, const bool allowUserCancellation = true);
int getCurrentProgressRoomCount() const { return mProgressDialogRoomsCount; }
qsizetype getCurrentProgressRoomCount() const { return mProgressDialogRoomsCount; }
bool incrementJsonProgressDialog(const bool isExportNotImport, const bool isRoomNotLabel, const int increment = 1);
QString getDefaultAreaName() const { return mDefaultAreaName; }
QString getUnnamedAreaName() const { return mUnnamedAreaName; }
Expand Down Expand Up @@ -374,12 +374,12 @@ public slots:
QProgressDialog* mpProgressDialog = nullptr;
// Using during updates of text in progress dialog partially from other
// classes:
int mProgressDialogAreasTotal = 0;
int mProgressDialogAreasCount = 0;
int mProgressDialogRoomsTotal = 0;
int mProgressDialogRoomsCount = 0;
int mProgressDialogLabelsTotal = 0;
int mProgressDialogLabelsCount = 0;
qsizetype mProgressDialogAreasTotal = 0;
qsizetype mProgressDialogAreasCount = 0;
qsizetype mProgressDialogRoomsTotal = 0;
qsizetype mProgressDialogRoomsCount = 0;
qsizetype mProgressDialogLabelsTotal = 0;
qsizetype mProgressDialogLabelsCount = 0;

// Used to flag whether the map auto-save needs to be done after the next interval:
bool mUnsavedMap = false;
Expand Down
4 changes: 2 additions & 2 deletions src/dlgProfilePreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2571,8 +2571,8 @@ void dlgProfilePreferences::slot_copyMap()

// Most of these we'll just get for debugging!
QString otherProfileFileUsed;
int otherProfileRoomCount;
int otherProfileAreaCount;
qsizetype otherProfileRoomCount;
qsizetype otherProfileAreaCount;
int otherProfileVersion;
int otherProfileCurrentRoomId; // What we are looking for!
if (pHost->mpMap->retrieveMapFileStats(itOtherProfile.key(),
Expand Down

0 comments on commit c4a96ff

Please sign in to comment.