Browse Source

Add `c_any_of` and friends

Adds handy helpers for performing algorithms on the entire container.
They're prefixed with `c_` for container.

This naming convention is identical to some popular C++ libraries, such
as Abseil.
pull/6458/head
Gleb Mazovetskiy 3 years ago
parent
commit
8101e2c0ba
  1. 3
      Source/DiabloUI/diabloui.cpp
  2. 4
      Source/DiabloUI/title.cpp
  3. 10
      Source/control.cpp
  4. 5
      Source/debug.cpp
  5. 3
      Source/dvlnet/zerotier_native.cpp
  6. 7
      Source/engine/render/text_render.cpp
  7. 9
      Source/inv.h
  8. 7
      Source/levels/themes.cpp
  9. 8
      Source/levels/trigs.cpp
  10. 5
      Source/loadsave.cpp
  11. 7
      Source/options.cpp
  12. 3
      Source/panels/charpanel.cpp
  13. 4
      Source/panels/spell_list.cpp
  14. 3
      Source/plrmsg.cpp
  15. 9
      Source/qol/autopickup.cpp
  16. 2
      Source/qol/autopickup.h
  17. 86
      Source/utils/algorithm/container.hpp
  18. 3
      Source/utils/language.cpp

3
Source/DiabloUI/diabloui.cpp

