diff --git a/include/stratosphere/defines.hpp b/include/stratosphere/defines.hpp index f054535f..5df9d676 100644 --- a/include/stratosphere/defines.hpp +++ b/include/stratosphere/defines.hpp @@ -15,6 +15,7 @@ */ #pragma once +#include /* Any broadly useful language defines should go here. */ @@ -27,4 +28,23 @@ cls& operator=(cls&&) = delete #define ALIGNED(algn) __attribute__((aligned(algn))) -#define WEAK __attribute__((weak)) \ No newline at end of file +#define WEAK __attribute__((weak)) + +namespace sts::util { + + /* std::size() does not support zero-size C arrays. We're fixing that. */ + template + constexpr auto size(const C& c) -> decltype(c.size()) { + return std::size(c); + } + + template + constexpr std::size_t size(const C& c) { + if constexpr (sizeof(C) == 0) { + return 0; + } else { + return std::size(c); + } + } + +} \ No newline at end of file diff --git a/source/cfg/cfg_sd_card.cpp b/source/cfg/cfg_sd_card.cpp index a1c1ed7c..e561d975 100644 --- a/source/cfg/cfg_sd_card.cpp +++ b/source/cfg/cfg_sd_card.cpp @@ -30,7 +30,7 @@ namespace sts::cfg { sm::ServiceName::Encode("pinmux"), sm::ServiceName::Encode("psc:c") }; - constexpr size_t NumRequiredServicesForSdCardAccess = sizeof(RequiredServicesForSdCardAccess) / sizeof(RequiredServicesForSdCardAccess[0]); + constexpr size_t NumRequiredServicesForSdCardAccess = util::size(RequiredServicesForSdCardAccess); /* SD card globals. */ HosMutex g_sd_card_lock; diff --git a/source/updater/updater_paths.cpp b/source/updater/updater_paths.cpp index 3fa4920b..794297b5 100644 --- a/source/updater/updater_paths.cpp +++ b/source/updater/updater_paths.cpp @@ -67,12 +67,12 @@ namespace sts::updater { case BootImageUpdateType::Erista: { constexpr const char *candidates[] = {BctPathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } case BootImageUpdateType::Mariko: { constexpr const char *candidates[] = {BctPathA, BctPathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } default: std::abort(); @@ -84,12 +84,12 @@ namespace sts::updater { case BootImageUpdateType::Erista: { constexpr const char *candidates[] = {Package1PathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } case BootImageUpdateType::Mariko: { constexpr const char *candidates[] = {Package1PathA, Package1PathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } default: std::abort(); @@ -101,12 +101,12 @@ namespace sts::updater { case BootImageUpdateType::Erista: { constexpr const char *candidates[] = {Package2PathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } case BootImageUpdateType::Mariko: { constexpr const char *candidates[] = {Package2PathA, Package2PathNx}; - return ChooseCandidatePath(candidates, sizeof(candidates) / sizeof(candidates[0])); + return ChooseCandidatePath(candidates, util::size(candidates)); } default: std::abort();