diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 3754049aa..1960011fb 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/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[] = { diff --git a/Source/DiabloUI/title.cpp b/Source/DiabloUI/title.cpp index d8c43e2c4..afd22a7be 100644 --- a/Source/DiabloUI/title.cpp +++ b/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 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; } diff --git a/Source/control.cpp b/Source/control.cpp index 9a40e7f3a..0f9a1d496 100644 --- a/Source/control.cpp +++ b/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)); diff --git a/Source/debug.cpp b/Source/debug.cpp index 189d82f32..59355a775 100644 --- a/Source/debug.cpp +++ b/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; diff --git a/Source/dvlnet/zerotier_native.cpp b/Source/dvlnet/zerotier_native.cpp index 791250151..21696d3d3 100644 --- a/Source/dvlnet/zerotier_native.cpp +++ b/Source/dvlnet/zerotier_native.cpp @@ -27,6 +27,7 @@ #include #include +#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) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index e81942eb6..c85efb634 100644 --- a/Source/engine/render/text_render.cpp +++ b/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); } diff --git a/Source/inv.h b/Source/inv.h index b65d64970..96e4eb866 100644 --- a/Source/inv.h +++ b/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 bool HasInventoryItem(Player &player, Predicate &&predicate) { const InventoryPlayerItemsRange items { player }; - return std::find_if(items.begin(), items.end(), std::forward(predicate)) != items.end(); + return c_find_if(items, std::forward(predicate)) != items.end(); } /** @@ -257,7 +258,7 @@ template bool HasBeltItem(Player &player, Predicate &&predicate) { const BeltPlayerItemsRange items { player }; - return std::find_if(items.begin(), items.end(), std::forward(predicate)) != items.end(); + return c_find_if(items, std::forward(predicate)) != items.end(); } /** @@ -306,7 +307,7 @@ template bool RemoveInventoryItem(Player &player, Predicate &&predicate) { const InventoryPlayerItemsRange items { player }; - const auto it = std::find_if(items.begin(), items.end(), std::forward(predicate)); + const auto it = c_find_if(items, std::forward(predicate)); if (it == items.end()) return false; player.RemoveInvItem(static_cast(it.index())); @@ -322,7 +323,7 @@ template bool RemoveBeltItem(Player &player, Predicate &&predicate) { const BeltPlayerItemsRange items { player }; - const auto it = std::find_if(items.begin(), items.end(), std::forward(predicate)); + const auto it = c_find_if(items, std::forward(predicate)); if (it == items.end()) return false; player.RemoveSpdBarItem(static_cast(it.index())); diff --git a/Source/levels/themes.cpp b/Source/levels/themes.cpp index afaf0b910..29c9cabf4 100644 --- a/Source/levels/themes.cpp +++ b/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; } diff --git a/Source/levels/trigs.cpp b/Source/levels/trigs.cpp index 75765d23e..46b85487e 100644 --- a/Source/levels/trigs.cpp +++ b/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 diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index e43fff4b5..7d2329f4a 100644 --- a/Source/loadsave.cpp +++ b/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 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; }); })) { diff --git a/Source/options.cpp b/Source/options.cpp index 66c5a26bc..548291381 100644 --- a/Source/options.cpp +++ b/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); diff --git a/Source/panels/charpanel.cpp b/Source/panels/charpanel.cpp index 79d5216bf..cbb3d3073 100644 --- a/Source/panels/charpanel.cpp +++ b/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); diff --git a/Source/panels/spell_list.cpp b/Source/panels/spell_list.cpp index 162d4dcd4..7953413f5 100644 --- a/Source/panels/spell_list.cpp +++ b/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)); diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index 84fdd190d..6fa94c559 100644 --- a/Source/plrmsg.cpp +++ b/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 Messages; int CountLinesOfText(string_view text) { - return 1 + std::count(text.begin(), text.end(), '\n'); + return 1 + c_count(text, '\n'); } PlayerMessage &GetNextMessage() diff --git a/Source/qol/autopickup.cpp b/Source/qol/autopickup.cpp index 8da479d34..c66ffd936 100644 --- a/Source/qol/autopickup.cpp +++ b/Source/qol/autopickup.cpp @@ -3,11 +3,14 @@ * * QoL feature for automatically picking up gold */ +#include "qol/autopickup.h" + +#include #include "inv_iterators.hpp" #include "options.h" #include "player.h" -#include +#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) diff --git a/Source/qol/autopickup.h b/Source/qol/autopickup.h index 089b003e1..924ea11c2 100644 --- a/Source/qol/autopickup.h +++ b/Source/qol/autopickup.h @@ -6,6 +6,8 @@ #pragma once +#include "player.h" + namespace devilution { void AutoPickup(const Player &player); diff --git a/Source/utils/algorithm/container.hpp b/Source/utils/algorithm/container.hpp new file mode 100644 index 000000000..03ff2a7af --- /dev/null +++ b/Source/utils/algorithm/container.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include +#include +#include +#include + +namespace devilution { + +// Internal namespace that sets up ADL lookup and the container Iterator type. +namespace container_internal { +using std::begin; +using std::end; + +template +using Iterator = decltype(begin(std::declval())); + +template +using Difference = typename std::iterator_traits>::difference_type; + +template +Iterator c_begin(C &c) +{ + return begin(c); +} + +template +Iterator c_end(C &c) +{ + return end(c); +} + +} // namespace container_internal + +template +bool c_any_of(const C &c, Predicate &&predicate) +{ + return std::any_of(container_internal::begin(c), + container_internal::end(c), + std::forward(predicate)); +} + +template +bool c_all_of(const C &c, Predicate &&predicate) +{ + return std::all_of(container_internal::begin(c), + container_internal::end(c), + std::forward(predicate)); +} + +template +bool c_none_of(const C &c, Predicate &&predicate) +{ + return std::none_of(container_internal::begin(c), + container_internal::end(c), + std::forward(predicate)); +} + +template +container_internal::Iterator +c_find_if(C &c, Predicate &&predicate) +{ + return std::find_if(container_internal::begin(c), + container_internal::end(c), + std::forward(predicate)); +} + +template +container_internal::Difference +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)); +} + +template +container_internal::Difference +c_count(const C &c, T &&value) +{ + return std::count(container_internal::c_begin(c), + container_internal::c_end(c), + std::forward(value)); +} + +} // namespace devilution diff --git a/Source/utils/language.cpp b/Source/utils/language.cpp index 18157d510..24f04b4e2 100644 --- a/Source/utils/language.cpp +++ b/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(); }); }