@ -19,6 +19,7 @@
#include "engine/load_pcx.hpp"
#include "engine/render/clx_render.hpp"
#include "hwcursor.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/display.h"
#include "utils/language.h"
#include "utils/log.hpp"
@ -651,7 +652,7 @@ bool UiValidPlayerName(string_view name)
// Only basic latin alphabet is supported for multiplayer characters to avoid rendering issues for players who do
// not have fonts.mpq installed
if (!std::all_of(name.begin(), name.end(), IsBasicLatin))
if (!c_all_of(name, IsBasicLatin))
return false;
string_view bannedNames[] = {

4
Source/DiabloUI/title.cpp

@ -5,6 +5,7 @@
#include "discord/discord.h"
#include "engine/load_clx.hpp"
#include "engine/load_pcx.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/language.h"
#include "utils/sdl_geometry.h"
#include "utils/stdcompat/optional.hpp"
@ -68,8 +69,7 @@ void UiTitleDialog()
discord_manager::UpdateMenu();
while (PollEvent(&event) != 0) {
std::vector<MenuAction> menuActions = GetMenuActions(event);
if (std::any_of(menuActions.begin(), menuActions.end(), [](auto menuAction) { return menuAction != MenuAction_NONE; })) {
if (c_any_of(GetMenuActions(event), [](MenuAction menuAction) { return menuAction != MenuAction_NONE; })) {
endMenu = true;
break;
}

10
Source/control.cpp

@ -44,6 +44,7 @@
#include "qol/xpbar.h"
#include "stores.h"
#include "towners.h"
#include "utils/algorithm/container.hpp"
#include "utils/format_int.hpp"
#include "utils/language.h"
#include "utils/log.hpp"
@ -257,7 +258,7 @@ void PrintInfo(const Surface &out)
const int space[] = { 18, 12, 6, 3, 0 };
Rectangle infoArea { GetMainPanel().position + Displacement { 177, 46 }, { 288, 60 } };
const int newLineCount = std::count(InfoString.str().begin(), InfoString.str().end(), '\n');
const int newLineCount = c_count(InfoString.str(), '\n');
const int spaceIndex = std::min(4, newLineCount);
const int spacing = space[spaceIndex];
const int lineHeight = 12 + spacing;
@ -351,7 +352,7 @@ std::string TextCmdHelp(const string_view parameter)
}
return ret;
}
auto textCmdIterator = std::find_if(TextCmdList.begin(), TextCmdList.end(), [&](const TextCmdItem &elem) { return elem.text == parameter; });
auto textCmdIterator = c_find_if(TextCmdList, [&](const TextCmdItem &elem) { return elem.text == parameter; });
if (textCmdIterator == TextCmdList.end())
return StrCat(_("Command "), parameter, _(" is unkown."));
auto &textCmdItem = *textCmdIterator;
@ -533,7 +534,7 @@ bool CheckTextCommand(const string_view text)
if (text.size() < 1 || text[0] != '/')
return false;
auto textCmdIterator = std::find_if(TextCmdList.begin(), TextCmdList.end(), [&](const TextCmdItem &elem) { return text.find(elem.text) == 0 && (text.length() == elem.text.length() || text[elem.text.length()] == ' '); });
auto textCmdIterator = c_find_if(TextCmdList, [&](const TextCmdItem &elem) { return text.find(elem.text) == 0 && (text.length() == elem.text.length() || text[elem.text.length()] == ' '); });
if (textCmdIterator == TextCmdList.end()) {
InitDiabloMsg(StrCat(_("Command \""), text, "\" is unknown."));
return true;
@ -1039,8 +1040,7 @@ void CheckPanelInfo()
} break;
case SpellType::Scroll: {
AddPanelString(fmt::format(fmt::runtime(_("Scroll of {:s}")), pgettext("spell", GetSpellData(spellId).sNameText)));
const InventoryAndBeltPlayerItemsRange items { myPlayer };
const int scrollCount = std::count_if(items.begin(), items.end(), [spellId](const Item &item) {
const int scrollCount = c_count_if(InventoryAndBeltPlayerItemsRange { myPlayer }, [spellId](const Item &item) {
return item.isScrollOf(spellId);
});
AddPanelString(fmt::format(fmt::runtime(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount)), scrollCount));

5
Source/debug.cpp

@ -28,6 +28,7 @@
#include "quests.h"
#include "spells.h"
#include "towners.h"
#include "utils/algorithm/container.hpp"
#include "utils/endian_stream.hpp"
#include "utils/file_util.h"
#include "utils/language.h"
@ -139,7 +140,7 @@ std::string DebugCmdHelp(const string_view parameter)
}
return ret;
}
auto debugCmdIterator = std::find_if(DebugCmdList.begin(), DebugCmdList.end(), [&](const DebugCmdItem &elem) { return elem.text == parameter; });
auto debugCmdIterator = c_find_if(DebugCmdList, [&](const DebugCmdItem &elem) { return elem.text == parameter; });
if (debugCmdIterator == DebugCmdList.end())
return StrCat("Debug command ", parameter, " wasn't found");
auto &dbgCmdItem = *debugCmdIterator;
@ -1122,7 +1123,7 @@ void SetDebugLevelSeedInfos(uint32_t mid1Seed, uint32_t mid2Seed, uint32_t mid3S
bool CheckDebugTextCommand(const string_view text)
{
auto debugCmdIterator = std::find_if(DebugCmdList.begin(), DebugCmdList.end(), [&](const DebugCmdItem &elem) { return text.find(elem.text) == 0 && (text.length() == elem.text.length() || text[elem.text.length()] == ' '); });
auto debugCmdIterator = c_find_if(DebugCmdList, [&](const DebugCmdItem &elem) { return text.find(elem.text) == 0 && (text.length() == elem.text.length() || text[elem.text.length()] == ' '); });
if (debugCmdIterator == DebugCmdList.end())
return false;

3
Source/dvlnet/zerotier_native.cpp

@ -27,6 +27,7 @@
#include <ZeroTierSockets.h>
#include <cstdlib>
#include "utils/algorithm/container.hpp"
#include "utils/log.hpp"
#include "utils/paths.h"
@ -40,7 +41,7 @@ namespace {
#ifdef DVL_ZT_SYMLINK
bool HasMultiByteChars(string_view path)
{
return std::any_of(path.begin(), path.end(), IsTrailUtf8CodeUnit);
return c_any_of(path, IsTrailUtf8CodeUnit);
}
std::string ComputeAlternateFolderName(string_view path)

7
Source/engine/render/text_render.cpp

@ -23,6 +23,7 @@
#include "engine/palette.h"
#include "engine/point.hpp"
#include "engine/render/clx_render.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/display.h"
#include "utils/language.h"
#include "utils/sdl_compat.h"
@ -241,10 +242,10 @@ bool IsBreakAllowed(char32_t codepoint, char32_t nextCodepoint)
std::size_t CountNewlines(string_view fmt, const DrawStringFormatArg *args, std::size_t argsLen)
{
std::size_t result = std::count(fmt.begin(), fmt.end(), '\n');
std::size_t result = c_count(fmt, '\n');
for (std::size_t i = 0; i < argsLen; ++i) {
if (args[i].GetType() == DrawStringFormatArg::Type::StringView)
result += std::count(args[i].GetFormatted().begin(), args[i].GetFormatted().end(), '\n');
result += c_count(args[i].GetFormatted(), '\n');
}
return result;
}
@ -662,7 +663,7 @@ uint32_t DrawString(const Surface &out, string_view text, const Rectangle &rect,
lineHeight = GetLineHeight(text, size);
if (HasAnyOf(flags, UiFlags::VerticalCenter)) {
int textHeight = (std::count(text.cbegin(), text.cend(), '\n') + 1) * lineHeight;
int textHeight = (c_count(text, '\n') + 1) * lineHeight;
characterPosition.y += std::max(0, (rect.size.height - textHeight) / 2);
}

9
Source/inv.h

@ -12,6 +12,7 @@
#include "inv_iterators.hpp"
#include "items.h"
#include "player.h"
#include "utils/algorithm/container.hpp"
namespace devilution {
@ -247,7 +248,7 @@ template <typename Predicate>
bool HasInventoryItem(Player &player, Predicate &&predicate)
{
const InventoryPlayerItemsRange items { player };
return std::find_if(items.begin(), items.end(), std::forward<Predicate>(predicate)) != items.end();
return c_find_if(items, std::forward<Predicate>(predicate)) != items.end();
}
/**
@ -257,7 +258,7 @@ template <typename Predicate>
bool HasBeltItem(Player &player, Predicate &&predicate)
{
const BeltPlayerItemsRange items { player };
return std::find_if(items.begin(), items.end(), std::forward<Predicate>(predicate)) != items.end();
return c_find_if(items, std::forward<Predicate>(predicate)) != items.end();
}
/**
@ -306,7 +307,7 @@ template <typename Predicate>
bool RemoveInventoryItem(Player &player, Predicate &&predicate)
{
const InventoryPlayerItemsRange items { player };
const auto it = std::find_if(items.begin(), items.end(), std::forward<Predicate>(predicate));
const auto it = c_find_if(items, std::forward<Predicate>(predicate));
if (it == items.end())
return false;
player.RemoveInvItem(static_cast<int>(it.index()));
@ -322,7 +323,7 @@ template <typename Predicate>
bool RemoveBeltItem(Player &player, Predicate &&predicate)
{
const BeltPlayerItemsRange items { player };
const auto it = std::find_if(items.begin(), items.end(), std::forward<Predicate>(predicate));
const auto it = c_find_if(items, std::forward<Predicate>(predicate));
if (it == items.end())
return false;
player.RemoveSpdBarItem(static_cast<int>(it.index()));

7
Source/levels/themes.cpp

@ -17,6 +17,7 @@
#include "monster.h"
#include "objects.h"
#include "quests.h"
#include "utils/algorithm/container.hpp"
#include "utils/str_cat.hpp"
namespace devilution {
@ -87,8 +88,7 @@ bool TFit_Shrine(int i)
bool CheckThemeObj5(Point origin, int8_t regionId)
{
const auto searchArea = PointsInRectangle(Rectangle { origin, 2 });
return std::all_of(searchArea.cbegin(), searchArea.cend(), [regionId](Point testPosition) {
return c_all_of(PointsInRectangle(Rectangle { origin, 2 }), [regionId](Point testPosition) {
// note out-of-bounds tiles are not solid, this function relies on the guard in TFit_Obj5 and dungeon border
if (IsTileSolid(testPosition)) {
return false;
@ -154,8 +154,7 @@ bool TFit_GoatShrine(int t)
bool CheckThemeObj3(Point origin, int8_t regionId, unsigned frequency = 0)
{
const auto searchArea = PointsInRectangle(Rectangle { origin, 1 });
return std::all_of(searchArea.cbegin(), searchArea.cend(), [regionId, frequency](Point testPosition) {
return c_all_of(PointsInRectangle(Rectangle { origin, 1 }), [regionId, frequency](Point testPosition) {
if (!InDungeonBounds(testPosition)) {
return false;
}

8
Source/levels/trigs.cpp

@ -14,6 +14,7 @@
#include "cursor.h"
#include "error.h"
#include "init.h"
#include "utils/algorithm/container.hpp"
#include "utils/language.h"
#include "utils/utf8.hpp"
@ -934,10 +935,9 @@ bool EntranceBoundaryContains(Point entrance, Point position)
{
constexpr Displacement entranceOffsets[7] = { { 0, 0 }, { -1, 0 }, { 0, -1 }, { -1, -1 }, { -2, -1 }, { -1, -2 }, { -2, -2 } };
return std::any_of(
std::begin(entranceOffsets),
std::end(entranceOffsets),
[&](auto offset) { return entrance + offset == position; });
return c_any_of(
entranceOffsets,
[=](Displacement offset) { return entrance + offset == position; });
}
} // namespace devilution

5
Source/loadsave.cpp

@ -34,6 +34,7 @@
#include "playerdat.hpp"
#include "qol/stash.h"
#include "stores.h"
#include "utils/algorithm/container.hpp"
#include "utils/endian.hpp"
#include "utils/language.h"
@ -2338,8 +2339,8 @@ void SaveStash(SaveWriter &stashWriter)
std::vector<unsigned> pagesToSave;
for (const auto &stashPage : Stash.stashGrids) {
if (std::any_of(stashPage.second.cbegin(), stashPage.second.cend(), [](const auto &row) {
return std::any_of(row.cbegin(), row.cend(), [](auto cell) {
if (c_any_of(stashPage.second, [](const auto &row) {
return c_any_of(row, [](StashStruct::StashCell cell) {
return cell > 0;
});
})) {

7
Source/options.cpp

@ -24,6 +24,7 @@
#include "platform/locale.hpp"
#include "qol/monhealthbar.h"
#include "qol/xpbar.h"
#include "utils/algorithm/container.hpp"
#include "utils/display.h"
#include "utils/file_util.h"
#include "utils/language.h"
@ -806,7 +807,7 @@ string_view OptionEntryResolution::GetListDescription(size_t index) const
size_t OptionEntryResolution::GetActiveListIndex() const
{
CheckResolutionsAreInitialized();
auto found = std::find_if(resolutions.begin(), resolutions.end(), [this](const auto &x) { return x.first == this->size; });
auto found = c_find_if(resolutions, [this](const auto &x) { return x.first == this->size; });
if (found == resolutions.end())
return 0;
return std::distance(resolutions.begin(), found);
@ -1248,7 +1249,7 @@ void OptionEntryLanguageCode::CheckLanguagesAreInitialized() const
}
// Ensures that the ini specified language is present in languages list even if unknown (for example if someone starts to translate a new language)
if (std::find_if(languages.begin(), languages.end(), [this](const auto &x) { return x.first == this->szCode; }) == languages.end()) {
if (c_find_if(languages, [this](const auto &x) { return x.first == this->szCode; }) == languages.end()) {
languages.emplace_back(szCode, szCode);
}
}
@ -1266,7 +1267,7 @@ string_view OptionEntryLanguageCode::GetListDescription(size_t index) const
size_t OptionEntryLanguageCode::GetActiveListIndex() const
{
CheckLanguagesAreInitialized();
auto found = std::find_if(languages.begin(), languages.end(), [this](const auto &x) { return x.first == this->szCode; });
auto found = c_find_if(languages, [this](const auto &x) { return x.first == this->szCode; });
if (found == languages.end())
return 0;
return std::distance(languages.begin(), found);

3
Source/panels/charpanel.cpp

@ -15,6 +15,7 @@
#include "panels/ui_panels.hpp"
#include "player.h"
#include "playerdat.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/display.h"
#include "utils/format_int.hpp"
#include "utils/language.h"
@ -240,7 +241,7 @@ void DrawShadowString(const Surface &out, const PanelEntry &entry)
// If the text is less tall then the field, we center it vertically relative to the field.
// Otherwise, we draw from the top of the field.
const int textHeight = (std::count(wrapped.begin(), wrapped.end(), '\n') + 1) * GetLineHeight(wrapped, GameFont12);
const int textHeight = (c_count(wrapped, '\n') + 1) * GetLineHeight(wrapped, GameFont12);
const int labelHeight = std::max(PanelFieldHeight, textHeight);
DrawString(out, text, { labelPosition + Displacement { -2, 2 }, { entry.labelLength, labelHeight } }, style | UiFlags::ColorBlack, Spacing);

4
Source/panels/spell_list.cpp

@ -15,6 +15,7 @@
#include "panels/spell_icons.hpp"
#include "player.h"
#include "spells.h"
#include "utils/algorithm/container.hpp"
#include "utils/language.h"
#include "utils/str_cat.hpp"
#include "utils/utf8.hpp"
@ -170,8 +171,7 @@ void DrawSpellList(const Surface &out)
}
PrintSBookSpellType(out, spellListItem.location, _("Scroll"), spellColor);
InfoString = fmt::format(fmt::runtime(_("Scroll of {:s}")), pgettext("spell", spellDataItem.sNameText));
const InventoryAndBeltPlayerItemsRange items { myPlayer };
const int scrollCount = std::count_if(items.begin(), items.end(), [spellId](const Item &item) {
const int scrollCount = c_count_if(InventoryAndBeltPlayerItemsRange { myPlayer }, [spellId](const Item &item) {
return item.isScrollOf(spellId);
});
AddPanelString(fmt::format(fmt::runtime(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount)), scrollCount));

3
Source/plrmsg.cpp

@ -15,6 +15,7 @@
#include "inv.h"
#include "qol/chatlog.h"
#include "qol/stash.h"
#include "utils/algorithm/container.hpp"
#include "utils/language.h"
#include "utils/utf8.hpp"
@ -39,7 +40,7 @@ std::array<PlayerMessage, 8> Messages;
int CountLinesOfText(string_view text)
{
return 1 + std::count(text.begin(), text.end(), '\n');
return 1 + c_count(text, '\n');
}
PlayerMessage &GetNextMessage()

9
Source/qol/autopickup.cpp

@ -3,11 +3,14 @@
*
* QoL feature for automatically picking up gold
*/
#include "qol/autopickup.h"
#include <algorithm>
#include "inv_iterators.hpp"
#include "options.h"
#include "player.h"
#include <algorithm>
#include "utils/algorithm/container.hpp"
namespace devilution {
namespace {
@ -34,8 +37,8 @@ bool HasRoomForGold()
int NumMiscItemsInInv(int iMiscId)
{
InventoryAndBeltPlayerItemsRange items { *MyPlayer };
return std::count_if(items.begin(), items.end(), [iMiscId](const Item &item) { return item._iMiscId == iMiscId; });
return c_count_if(InventoryAndBeltPlayerItemsRange { *MyPlayer },
[iMiscId](const Item &item) { return item._iMiscId == iMiscId; });
}
bool DoPickup(Item item)

2
Source/qol/autopickup.h

@ -6,6 +6,8 @@
#pragma once
#include "player.h"
namespace devilution {
void AutoPickup(const Player &player);

86
Source/utils/algorithm/container.hpp

@ -0,0 +1,86 @@
#pragma once
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <utility>
namespace devilution {
// Internal namespace that sets up ADL lookup and the container Iterator type.
namespace container_internal {
using std::begin;
using std::end;
template <typename C>
using Iterator = decltype(begin(std::declval<C &>()));
template <typename C>
using Difference = typename std::iterator_traits<Iterator<C>>::difference_type;
template <typename C>
Iterator<C> c_begin(C &c)
{
return begin(c);
}
template <typename C>
Iterator<C> c_end(C &c)
{
return end(c);
}
} // namespace container_internal
template <typename C, typename Predicate>
bool c_any_of(const C &c, Predicate &&predicate)
{
return std::any_of(container_internal::begin(c),
container_internal::end(c),
std::forward<Predicate>(predicate));
}
template <typename C, typename Predicate>
bool c_all_of(const C &c, Predicate &&predicate)
{
return std::all_of(container_internal::begin(c),
container_internal::end(c),
std::forward<Predicate>(predicate));
}
template <typename C, typename Predicate>
bool c_none_of(const C &c, Predicate &&predicate)
{
return std::none_of(container_internal::begin(c),
container_internal::end(c),
std::forward<Predicate>(predicate));
}
template <typename C, typename Predicate>
container_internal::Iterator<C>
c_find_if(C &c, Predicate &&predicate)
{
return std::find_if(container_internal::begin(c),
container_internal::end(c),
std::forward<Predicate>(predicate));
}
template <typename C, typename Predicate>
container_internal::Difference<C>
c_count_if(const C &c, Predicate &&predicate)
{
return std::count_if(container_internal::c_begin(c),
container_internal::c_end(c),
std::forward<Predicate>(predicate));
}
template <typename C, typename T>
container_internal::Difference<C>
c_count(const C &c, T &&value)
{
return std::count(container_internal::c_begin(c),
container_internal::c_end(c),
std::forward<T>(value));
}
} // namespace devilution

3
Source/utils/language.cpp

@ -9,6 +9,7 @@
#include "engine/assets.hpp"
#include "options.h"
#include "utils/algorithm/container.hpp"
#include "utils/file_util.h"
#include "utils/log.hpp"
#include "utils/paths.h"
@ -338,7 +339,7 @@ bool HasTranslation(const std::string &locale)
return true;
}
return std::any_of(Extensions.cbegin(), Extensions.cend(), [locale](const char *extension) {
return c_any_of(Extensions, [locale](const char *extension) {
return FindAsset((locale + extension).c_str()).ok();
});
}

Loading…
Cancel
Save