diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp index c4472484603..f7fcce3db11 100644 --- a/src/buffer/out/TextAttribute.cpp +++ b/src/buffer/out/TextAttribute.cpp @@ -11,6 +11,8 @@ static_assert(sizeof(TextAttribute) == 14); static_assert(alignof(TextAttribute) == 2); // Ensure that we can memcpy() and memmove() the struct for performance. static_assert(std::is_trivially_copyable_v); +// Assert that the use of memcmp() for comparisons is safe. +static_assert(std::has_unique_object_representations_v); BYTE TextAttribute::s_legacyDefaultForeground = 7; BYTE TextAttribute::s_legacyDefaultBackground = 0; diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index 00f8a22665f..a675c19ed3a 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -83,12 +83,15 @@ class TextAttribute final void Invert() noexcept; - friend constexpr bool operator==(const TextAttribute& a, const TextAttribute& b) noexcept; - friend constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexcept; - friend constexpr bool operator==(const TextAttribute& attr, const WORD& legacyAttr) noexcept; - friend constexpr bool operator!=(const TextAttribute& attr, const WORD& legacyAttr) noexcept; - friend constexpr bool operator==(const WORD& legacyAttr, const TextAttribute& attr) noexcept; - friend constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept; + inline bool operator==(const TextAttribute& other) const noexcept + { + return memcmp(this, &other, sizeof(TextAttribute)) == 0; + } + + inline bool operator!=(const TextAttribute& other) const noexcept + { + return memcmp(this, &other, sizeof(TextAttribute)) != 0; + } bool IsLegacy() const noexcept; bool IsBold() const noexcept; @@ -179,7 +182,7 @@ class TextAttribute final uint16_t _hyperlinkId; // sizeof: 2, alignof: 2 TextColor _foreground; // sizeof: 4, alignof: 1 TextColor _background; // sizeof: 4, alignof: 1 - ExtendedAttributes _extendedAttrs; // sizeof: 1, alignof: 1 + ExtendedAttributes _extendedAttrs; // sizeof: 2, alignof: 2 #ifdef UNIT_TESTING friend class TextBufferTests; @@ -196,20 +199,6 @@ enum class TextAttributeBehavior StoredOnly, // only use the contained text attribute and skip the insertion of anything else }; -constexpr bool operator==(const TextAttribute& a, const TextAttribute& b) noexcept -{ - return a._wAttrLegacy == b._wAttrLegacy && - a._foreground == b._foreground && - a._background == b._background && - a._extendedAttrs == b._extendedAttrs && - a._hyperlinkId == b._hyperlinkId; -} - -constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexcept -{ - return !(a == b); -} - #ifdef UNIT_TESTING #define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \ diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index dcd0a8df342..b58d223722a 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -52,6 +52,8 @@ constexpr std::array Index256ToIndex16 = { // We should only need 4B for TextColor. Any more than that is just waste. static_assert(sizeof(TextColor) == 4); +// Assert that the use of memcmp() for comparisons is safe. +static_assert(std::has_unique_object_representations_v); bool TextColor::CanBeBrightened() const noexcept { @@ -109,6 +111,8 @@ void TextColor::SetIndex(const BYTE index, const bool isIndex256) noexcept { _meta = isIndex256 ? ColorType::IsIndex256 : ColorType::IsIndex16; _index = index; + _green = 0; + _blue = 0; } // Method Description: @@ -121,6 +125,9 @@ void TextColor::SetIndex(const BYTE index, const bool isIndex256) noexcept void TextColor::SetDefault() noexcept { _meta = ColorType::IsDefault; + _red = 0; + _green = 0; + _blue = 0; } // Method Description: diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h index ad984702fe1..47ff20009da 100644 --- a/src/buffer/out/TextColor.h +++ b/src/buffer/out/TextColor.h @@ -72,8 +72,15 @@ struct TextColor { } - friend constexpr bool operator==(const TextColor& a, const TextColor& b) noexcept; - friend constexpr bool operator!=(const TextColor& a, const TextColor& b) noexcept; + bool operator==(const TextColor& other) const noexcept + { + return memcmp(this, &other, sizeof(TextColor)) == 0; + } + + bool operator!=(const TextColor& other) const noexcept + { + return memcmp(this, &other, sizeof(TextColor)) != 0; + } bool CanBeBrightened() const noexcept; bool IsLegacy() const noexcept; @@ -112,19 +119,6 @@ struct TextColor #endif }; -bool constexpr operator==(const TextColor& a, const TextColor& b) noexcept -{ - return a._meta == b._meta && - a._red == b._red && - a._green == b._green && - a._blue == b._blue; -} - -bool constexpr operator!=(const TextColor& a, const TextColor& b) noexcept -{ - return !(a == b); -} - #ifdef UNIT_TESTING namespace WEX diff --git a/src/inc/conattrs.hpp b/src/inc/conattrs.hpp index cb911006435..364fef34aa0 100644 --- a/src/inc/conattrs.hpp +++ b/src/inc/conattrs.hpp @@ -8,7 +8,7 @@ Licensed under the MIT license. #define BG_ATTRS (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY) #define META_ATTRS (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE | COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_REVERSE_VIDEO | COMMON_LVB_UNDERSCORE) -enum class ExtendedAttributes : BYTE +enum class ExtendedAttributes : uint16_t { Normal = 0x00, Bold = 0x01,