Browse Source

Use `std::variant` in `StringOrView`

We also add a direct string move-assignment (`operator=(std::string &&)`),
which results in better codegen.

As a consequence, we have to replace `= {}` assignments with `= StringOrView {}`
because `= {}` is now ambiguous.
pull/6466/head
Gleb Mazovetskiy 3 years ago
parent
commit
d5446f2f01
  1. 4
      Source/control.cpp
  2. 2
      Source/controls/plrctrls.cpp
  3. 6
      Source/diablo.cpp
  4. 2
      Source/panels/spell_list.cpp
  5. 61
      Source/utils/string_or_view.hpp

4
Source/control.cpp

@ -883,7 +883,7 @@ void InitControlPan()
for (bool &buttonEnabled : chrbtn) for (bool &buttonEnabled : chrbtn)
buttonEnabled = false; buttonEnabled = false;
chrbtnactive = false; chrbtnactive = false;
InfoString = {}; InfoString = StringOrView {};
RedrawComponent(PanelDrawComponent::Health); RedrawComponent(PanelDrawComponent::Health);
RedrawComponent(PanelDrawComponent::Mana); RedrawComponent(PanelDrawComponent::Mana);
CloseCharPanel(); CloseCharPanel();
@ -1165,7 +1165,7 @@ void DrawInfoBox(const Surface &out)
{ {
DrawPanelBox(out, { 177, 62, 288, 63 }, GetMainPanel().position + Displacement { 177, 46 }); DrawPanelBox(out, { 177, 62, 288, 63 }, GetMainPanel().position + Displacement { 177, 46 });
if (!panelflag && !trigflag && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && !spselflag) { if (!panelflag && !trigflag && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && !spselflag) {
InfoString = {}; InfoString = StringOrView {};
InfoColor = UiFlags::ColorWhite; InfoColor = UiFlags::ColorWhite;
} }
Player &myPlayer = *MyPlayer; Player &myPlayer = *MyPlayer;

2
Source/controls/plrctrls.cpp

@ -1781,7 +1781,7 @@ void plrctrls_after_check_curs_move()
return; return;
} }
if (!invflag) { if (!invflag) {
InfoString = {}; InfoString = StringOrView {};
FindActor(); FindActor();
FindItemOrObject(); FindItemOrObject();
FindTrigger(); FindTrigger();

6
Source/diablo.cpp

@ -1435,7 +1435,7 @@ void TimeoutCursor(bool bTimeout)
if (sgnTimeoutCurs == CURSOR_NONE && sgbMouseDown == CLICK_NONE) { if (sgnTimeoutCurs == CURSOR_NONE && sgbMouseDown == CLICK_NONE) {
sgnTimeoutCurs = pcurs; sgnTimeoutCurs = pcurs;
multi_net_ping(); multi_net_ping();
InfoString = {}; InfoString = StringOrView {};
AddPanelString(_("-- Network timeout --")); AddPanelString(_("-- Network timeout --"));
AddPanelString(_("-- Waiting for players --")); AddPanelString(_("-- Waiting for players --"));
NewCursor(CURSOR_HOURGLASS); NewCursor(CURSOR_HOURGLASS);
@ -1449,7 +1449,7 @@ void TimeoutCursor(bool bTimeout)
if (pcurs == CURSOR_HOURGLASS) if (pcurs == CURSOR_HOURGLASS)
NewCursor(sgnTimeoutCurs); NewCursor(sgnTimeoutCurs);
sgnTimeoutCurs = CURSOR_NONE; sgnTimeoutCurs = CURSOR_NONE;
InfoString = {}; InfoString = StringOrView {};
RedrawEverything(); RedrawEverything();
} }
} }
@ -1459,7 +1459,7 @@ void HelpKeyPressed()
if (HelpFlag) { if (HelpFlag) {
HelpFlag = false; HelpFlag = false;
} else if (stextflag != TalkID::None) { } else if (stextflag != TalkID::None) {
InfoString = {}; InfoString = StringOrView {};
AddPanelString(_("No help available")); /// BUGFIX: message isn't displayed AddPanelString(_("No help available")); /// BUGFIX: message isn't displayed
AddPanelString(_("while in stores")); AddPanelString(_("while in stores"));
LastMouseButtonAction = MouseActionType::None; LastMouseButtonAction = MouseActionType::None;

2
Source/panels/spell_list.cpp

@ -114,7 +114,7 @@ void DrawSpell(const Surface &out)
void DrawSpellList(const Surface &out) void DrawSpellList(const Surface &out)
{ {
InfoString = {}; InfoString = StringOrView {};
Player &myPlayer = *MyPlayer; Player &myPlayer = *MyPlayer;

61
Source/utils/string_or_view.hpp

@ -3,78 +3,51 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <variant>
namespace devilution { namespace devilution {
class StringOrView { class StringOrView {
public: public:
StringOrView() StringOrView()
: owned_(false) : rep_ { std::string_view {} }
, view_()
{ {
} }
StringOrView(StringOrView &&) noexcept = default;
StringOrView(std::string &&str) StringOrView(std::string &&str)
: owned_(true) : rep_ { std::move(str) }
, str_(std::move(str))
{ {
} }
StringOrView(std::string_view str) StringOrView(std::string_view str)
: owned_(false) : rep_ { str }
, view_(str)
{ {
} }
StringOrView(StringOrView &&other) noexcept StringOrView &operator=(StringOrView &&) noexcept = default;
: owned_(other.owned_)
{
if (other.owned_) {
new (&str_) std::string(std::move(other.str_));
} else {
new (&view_) std::string_view(other.view_);
}
}
StringOrView &operator=(StringOrView &&other) noexcept StringOrView &operator=(std::string &&value) noexcept
{ {
if (owned_) { rep_ = std::move(value);
if (other.owned_) {
str_ = std::move(other.str_);
} else {
str_.~basic_string();
owned_ = false;
new (&view_) std::string_view(other.view_);
}
} else {
if (other.owned_) {
view_.~basic_string_view();
owned_ = true;
new (&str_) std::string(std::move(other.str_));
} else {
view_ = other.view_;
}
}
return *this; return *this;
} }
~StringOrView() StringOrView &operator=(std::string_view value) noexcept
{ {
if (owned_) { rep_ = value;
str_.~basic_string(); return *this;
} else {
view_.~basic_string_view();
}
} }
bool empty() const bool empty() const
{ {
return owned_ ? str_.empty() : view_.empty(); return std::visit([](auto &&val) -> bool { return val.empty(); }, rep_);
} }
std::string_view str() const std::string_view str() const
{ {
return owned_ ? str_ : view_; return std::visit([](auto &&val) -> std::string_view { return val; }, rep_);
} }
operator std::string_view() const operator std::string_view() const
@ -83,11 +56,7 @@ public:
} }
private: private:
bool owned_; std::variant<std::string, std::string_view> rep_;
union {
std::string str_;
std::string_view view_;
};
}; };
} // namespace devilution } // namespace devilution

Loading…
Cancel
Save