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

2
Source/controls/plrctrls.cpp

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

6
Source/diablo.cpp

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

2
Source/panels/spell_list.cpp

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

61
Source/utils/string_or_view.hpp

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

Loading…
Cancel
Save