From d81cb729fe01c9fbf5b47fb5853f5210f9125da9 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 2 Mar 2025 20:28:53 +0100 Subject: [PATCH 1/5] Make plLocation ==, !=, and < all consider the same fields Fixes some odd behavior in PrpShop when changing a PRP file's flags. Most likely this also caused other weirdness besides that. --- core/PRP/KeyedObject/plLocation.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/PRP/KeyedObject/plLocation.cpp b/core/PRP/KeyedObject/plLocation.cpp index cb66a7f21..b560b5c3e 100644 --- a/core/PRP/KeyedObject/plLocation.cpp +++ b/core/PRP/KeyedObject/plLocation.cpp @@ -20,7 +20,7 @@ bool plLocation::operator==(const plLocation& other) const { return (fState == other.fState && fPageNum == other.fPageNum - && fSeqPrefix == other.fSeqPrefix); + && fSeqPrefix == other.fSeqPrefix && fFlags == other.fFlags); } bool plLocation::operator!=(const plLocation& other) const @@ -31,9 +31,15 @@ bool plLocation::operator!=(const plLocation& other) const bool plLocation::operator<(const plLocation& other) const { - if (fSeqPrefix == other.fSeqPrefix) + if (fState != other.fState) { + return fState < other.fState; + } else if (fSeqPrefix != other.fSeqPrefix) { + return fSeqPrefix < other.fSeqPrefix; + } else if (fPageNum != other.fPageNum) { return fPageNum < other.fPageNum; - return fSeqPrefix < other.fSeqPrefix; + } else { + return fFlags < other.fFlags; + } } void plLocation::parse(unsigned int id) From a0a13f4dd142c4ff8414809b1e1a8aaca0b3afa2 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 2 Mar 2025 20:33:03 +0100 Subject: [PATCH 2/5] Delegate all operator!= implementations to operator== To prevent any future inconsistencies between the two. --- core/Math/hsGeometry3.h | 5 +---- core/Math/hsQuat.h | 5 +---- core/PRP/KeyedObject/plKey.h | 4 ++-- core/PRP/KeyedObject/plLocation.cpp | 6 ------ core/PRP/KeyedObject/plLocation.h | 2 +- core/Sys/hsColor.cpp | 10 ---------- core/Sys/hsColor.h | 4 ++-- core/Sys/plUnifiedTime.cpp | 5 ----- core/Sys/plUnifiedTime.h | 2 +- core/Sys/plUuid.cpp | 7 ------- core/Sys/plUuid.h | 2 +- core/Util/plMD5.cpp | 5 ----- core/Util/plMD5.h | 2 +- net/crypt/pnBigInteger.cpp | 10 ---------- net/crypt/pnBigInteger.h | 4 ++-- 15 files changed, 12 insertions(+), 61 deletions(-) diff --git a/core/Math/hsGeometry3.h b/core/Math/hsGeometry3.h index b025b76b9..6524f2db4 100644 --- a/core/Math/hsGeometry3.h +++ b/core/Math/hsGeometry3.h @@ -47,10 +47,7 @@ struct HSPLASMA_EXPORT hsVector3 } /** Returns true if the values of the vectors are non-identical */ - bool operator!=(const hsVector3& other) const - { - return (X != other.X) || (Y != other.Y) || (Z != other.Z); - } + bool operator!=(const hsVector3& other) const { return !operator==(other); } /** Reads the vector from a stream */ void read(hsStream* S); diff --git a/core/Math/hsQuat.h b/core/Math/hsQuat.h index 8f3579fed..bef03de32 100644 --- a/core/Math/hsQuat.h +++ b/core/Math/hsQuat.h @@ -34,10 +34,7 @@ struct HSPLASMA_EXPORT hsQuat return (X == other.X) && (Y == other.Y) && (Z == other.Z) && (W == other.W); } - bool operator!=(const hsQuat& other) const - { - return (X != other.X) || (Y != other.Y) || (Z != other.Z) || (W != other.W); - } + bool operator!=(const hsQuat& other) const { return !operator==(other); } hsQuat operator+(const hsQuat& rt) const { diff --git a/core/PRP/KeyedObject/plKey.h b/core/PRP/KeyedObject/plKey.h index 107cc1153..72d153fbb 100644 --- a/core/PRP/KeyedObject/plKey.h +++ b/core/PRP/KeyedObject/plKey.h @@ -347,10 +347,10 @@ class HSPLASMA_EXPORT plKey HS_FINAL bool operator==(const plKeyData* other) const { return fKeyData == other; } /** Returns true if the keys point to different plKeyData structures */ - bool operator!=(const plKey& other) const { return fKeyData != other.fKeyData; } + bool operator!=(const plKey& other) const { return !operator==(other); } /** Returns true if this key's plKeyData is NOT 'other' */ - bool operator!=(const plKeyData* other) const { return fKeyData != other; } + bool operator!=(const plKeyData* other) const { return !operator==(other); } /** Provides sorting functionality for STL containers */ bool operator<(const plKey& other) const diff --git a/core/PRP/KeyedObject/plLocation.cpp b/core/PRP/KeyedObject/plLocation.cpp index b560b5c3e..41ed3cde8 100644 --- a/core/PRP/KeyedObject/plLocation.cpp +++ b/core/PRP/KeyedObject/plLocation.cpp @@ -23,12 +23,6 @@ bool plLocation::operator==(const plLocation& other) const && fSeqPrefix == other.fSeqPrefix && fFlags == other.fFlags); } -bool plLocation::operator!=(const plLocation& other) const -{ - return (fState != other.fState || fPageNum != other.fPageNum - || fSeqPrefix != other.fSeqPrefix || fFlags != other.fFlags); -} - bool plLocation::operator<(const plLocation& other) const { if (fState != other.fState) { diff --git a/core/PRP/KeyedObject/plLocation.h b/core/PRP/KeyedObject/plLocation.h index 524c6ec51..56e760681 100644 --- a/core/PRP/KeyedObject/plLocation.h +++ b/core/PRP/KeyedObject/plLocation.h @@ -53,7 +53,7 @@ class HSPLASMA_EXPORT plLocation void setVer(PlasmaVer pv) { fVer = pv; } bool operator==(const plLocation& other) const; - bool operator!=(const plLocation& other) const; + bool operator!=(const plLocation& other) const { return !operator==(other); } bool operator<(const plLocation& other) const; void parse(unsigned int id); diff --git a/core/Sys/hsColor.cpp b/core/Sys/hsColor.cpp index 4ef76058f..2eb4a6981 100644 --- a/core/Sys/hsColor.cpp +++ b/core/Sys/hsColor.cpp @@ -49,11 +49,6 @@ bool hsColorRGBA::operator==(const hsColorRGBA& other) const return (r == other.r) && (g == other.g) && (b == other.b) && (a == other.a); } -bool hsColorRGBA::operator!=(const hsColorRGBA& other) const -{ - return (r != other.r) || (g != other.g) || (b != other.b) || (a != other.a); -} - void hsColorRGBA::read(hsStream* S) { r = S->readFloat(); @@ -113,11 +108,6 @@ bool hsColor32::operator==(const hsColor32& other) const return (color == other.color); } -bool hsColor32::operator!=(const hsColor32& other) const -{ - return (color != other.color); -} - void hsColor32::read32(hsStream* S) { color = S->readInt(); diff --git a/core/Sys/hsColor.h b/core/Sys/hsColor.h index a62c00b41..92c4204f9 100644 --- a/core/Sys/hsColor.h +++ b/core/Sys/hsColor.h @@ -45,7 +45,7 @@ struct HSPLASMA_EXPORT hsColorRGBA void set(const hsColorRGBA& init); bool operator==(const hsColorRGBA& other) const; - bool operator!=(const hsColorRGBA& other) const; + bool operator!=(const hsColorRGBA& other) const { return !operator==(other); } void read(hsStream* S); void write(hsStream* S); @@ -74,7 +74,7 @@ struct HSPLASMA_EXPORT hsColor32 : b(blue), g(green), r(red), a(alpha) { } bool operator==(const hsColor32& other) const; - bool operator!=(const hsColor32& other) const; + bool operator!=(const hsColor32& other) const { return !operator==(other); } void read32(hsStream* S); void write32(hsStream* S); diff --git a/core/Sys/plUnifiedTime.cpp b/core/Sys/plUnifiedTime.cpp index 58489ad69..404c9dcbf 100644 --- a/core/Sys/plUnifiedTime.cpp +++ b/core/Sys/plUnifiedTime.cpp @@ -151,11 +151,6 @@ bool plUnifiedTime::operator==(const plUnifiedTime& other) return (fSecs == other.fSecs && fMicros == other.fMicros); } -bool plUnifiedTime::operator!=(const plUnifiedTime& other) -{ - return (fSecs != other.fSecs || fMicros != other.fMicros); -} - bool plUnifiedTime::operator<(const plUnifiedTime& other) { if (fSecs < other.fSecs) diff --git a/core/Sys/plUnifiedTime.h b/core/Sys/plUnifiedTime.h index 20aec3e23..850a8af82 100644 --- a/core/Sys/plUnifiedTime.h +++ b/core/Sys/plUnifiedTime.h @@ -63,7 +63,7 @@ class HSPLASMA_EXPORT plUnifiedTime plUnifiedTime& operator+=(const plUnifiedTime& other); plUnifiedTime& operator-=(const plUnifiedTime& other); bool operator==(const plUnifiedTime& other); - bool operator!=(const plUnifiedTime& other); + bool operator!=(const plUnifiedTime& other) { return !operator==(other); } bool operator<(const plUnifiedTime& other); bool operator>(const plUnifiedTime& other); bool operator<=(const plUnifiedTime& other); diff --git a/core/Sys/plUuid.cpp b/core/Sys/plUuid.cpp index 4b0216c2c..d20d81a25 100644 --- a/core/Sys/plUuid.cpp +++ b/core/Sys/plUuid.cpp @@ -35,13 +35,6 @@ bool plUuid::operator==(const plUuid& other) const return (memcmp(fData4, other.fData4, sizeof(fData4)) == 0); } -bool plUuid::operator!=(const plUuid& other) const -{ - if (fData1 == other.fData1 || fData2 == other.fData2 || fData3 == other.fData3) - return false; - return (memcmp(fData4, other.fData4, sizeof(fData4)) != 0); -} - void plUuid::read(hsStream* S) { fData1 = S->readInt(); diff --git a/core/Sys/plUuid.h b/core/Sys/plUuid.h index 10e8883f7..6d9926bcc 100644 --- a/core/Sys/plUuid.h +++ b/core/Sys/plUuid.h @@ -53,7 +53,7 @@ struct HSPLASMA_EXPORT plUuid { bool operator==(const plUuid& other) const; /** Returns true if the two UUIDs are non-identical. */ - bool operator!=(const plUuid& other) const; + bool operator!=(const plUuid& other) const { return !operator==(other); } /** Read the UUID from a stream */ void read(hsStream* S); diff --git a/core/Util/plMD5.cpp b/core/Util/plMD5.cpp index 5d7ea23eb..29d4ac843 100644 --- a/core/Util/plMD5.cpp +++ b/core/Util/plMD5.cpp @@ -61,11 +61,6 @@ bool plMD5Hash::operator==(const plMD5Hash& cmp) const return memcmp(fHash, cmp.fHash, sizeof(fHash)) == 0; } -bool plMD5Hash::operator!=(const plMD5Hash& cmp) const -{ - return memcmp(fHash, cmp.fHash, sizeof(fHash)) != 0; -} - ST::string plMD5Hash::toHex() const { // Little-endian byte order diff --git a/core/Util/plMD5.h b/core/Util/plMD5.h index a0e8c2a71..317df30e5 100644 --- a/core/Util/plMD5.h +++ b/core/Util/plMD5.h @@ -29,7 +29,7 @@ class HSPLASMA_EXPORT plMD5Hash plMD5Hash(); plMD5Hash(const char* hex) { fromHex(hex); } bool operator==(const plMD5Hash& cmp) const; - bool operator!=(const plMD5Hash& cmp) const; + bool operator!=(const plMD5Hash& cmp) const { return !operator==(cmp); } ST::string toHex() const; void fromHex(const char* hex); diff --git a/net/crypt/pnBigInteger.cpp b/net/crypt/pnBigInteger.cpp index 51a264f28..49c35025c 100644 --- a/net/crypt/pnBigInteger.cpp +++ b/net/crypt/pnBigInteger.cpp @@ -104,16 +104,6 @@ bool pnBigInteger::operator==(unsigned int num) const return BN_is_word(fValue, num) != 0; } -bool pnBigInteger::operator!=(const pnBigInteger& num) const -{ - return BN_cmp(fValue, num.fValue) != 0; -} - -bool pnBigInteger::operator!=(unsigned int num) const -{ - return BN_is_word(fValue, num) == 0; -} - bool pnBigInteger::operator<(const pnBigInteger& num) const { return BN_cmp(fValue, num.fValue) < 0; diff --git a/net/crypt/pnBigInteger.h b/net/crypt/pnBigInteger.h index 3ae34d5af..9fbfc76e5 100644 --- a/net/crypt/pnBigInteger.h +++ b/net/crypt/pnBigInteger.h @@ -49,8 +49,8 @@ class HSPLASMANET_EXPORT pnBigInteger // Comparison bool operator==(const pnBigInteger& num) const; bool operator==(unsigned int num) const; - bool operator!=(const pnBigInteger& num) const; - bool operator!=(unsigned int num) const; + bool operator!=(const pnBigInteger& num) const { return !operator==(num); } + bool operator!=(unsigned int num) const { return !operator==(num); } bool operator<(const pnBigInteger& num) const; bool operator<(unsigned int num) const; bool operator>(const pnBigInteger& num) const; From 3bafdae9862ab42f7dfe8f58b23e4e67220af6c3 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 2 Mar 2025 20:40:45 +0100 Subject: [PATCH 3/5] Fix const-ness of plKeyData::operator== --- core/PRP/KeyedObject/plKey.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/PRP/KeyedObject/plKey.h b/core/PRP/KeyedObject/plKey.h index 72d153fbb..90a540473 100644 --- a/core/PRP/KeyedObject/plKey.h +++ b/core/PRP/KeyedObject/plKey.h @@ -81,7 +81,7 @@ class HSPLASMA_EXPORT plKeyData * equivalent. This basically just calls the == operator on the * plUoid (so storage information is not compared). */ - bool operator==(plKeyData& other) const { return (fUoid == other.fUoid); } + bool operator==(const plKeyData& other) const { return (fUoid == other.fUoid); } /** * Read a key directly from the key index of a PRP file. This will From 26e57fc6fcac70c3b09fb121d755509a4b09f9e5 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 2 Mar 2025 20:42:26 +0100 Subject: [PATCH 4/5] Add missing operator!= overloads for classes that overload operator== --- core/Math/hsMatrix44.h | 1 + core/PRP/KeyedObject/plKey.h | 2 ++ core/Util/hsBitVector.h | 2 ++ net/auth/pnVaultNode.h | 1 + 4 files changed, 6 insertions(+) diff --git a/core/Math/hsMatrix44.h b/core/Math/hsMatrix44.h index ac09b8f66..7b04c5f1e 100644 --- a/core/Math/hsMatrix44.h +++ b/core/Math/hsMatrix44.h @@ -45,6 +45,7 @@ struct HSPLASMA_EXPORT hsMatrix44 float operator()(int y, int x) const { return data[y+(x*4)]; } float& operator()(int y, int x) { return data[y+(x*4)]; } bool operator==(const hsMatrix44& other) const; + bool operator!=(const hsMatrix44& other) const { return !operator==(other); } const float* glMatrix() const { return data; } hsMatrix44 operator*(const hsMatrix44& right) const; diff --git a/core/PRP/KeyedObject/plKey.h b/core/PRP/KeyedObject/plKey.h index 90a540473..26488cb0e 100644 --- a/core/PRP/KeyedObject/plKey.h +++ b/core/PRP/KeyedObject/plKey.h @@ -83,6 +83,8 @@ class HSPLASMA_EXPORT plKeyData */ bool operator==(const plKeyData& other) const { return (fUoid == other.fUoid); } + bool operator!=(const plKeyData& other) const { return !operator==(other); } + /** * Read a key directly from the key index of a PRP file. This will * include the file offset and size where the hsKeyedObject is stored. diff --git a/core/Util/hsBitVector.h b/core/Util/hsBitVector.h index 7a47e3e72..52ad3ac7e 100644 --- a/core/Util/hsBitVector.h +++ b/core/Util/hsBitVector.h @@ -69,6 +69,8 @@ class HSPLASMA_EXPORT hsBitVector /** Comparison operator */ bool operator==(bool value) const; + bool operator!=(bool value) const { return !operator==(value); } + /** Assignment operator -- modifies the hsBitVector */ Bit& operator=(bool value); }; diff --git a/net/auth/pnVaultNode.h b/net/auth/pnVaultNode.h index f315f8e41..42520fabc 100644 --- a/net/auth/pnVaultNode.h +++ b/net/auth/pnVaultNode.h @@ -127,6 +127,7 @@ struct HSPLASMANET_EXPORT pnVaultNodeRef void read(const unsigned char* buffer); void write(unsigned char* buffer); bool operator==(const pnVaultNodeRef& ref) const; + bool operator!=(const pnVaultNodeRef& ref) const { return !operator==(ref); } }; #endif From b6ec814117d89009d6ad96ac0e6245077af19392 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 13 Apr 2025 23:54:34 +0200 Subject: [PATCH 5/5] Re-implement previous plLocation comparison behavior for FindPage, etc. Otherwise the plAgeInfo methods getPageLoc, getCommonPageLoc, and getPageLocs can no longer be used, because they return locations whose flags do not necessarily match the flags of the real corresponding pages (and those methods *cannot* be fixed to return the correct flags in the general case, because of the kItinerant flag, which cannot be predicted from other properties of the page). This fixes the crash when opening an .age file in PrpShop, caused by the preceding commits. --- core/PRP/KeyedObject/plLocation.cpp | 5 +++++ core/PRP/KeyedObject/plLocation.h | 3 +++ core/ResManager/plResManager.cpp | 14 +++++++------- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/core/PRP/KeyedObject/plLocation.cpp b/core/PRP/KeyedObject/plLocation.cpp index 41ed3cde8..a30f33c1f 100644 --- a/core/PRP/KeyedObject/plLocation.cpp +++ b/core/PRP/KeyedObject/plLocation.cpp @@ -36,6 +36,11 @@ bool plLocation::operator<(const plLocation& other) const } } +bool plLocation::isSamePage(const plLocation& other) const +{ + return fState == other.fState && fSeqPrefix == other.fSeqPrefix && fPageNum == other.fPageNum; +} + void plLocation::parse(unsigned int id) { if (id == 0xFFFFFFFF) { diff --git a/core/PRP/KeyedObject/plLocation.h b/core/PRP/KeyedObject/plLocation.h index 56e760681..8dcb93511 100644 --- a/core/PRP/KeyedObject/plLocation.h +++ b/core/PRP/KeyedObject/plLocation.h @@ -56,6 +56,9 @@ class HSPLASMA_EXPORT plLocation bool operator!=(const plLocation& other) const { return !operator==(other); } bool operator<(const plLocation& other) const; + /** Compare two locations only by their state and sequence number, ignoring flags. */ + bool isSamePage(const plLocation& other) const; + void parse(unsigned int id); unsigned int unparse() const; diff --git a/core/ResManager/plResManager.cpp b/core/ResManager/plResManager.cpp index 37f8ed766..226c7fc25 100644 --- a/core/ResManager/plResManager.cpp +++ b/core/ResManager/plResManager.cpp @@ -273,7 +273,7 @@ plPageInfo* plResManager::FindPage(const plLocation& loc) { std::vector::iterator pi = pages.begin(); while (pi != pages.end()) { - if ((*pi)->getLocation() == loc) + if ((*pi)->getLocation().isSamePage(loc)) return *pi; pi++; } @@ -282,16 +282,16 @@ plPageInfo* plResManager::FindPage(const plLocation& loc) void plResManager::UnloadPage(const plLocation& loc) { - // Make a copy, in case someone passed us the page's getLocation() reference - plLocation pageLoc = loc; - for (auto it = pages.begin(); it != pages.end(); it++) { - if ((*it)->getLocation() == loc) { + if ((*it)->getLocation().isSamePage(loc)) { + // Copy the location so we can still use it + // after the plPageInfo has been deleted. + plLocation foundLocation = (*it)->getLocation(); if (pageUnloadFunc) - pageUnloadFunc(loc); + pageUnloadFunc(foundLocation); delete *it; pages.erase(it); - keys.delAll(pageLoc); + keys.delAll(foundLocation); break; } }