fix cctype usage

According to the documentation, we should cast to unsigned char.
Anything negative is undefined behavior.
This commit is contained in:
Megamouse
2026-09-15 17:38:26 +02:00
parent b6bdf0d92d
commit ca522cf84c
36 changed files with 524 additions and 115 deletions
+21
View File
@@ -2,6 +2,7 @@
#include "Config.h"
#include "util/types.hpp"
#include "util/yaml.hpp"
#include "util/cctype.hpp"
#include <charconv>
@@ -712,6 +713,26 @@ bool cfg::node::validate(std::string_view value)
return false;
}
bool cfg::_bool::from_string(std::string_view value, bool /*dynamic*/)
{
if (value.size() != 4 && value.size() != 5)
{
return false;
}
char copy[5];
std::transform(value.begin(), value.end(), std::begin(copy), utils::tolower<char>);
if (value.size() == 5 && std::string_view{copy, 5} == "false")
m_value = false;
else if (value.size() == 4 && std::string_view{copy, 4} == "true")
m_value = true;
else
return false;
return true;
}
std::string cfg::map_entry::get_value(std::string_view key)
{
if (auto it = m_map.find(key); it != m_map.end())
+1 -19
View File
@@ -212,25 +212,7 @@ namespace cfg
return def ? "true" : "false";
}
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
{
if (value.size() != 4 && value.size() != 5)
{
return false;
}
char copy[5];
std::transform(value.begin(), value.end(), std::begin(copy), ::tolower);
if (value.size() == 5 && std::string_view{copy, 5} == "false")
m_value = false;
else if (value.size() == 4 && std::string_view{copy, 4} == "true")
m_value = true;
else
return false;
return true;
}
bool from_string(std::string_view value, bool dynamic = false) override;
void set(const bool& value)
{
+3 -1
View File
@@ -14,6 +14,8 @@
#if defined(__APPLE__)
#include <pthread.h>
#elif defined(ANDROID)
#include "util/cctype.hpp"
#endif
LOG_CHANNEL(jit_log, "JIT");
@@ -1039,7 +1041,7 @@ const char * fallback_cpu_detection()
return "cortex-a78";
}
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
std::transform(result.begin(), result.end(), result.begin(), utils::tolower<char>);
return result;
}();
+2 -1
View File
@@ -26,6 +26,7 @@
*/
#include "LUrlParser.h"
#include "util/cctype.hpp"
#include <algorithm>
#include <cstring>
@@ -36,7 +37,7 @@ static bool IsSchemeValid( const std::string& SchemeName )
{
return std::all_of(SchemeName.cbegin(), SchemeName.cend(), [](const auto& c)
{
return isalpha(c) || c == '+' || c == '-' || c == '.';
return utils::isalpha(c) || c == '+' || c == '-' || c == '.';
});
}
+6 -5
View File
@@ -3,6 +3,7 @@
#include "cfmt.h"
#include "util/endian.hpp"
#include "util/v128.hpp"
#include "util/cctype.hpp"
#include <locale>
#include <codecvt>
@@ -198,12 +199,12 @@ fmt::base57_result fmt::base57_result::from_string(std::string_view str)
{
auto to_val = [](u8 c) -> u64
{
if (std::isdigit(c))
if (utils::isdigit(c))
{
return c - '0';
}
if (std::isupper(c))
if (utils::isupper(c))
{
// Omitted characters
if (c == 'B' || c == 'D' || c == 'I' || c == 'O')
@@ -231,7 +232,7 @@ fmt::base57_result fmt::base57_result::from_string(std::string_view str)
return c - 'A' + 10;
}
if (std::islower(c))
if (utils::islower(c))
{
// Omitted characters
if (c == 'l')
@@ -952,7 +953,7 @@ std::string fmt::to_upper(std::string_view string)
{
std::string result;
result.resize(string.size());
std::transform(string.begin(), string.end(), result.begin(), ::toupper);
std::transform(string.begin(), string.end(), result.begin(), utils::toupper<char>);
return result;
}
@@ -960,7 +961,7 @@ std::string fmt::to_lower(std::string_view string)
{
std::string result;
result.resize(string.size());
std::transform(string.begin(), string.end(), result.begin(), ::tolower);
std::transform(string.begin(), string.end(), result.begin(), utils::tolower<char>);
return result;
}
+3 -2
View File
@@ -96,6 +96,7 @@ DYNAMIC_IMPORT_RENAME("Kernel32.dll", SetThreadDescriptionImport, "SetThreadDesc
#include "util/asm.hpp"
#include "util/v128.hpp"
#include "util/simd.hpp"
#include "util/cctype.hpp"
#include "util/sysinfo.hpp"
#include "Emu/Memory/vm_locking.h"
@@ -185,9 +186,9 @@ bool IsDebuggerPresent()
for (const char* cp = status.data() + found + 10; cp <= status.data() + num_read; ++cp)
{
if (!std::isspace(*cp))
if (!utils::isspace(*cp))
{
return std::isdigit(*cp) != 0 && *cp != '0';
return utils::isdigit(*cp) != 0 && *cp != '0';
}
}
+2 -1
View File
@@ -10,6 +10,7 @@
#include "util/types.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
#include <charconv>
#include <regex>
@@ -329,7 +330,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
is_valid = false;
continue;
}
else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c) { return std::isalnum(static_cast<unsigned char>(c)); }))
else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c) { return utils::isalnum(c); }))
{
append_log_message(log_messages, fmt::format("Error: Serial '%s' invalid (patch: %s, key: %s, location: %s, file: %s)", serial, description, main_key, get_yaml_node_location(serial_node), path), &patch_log.error);
is_valid = false;
+9 -7
View File
@@ -182,19 +182,21 @@ if(BUILD_RPCS3_TESTS)
target_sources(rpcs3_test
PRIVATE
tests/test.cpp
tests/test_bit_set.cpp
tests/test_fmt.cpp
tests/test_pair.cpp
tests/test_tuple.cpp
tests/test_simple_array.cpp
tests/test_address_range.cpp
tests/test_sys_fs.cpp
tests/test_bit_set.cpp
tests/test_cctype.cpp
tests/test_dmux_pamf.cpp
tests/test_fmt.cpp
tests/test_iso_open.cpp
tests/test_iso_extent.cpp
tests/test_pair.cpp
tests/test_rsx_cfg.cpp
tests/test_rsx_fp_asm.cpp
tests/test_dmux_pamf.cpp
tests/test_rsx_mm_queue.cpp
tests/test_simple_array.cpp
tests/test_spu_analyser.cpp
tests/test_sys_fs.cpp
tests/test_tuple.cpp
tests/test_types_util.cpp
)
+4 -2
View File
@@ -9,6 +9,8 @@
#include "Emu/system_utils.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
#include <algorithm>
#include <span>
@@ -628,8 +630,8 @@ bool validate_npd_hashes(std::string_view file_name, const u8* klicensee, const
for (usz i = std::distance(it, buf_span.rend()) - 1; i < buf_len; ++i)
{
const u8 c = buf[i];
buf_upper[i] = std::toupper(c);
buf_lower[i] = std::tolower(c);
buf_upper[i] = utils::toupper(c);
buf_lower[i] = utils::tolower(c);
}
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
+7 -6
View File
@@ -18,6 +18,7 @@
#include "Utilities/StrUtil.h"
#include "util/init_mutex.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
#include "Crypto/utils.h"
#include <span>
@@ -228,13 +229,13 @@ static bool check_system_ver(vm::cptr<char> systemVersion)
return (
systemVersion &&
std::strlen(systemVersion.get_ptr()) == 7 &&
std::isdigit(systemVersion[0]) &&
std::isdigit(systemVersion[1]) &&
utils::isdigit(systemVersion[0]) &&
utils::isdigit(systemVersion[1]) &&
systemVersion[2] == '.' &&
std::isdigit(systemVersion[3]) &&
std::isdigit(systemVersion[4]) &&
std::isdigit(systemVersion[5]) &&
std::isdigit(systemVersion[6])
utils::isdigit(systemVersion[3]) &&
utils::isdigit(systemVersion[4]) &&
utils::isdigit(systemVersion[5]) &&
utils::isdigit(systemVersion[6])
);
}
+2 -2
View File
@@ -2,8 +2,8 @@
#include "Emu/IdManager.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Io/KeyboardHandler.h"
#include "util/cctype.hpp"
#include "cellKb.h"
error_code sys_config_start(ppu_thread& ppu);
@@ -198,7 +198,7 @@ u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode)
const auto get_ascii = [&](u16 raw, u16 shifted = 0, u16 altered = 0)
{
// Usually caps lock only applies uppercase to letters, but some layouts treat it as shift lock for all keys.
if ((is_shift || (is_caps_lock && (is_shift_lock || std::isalpha(raw)))) && shifted)
if ((is_shift || (is_caps_lock && (is_shift_lock || utils::isalpha(raw)))) && shifted)
{
return shifted;
}
+41 -37
View File
@@ -6,6 +6,7 @@
#include "Emu/Cell/lv2/sys_time.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/lv2/sys_ss.h"
#include "util/cctype.hpp"
LOG_CHANNEL(cellRtc);
@@ -197,7 +198,7 @@ error_code cellRtcFormatRfc2822(ppu_thread& ppu, vm::ptr<char> pszDateTime, vm::
s32 weekdayIdx = cellRtcGetDayOfWeek(date_time->year, date_time->month, date_time->day);
// Day name
pszDateTime[0] = std::toupper(WEEKDAY_NAMES[weekdayIdx][0]);
pszDateTime[0] = utils::toupper(WEEKDAY_NAMES[weekdayIdx][0]);
pszDateTime[1] = WEEKDAY_NAMES[weekdayIdx][1];
pszDateTime[2] = WEEKDAY_NAMES[weekdayIdx][2];
pszDateTime[3] = ',';
@@ -208,7 +209,7 @@ error_code cellRtcFormatRfc2822(ppu_thread& ppu, vm::ptr<char> pszDateTime, vm::
pszDateTime[7] = ' ';
// month name
pszDateTime[8] = std::toupper(MONTH_NAMES[date_time->month - 1][0]);
pszDateTime[8] = utils::toupper(MONTH_NAMES[date_time->month - 1][0]);
pszDateTime[9] = MONTH_NAMES[date_time->month - 1][1];
pszDateTime[10] = MONTH_NAMES[date_time->month - 1][2];
pszDateTime[0xb] = ' ';
@@ -433,7 +434,7 @@ u16 rtcParseComponent(vm::cptr<char> pszDateTime, u32& pos, char delimiter, cons
pos++;
}
if (!std::isdigit(pszDateTime[pos]))
if (!utils::isdigit(pszDateTime[pos]))
{
cellRtc.error("rtcParseComponent(): failed to parse %s: ASCII value 0x%x at position %d is not a digit", component_name, pszDateTime[pos + 1], pos);
return umax;
@@ -443,7 +444,7 @@ u16 rtcParseComponent(vm::cptr<char> pszDateTime, u32& pos, char delimiter, cons
pos++;
if (std::isdigit(pszDateTime[pos]))
if (utils::isdigit(pszDateTime[pos]))
{
ret = ret * 10 + digit(pszDateTime[pos]);
@@ -462,7 +463,7 @@ u8 rtcParseName(vm::cptr<char> pszDateTime, u32& pos, const std::array<std::stri
u32 ch_idx = 0;
while (ch_idx < name_length && std::tolower(pszDateTime[pos + ch_idx]) == names[name_idx][ch_idx]) // Not case sensitive
while (ch_idx < name_length && utils::tolower(pszDateTime[pos + ch_idx]) == names[name_idx][ch_idx]) // Not case sensitive
{
ch_idx++;
}
@@ -520,15 +521,15 @@ error_code rtcParseRfc2822(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::cptr<
// Year: "XX" or "XXXX"
u16 year = 0;
if (!std::isdigit(pszDateTime[pos]) ||
!std::isdigit(pszDateTime[pos + 1]))
if (!utils::isdigit(pszDateTime[pos]) ||
!utils::isdigit(pszDateTime[pos + 1]))
{
return { CELL_RTC_ERROR_BAD_PARSE, "rtcParseRfc2822(): failed to parse year: one of the first two ASCII values 0x%x, 0x%x at position %d is not a digit",
pszDateTime[pos], pszDateTime[pos + 1], pos };
}
if (!std::isdigit(pszDateTime[pos + 2]) ||
!std::isdigit(pszDateTime[pos + 3]))
if (!utils::isdigit(pszDateTime[pos + 2]) ||
!utils::isdigit(pszDateTime[pos + 3]))
{
year = digit(pszDateTime[pos]) * 10 + digit(pszDateTime[pos + 1]);
year += (year < 50) ? 2000 : 1900;
@@ -591,10 +592,10 @@ error_code rtcParseRfc2822(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::cptr<
{
// "±hhmm"
if (std::isdigit(pszDateTime[pos + 1]) &&
std::isdigit(pszDateTime[pos + 2]) &&
std::isdigit(pszDateTime[pos + 3]) &&
std::isdigit(pszDateTime[pos + 4]))
if (utils::isdigit(pszDateTime[pos + 1]) &&
utils::isdigit(pszDateTime[pos + 2]) &&
utils::isdigit(pszDateTime[pos + 3]) &&
utils::isdigit(pszDateTime[pos + 4]))
{
const s32 time_zone_hhmm = digit(pszDateTime[pos + 1]) * 1000 + digit(pszDateTime[pos + 2]) * 100 + digit(pszDateTime[pos + 3]) * 10 + digit(pszDateTime[pos + 4]);
@@ -627,7 +628,7 @@ error_code rtcParseRfc2822(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::cptr<
// "A", "B", "C", ..., not case sensitive
// These are all off by one ("A" should be UTC+01:00, "B" should be UTC+02:00, etc.)
const char letter = std::toupper(pszDateTime[pos]);
const char letter = utils::toupper(pszDateTime[pos]);
if (letter >= 'A' && letter <= 'M' && letter != 'J')
{
@@ -671,15 +672,15 @@ error_code cellRtcParseDateTime(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::
u32 pos = 0;
while (std::isblank(pszDateTime[pos]))
while (utils::isblank(pszDateTime[pos]))
{
pos++;
}
if (std::isdigit(pszDateTime[pos]) &&
std::isdigit(pszDateTime[pos + 1]) &&
std::isdigit(pszDateTime[pos + 2]) &&
std::isdigit(pszDateTime[pos + 3]))
if (utils::isdigit(pszDateTime[pos]) &&
utils::isdigit(pszDateTime[pos + 1]) &&
utils::isdigit(pszDateTime[pos + 2]) &&
utils::isdigit(pszDateTime[pos + 3]))
{
return cellRtcParseRfc3339(ppu, pUtc, pszDateTime + pos);
}
@@ -697,7 +698,7 @@ error_code cellRtcParseDateTime(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::
}
// Skip spaces and tabs
while (std::isblank(pszDateTime[pos]))
while (utils::isblank(pszDateTime[pos]))
{
pos++;
}
@@ -742,13 +743,13 @@ error_code cellRtcParseDateTime(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::
pos++;
}
else if (std::isdigit(pszDateTime[pos]))
else if (utils::isdigit(pszDateTime[pos]))
{
day = digit(pszDateTime[pos]);
pos++;
if (std::isdigit(pszDateTime[pos]))
if (utils::isdigit(pszDateTime[pos]))
{
day = day * 10 + digit(pszDateTime[pos]);
@@ -793,10 +794,10 @@ error_code cellRtcParseDateTime(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::
pos++;
// Year: XXXX
if (!std::isdigit(pszDateTime[pos]) ||
!std::isdigit(pszDateTime[pos + 1]) ||
!std::isdigit(pszDateTime[pos + 2]) ||
!std::isdigit(pszDateTime[pos + 3]))
if (!utils::isdigit(pszDateTime[pos]) ||
!utils::isdigit(pszDateTime[pos + 1]) ||
!utils::isdigit(pszDateTime[pos + 2]) ||
!utils::isdigit(pszDateTime[pos + 3]))
{
return { CELL_RTC_ERROR_BAD_PARSE, "cellRtcParseDateTime(): failed to parse year: one of the ASCII values 0x%x, 0x%x, 0x%x, or 0x%x is not a digit",
pszDateTime[pos], pszDateTime[pos + 1], pszDateTime[pos + 2], pszDateTime[pos + 3] };
@@ -831,7 +832,10 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
vm::var<CellRtcDateTime> date_time;
// Year: XXXX-12-03T13:23:00.00Z
if (std::isdigit(pszDateTime[0]) && std::isdigit(pszDateTime[1]) && std::isdigit(pszDateTime[2]) && std::isdigit(pszDateTime[3]))
if (utils::isdigit(pszDateTime[0]) &&
utils::isdigit(pszDateTime[1]) &&
utils::isdigit(pszDateTime[2]) &&
utils::isdigit(pszDateTime[3]))
{
date_time->year = digit(pszDateTime[0]) * 1000 + digit(pszDateTime[1]) * 100 + digit(pszDateTime[2]) * 10 + digit(pszDateTime[3]);
}
@@ -846,7 +850,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
}
// Month: 1995-XX-03T13:23:00.00Z
if (std::isdigit(pszDateTime[5]) && std::isdigit(pszDateTime[6]))
if (utils::isdigit(pszDateTime[5]) && utils::isdigit(pszDateTime[6]))
{
date_time->month = digit(pszDateTime[5]) * 10 + digit(pszDateTime[6]);
}
@@ -861,7 +865,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
}
// Day: 1995-12-XXT13:23:00.00Z
if (std::isdigit(pszDateTime[8]) && std::isdigit(pszDateTime[9]))
if (utils::isdigit(pszDateTime[8]) && utils::isdigit(pszDateTime[9]))
{
date_time->day = digit(pszDateTime[8]) * 10 + digit(pszDateTime[9]);
}
@@ -876,7 +880,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
}
// Hour: 1995-12-03TXX:23:00.00Z
if (std::isdigit(pszDateTime[11]) && std::isdigit(pszDateTime[12]))
if (utils::isdigit(pszDateTime[11]) && utils::isdigit(pszDateTime[12]))
{
date_time->hour = digit(pszDateTime[11]) * 10 + digit(pszDateTime[12]);
}
@@ -891,7 +895,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
}
// Minute: 1995-12-03T13:XX:00.00Z
if (std::isdigit(pszDateTime[14]) && std::isdigit(pszDateTime[15]))
if (utils::isdigit(pszDateTime[14]) && utils::isdigit(pszDateTime[15]))
{
date_time->minute = digit(pszDateTime[14]) * 10 + digit(pszDateTime[15]);
}
@@ -906,7 +910,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
}
// Second: 1995-12-03T13:23:XX.00Z
if (std::isdigit(pszDateTime[17]) && std::isdigit(pszDateTime[18]))
if (utils::isdigit(pszDateTime[17]) && utils::isdigit(pszDateTime[18]))
{
date_time->second = digit(pszDateTime[17]) * 10 + digit(pszDateTime[18]);
}
@@ -923,7 +927,7 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
{
u32 mul = 100000;
for (char c = pszDateTime[++pos]; std::isdigit(c); c = pszDateTime[++pos])
for (char c = pszDateTime[++pos]; utils::isdigit(c); c = pszDateTime[++pos])
{
date_time->microsecond += digit(c) * mul;
mul /= 10;
@@ -942,11 +946,11 @@ error_code cellRtcParseRfc3339(ppu_thread& ppu, vm::ptr<CellRtcTick> pUtc, vm::c
// Time offset: 1995-12-03T13:23:00.00+02:30
if (sign == '+' || sign == '-')
{
if (!std::isdigit(pszDateTime[pos + 1]) ||
!std::isdigit(pszDateTime[pos + 2]) ||
if (!utils::isdigit(pszDateTime[pos + 1]) ||
!utils::isdigit(pszDateTime[pos + 2]) ||
pszDateTime[pos + 3] != ':' ||
!std::isdigit(pszDateTime[pos + 4]) ||
!std::isdigit(pszDateTime[pos + 5]))
!utils::isdigit(pszDateTime[pos + 4]) ||
!utils::isdigit(pszDateTime[pos + 5]))
{
return CELL_RTC_ERROR_BAD_PARSE;
}
+2 -1
View File
@@ -10,6 +10,7 @@
#include "Emu/NP/np_handler.h"
#include "Emu/NP/np_contexts.h"
#include "util/cctype.hpp"
LOG_CHANNEL(sceNpCommerce2);
@@ -933,7 +934,7 @@ error_code sceNpCommerce2DoProductCodeStartAsync(u32 ctx_id, u32 container, vm::
for (u32 i = 0; i < SCE_NP_COMMERCE2_PRODUCT_CODE_BLOCK_LEN; i++)
{
if (!isalnum(param->code1[i]) || !isalnum(param->code2[i]) || !isalnum(param->code3[i]))
if (!utils::isalnum(param->code1[i]) || !utils::isalnum(param->code2[i]) || !utils::isalnum(param->code3[i]))
return SCE_NP_COMMERCE2_ERROR_INVALID_TARGET_ID;
}
}
+2 -1
View File
@@ -25,6 +25,7 @@
#include <functional>
#include <shared_mutex>
#include "util/asm.hpp"
#include "util/cctype.hpp"
LOG_CHANNEL(sceNpTrophy);
@@ -254,7 +255,7 @@ void fmt_class_string<SceNpCommunicationId>::format(std::string& out, u64 arg)
const auto& id = get_object(arg);
const u8 term = id.data[9];
fmt::append(out, "{ data='%s', term='%s' (0x%x), num=%d, dummy=%d }", id.data, std::isprint(term) ? fmt::format("%c", term) : "", term, id.num, id.dummy);
fmt::append(out, "{ data='%s', term='%s' (0x%x), num=%d, dummy=%d }", id.data, utils::isprint(term) ? fmt::format("%c", term) : "", term, id.num, id.dummy);
}
// Helpers
+2 -2
View File
@@ -54,7 +54,6 @@
#endif
#include <cfenv>
#include <cctype>
#include <span>
#include <optional>
#include <charconv>
@@ -65,6 +64,7 @@
#include "util/simd.hpp"
#include "util/sysinfo.hpp"
#include "util/fnv_hash.hpp"
#include "util/cctype.hpp"
#include "Utilities/sema.h"
@@ -1481,7 +1481,7 @@ void ppu_thread::dump_regs(std::string& ret, std::any& custom_data) const
// NTS: size of 3 and above is required
// If ends with a newline, only one character is required
else if ((sv.size() == buf_tmp.size() || (sv.size() >= (buf_tmp[sv.size()] == '\n' ? 1 : 3))) &&
std::all_of(sv.begin(), sv.end(), [](u8 c){ return std::isprint(c); }))
std::all_of(sv.begin(), sv.end(), [](u8 c){ return utils::isprint(c); }))
{
fmt::append(ret, " -> \"%s\"", sv);
}
+2 -1
View File
@@ -60,6 +60,7 @@
#include "util/tsc.hpp"
#include "util/sysinfo.hpp"
#include "util/init_mutex.hpp"
#include "util/cctype.hpp"
#if defined(ARCH_X64)
#ifdef _MSC_VER
@@ -1380,7 +1381,7 @@ std::string lv2_obj::name64(u64 name_u64)
// NTS string, ignore invalid/newline characters
// Example: "lv2\n\0tx" will be printed as "lv2"
std::string str{ptr, std::find(ptr, ptr + 7, '\0')};
str.erase(std::remove_if(str.begin(), str.end(), [](uchar c){ return !std::isprint(c); }), str.end());
str.erase(std::remove_if(str.begin(), str.end(), [](uchar c){ return !utils::isprint(c); }), str.end());
return str;
}
+2 -1
View File
@@ -2,6 +2,7 @@
#include "Emu/system_config.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/timers.hpp"
#include "util/cctype.hpp"
#include "sys_tty.h"
@@ -115,7 +116,7 @@ error_code sys_tty_write([[maybe_unused]] ppu_thread& ppu, s32 ch, vm::cptr<char
if (index != umax && index >= 1u)
{
return std::tolower(static_cast<u8>(msg[index - 1])) == word[0];
return utils::tolower(msg[index - 1]) == word[0];
}
return false;
+3 -2
View File
@@ -1,6 +1,7 @@
#include "Emu/Cell/Modules/sceNp.h"
#include "stdafx.h"
#include "util/types.hpp"
#include "util/cctype.hpp"
#include "Utilities/StrUtil.h"
#include "rpcn_client.h"
@@ -42,7 +43,7 @@ namespace np
const auto split_id = fmt::split_sv(str, {"_"});
if (split_id.size() != 2 || split_id[0].length() != 9 || split_id[1].length() != 2 || !std::isdigit(split_id[1][0]) || !std::isdigit(split_id[1][1]))
if (split_id.size() != 2 || split_id[0].length() != 9 || split_id[1].length() != 2 || !utils::isdigit(split_id[1][0]) || !utils::isdigit(split_id[1][1]))
{
rpcn_log.error("Tried to parse an invalid communication_id!");
return std::nullopt;
@@ -110,7 +111,7 @@ namespace np
bool is_valid_npid(const SceNpId& npid)
{
if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == 0; } )
if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return utils::isalnum(c) || c == '-' || c == '_' || c == 0; } )
|| npid.handle.data[16] != 0
|| !std::all_of(npid.handle.dummy, npid.handle.dummy + 3, [](char val) { return val == 0; }) )
{
+2 -1
View File
@@ -2,6 +2,7 @@
#include "capabilities.h"
#include "Utilities/StrUtil.h"
#include "util/cctype.hpp"
#include "Emu/system_config.h"
#include <unordered_set>
@@ -118,7 +119,7 @@ namespace gl
// Workaround for intel drivers which have terrible capability reporting
if (!vendor_string.empty())
{
std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), ::tolower);
std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), utils::tolower<char>);
}
else
{
+3 -2
View File
@@ -3,6 +3,7 @@
#include "state_tracker.hpp"
#include "Emu/system_config.h"
#include "util/cctype.hpp"
namespace gl
{
@@ -15,8 +16,8 @@ namespace gl
size_t string_begin = std::string::npos, i = start;
for (size_t count = 0; i < source.length(); ++i)
{
const auto& c = source[i];
const auto is_space = std::isspace(c);
const char c = source[i];
const auto is_space = utils::isspace(c);
if (string_begin == std::string::npos)
{
+3 -2
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "FPASM.h"
#include "Emu/RSX/Program/RSXFragmentProgram.h"
#include "util/cctype.hpp"
#include <stack>
@@ -198,7 +199,7 @@ namespace rsx::assembler
result.reserve(s.size());
bool literal = false;
for (const auto& c : s)
for (const char c : s)
{
if (c == ' ')
{
@@ -209,7 +210,7 @@ namespace rsx::assembler
continue;
}
if (std::isspace(c))
if (utils::isspace(c))
{
continue;
}
+2 -1
View File
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "VKCommonDecompiler.h"
#include "util/cctype.hpp"
namespace vk
{
@@ -50,7 +51,7 @@ namespace vk
for (int char_idx = name_length - max_index_length; char_idx < name_length; ++char_idx)
{
if (std::isdigit(name[char_idx]))
if (utils::isdigit(name[char_idx]))
{
index += name[char_idx];
}
+3 -2
View File
@@ -47,6 +47,7 @@
#include "util/logs.hpp"
#include "util/init_mutex.hpp"
#include "util/sysinfo.hpp"
#include "util/cctype.hpp"
#include <memory>
#include <shared_mutex>
@@ -4050,7 +4051,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
tty_buffer.resize(tty_read_fd.read_at(m_tty_file_init_pos, tty_buffer.data(), tty_buffer.size()));
tty_read_fd.close();
if (!tty_buffer.empty() && std::isspace(tty_buffer.back()))
if (!tty_buffer.empty() && utils::isspace(tty_buffer.back()))
{
tty_buffer.resize(tty_buffer.find_last_not_of(" \f\n\r\t\v"sv) + 1);
}
@@ -4143,7 +4144,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
iter = index + 1;
}
if (!new_log.empty() && std::isspace(new_log.back()))
if (!new_log.empty() && utils::isspace(new_log.back()))
{
new_log.resize(new_log.find_last_not_of(" \f\n\r\t\v"sv) + 1);
}
+2 -1
View File
@@ -7,6 +7,7 @@
#include "Utilities/mutex.h"
#include "Utilities/StrUtil.h"
#include "util/cctype.hpp"
#ifdef _WIN32
#include <Windows.h>
@@ -567,7 +568,7 @@ std::string vfs::escape(std::string_view name, bool escape_slash)
if (name.size() > 2)
{
// Pack first 3 characters
const u32 triple = std::bit_cast<le_t<u32>, u32>(toupper(name[0]) | toupper(name[1]) << 8 | toupper(name[2]) << 16);
const u32 triple = std::bit_cast<le_t<u32>, u32>(utils::toupper(name[0]) | utils::toupper(name[1]) << 8 | utils::toupper(name[2]) << 16);
switch (triple)
{
+1
View File
@@ -803,6 +803,7 @@
<ClInclude Include="util\atomic.hpp" />
<ClInclude Include="util\bit_set.hpp" />
<ClInclude Include="util\bless.hpp" />
<ClInclude Include="util\cctype.hpp" />
<ClInclude Include="util\pair.hpp" />
<ClInclude Include="util\tuple.hpp" />
<ClInclude Include="util\video_sink.h" />
+3
View File
@@ -3013,6 +3013,9 @@
<ClInclude Include="Emu\Cell\lv2\sys_bluetooth.h">
<Filter>Emu\Cell\lv2</Filter>
</ClInclude>
<ClInclude Include="util\cctype.hpp">
<Filter>Utilities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
+3 -2
View File
@@ -22,6 +22,7 @@
#include "util/asm.hpp"
#include "util/logs.hpp"
#include "util/to_endian.hpp"
#include "util/cctype.hpp"
#include "Utilities/File.h"
#include "Utilities/StrUtil.h"
#include "Utilities/bin_patch.h" // get_patches_path()
@@ -221,12 +222,12 @@ bool cheat_engine::resolve_script(u32& final_offset, const u32 offset, std::stri
while (index < red_script.size())
{
if (std::isdigit(static_cast<u8>(red_script[index])))
if (utils::isdigit(red_script[index]))
{
std::string num_string;
for (; index < red_script.size(); index++)
{
if (!std::isdigit(static_cast<u8>(red_script[index])))
if (!utils::isdigit(red_script[index]))
break;
num_string += red_script[index];
+3 -2
View File
@@ -13,6 +13,7 @@
#include "Emu/Io/Keyboard.h"
#include "util/yaml.hpp"
#include "util/cctype.hpp"
#include "Utilities/File.h"
#include "Utilities/Config.h"
@@ -444,7 +445,7 @@ void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, emu_settings_type type)
}
std::string def = GetSettingDefault(type);
std::transform(def.begin(), def.end(), def.begin(), ::tolower);
std::transform(def.begin(), def.end(), def.begin(), utils::tolower<char>);
if (def != "true" && def != "false")
{
@@ -453,7 +454,7 @@ void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, emu_settings_type type)
}
std::string selected = GetSetting(type);
std::transform(selected.begin(), selected.end(), selected.begin(), ::tolower);
std::transform(selected.begin(), selected.end(), selected.begin(), utils::tolower<char>);
if (selected == "true")
{
+2 -1
View File
@@ -1,5 +1,6 @@
#include "input_dialog.h"
#include "qt_utils.h"
#include "util/cctype.hpp"
#include <QVBoxLayout>
#include <QDialogButtonBox>
@@ -46,7 +47,7 @@ void input_dialog::set_clear_button_enabled(bool enabled) const
void input_dialog::set_input_font(const QFont& font, bool fix_width, char sample) const
{
if (const int max = m_input->maxLength(); max > 0 && fix_width && std::isprint(static_cast<uchar>(sample)))
if (const int max = m_input->maxLength(); max > 0 && fix_width && utils::isprint(sample))
{
const QString str = QString(max, sample);
m_input->setFixedWidth(gui::utils::get_label_width(str, &font));
+5 -4
View File
@@ -16,6 +16,7 @@
#include "util/logs.hpp"
#include "util/sysinfo.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
LOG_CHANNEL(gui_log, "GUI");
@@ -71,7 +72,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
bool case_insensitive = false;
// First characters for case insensitive search
const char first_chars[2]{ static_cast<char>(::tolower(wstr[0])), static_cast<char>(::toupper(wstr[0])) };
const char first_chars[2]{ static_cast<char>(utils::tolower(wstr[0])), static_cast<char>(utils::toupper(wstr[0])) };
std::string_view insensitive_search{first_chars, 2};
if (insensitive_search[0] == insensitive_search[1])
@@ -92,7 +93,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
if (case_insensitive)
{
std::transform(wstr.begin(), wstr.end(), wstr.begin(), ::tolower);
std::transform(wstr.begin(), wstr.end(), wstr.begin(), utils::tolower<char>);
}
break;
@@ -257,7 +258,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
if (case_insensitive)
{
std::transform(last.begin(), last.end(), last.begin(), ::tolower);
std::transform(last.begin(), last.end(), last.begin(), utils::tolower<char>);
}
std::smatch sm;
@@ -399,7 +400,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
std::string_view test_sv{get_ptr(start), addr_max - start};
// Do not use allocating functions such as fmt::to_lower
if (test_sv.size() >= wstr.size() && std::all_of(wstr.begin(), wstr.end(), [&](const char& c) { return c == ::tolower(test_sv[&c - wstr.data()]); }))
if (test_sv.size() >= wstr.size() && std::all_of(wstr.begin(), wstr.end(), [&](const char& c) { return c == utils::tolower(test_sv[&c - wstr.data()]); }))
{
// Force full logging if any character differs in case
log_occurance(test_sv, !test_sv.starts_with(wstr));
+2 -1
View File
@@ -27,6 +27,7 @@
#include "util/logs.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
#include "debugger_frame.h"
LOG_CHANNEL(gui_log, "GUI");
@@ -876,7 +877,7 @@ void memory_viewer_panel::ShowMemory()
for (auto& ch : str)
{
if (!std::isprint(static_cast<u8>(ch))) ch = '.';
if (!utils::isprint(ch)) ch = '.';
}
t_mem_ascii_str += QString::fromStdString(std::move(str));
+3 -2
View File
@@ -17,6 +17,7 @@
#include "util/v128.hpp"
#include "util/asm.hpp"
#include "util/cctype.hpp"
enum registers : int
{
@@ -300,7 +301,7 @@ void register_editor_dialog::OnOkay()
}
}
value.erase(std::remove_if(value.begin(), value.end(), [](uchar c){ return std::isspace(c); }), value.end());
value.erase(std::remove_if(value.begin(), value.end(), utils::isspace<char>), value.end());
pad(32);
@@ -365,7 +366,7 @@ void register_editor_dialog::OnOkay()
}
}
value.erase(std::remove_if(value.begin(), value.end(), [](uchar c){ return std::isspace(c); }), value.end());
value.erase(std::remove_if(value.begin(), value.end(), utils::isspace<char>), value.end());
pad(32);
+4 -3
View File
@@ -15,6 +15,7 @@
#include "Emu/System.h"
#include "Emu/NP/rpcn_config.h"
#include "Emu/NP/ip_address.h"
#include "util/cctype.hpp"
#ifdef __clang__
#pragma clang diagnostic push
@@ -36,9 +37,9 @@ bool validate_rpcn_username(std::string_view username)
return false;
return std::all_of(username.cbegin(), username.cend(), [](const char c)
{
return std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_';
});
{
return utils::isalnum(c) || c == '-' || c == '_';
});
}
bool validate_email(std::string_view email)
+1
View File
@@ -93,6 +93,7 @@
<ItemGroup>
<ClCompile Include="test.cpp" />
<ClCompile Include="test_bit_set.cpp" />
<ClCompile Include="test_cctype.cpp" />
<ClCompile Include="test_dmux_pamf.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
+314
View File
@@ -0,0 +1,314 @@
#include <gtest/gtest.h>
#include "util/cctype.hpp"
namespace utils
{
TEST(CctypeTest, Test_check_arg)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_TRUE(utils::check_cctype_arg<char>(static_cast<char>(i)));
EXPECT_TRUE(utils::check_cctype_arg<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
EXPECT_EQ(i < 256, utils::check_cctype_arg<u16>(static_cast<u16>(i)));
}
}
TEST(CctypeTest, Test_isalnum)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isalnum(static_cast<unsigned char>(i)) != 0, utils::isalnum<char>(static_cast<char>(i)));
EXPECT_EQ(::isalnum(static_cast<unsigned char>(i)) != 0, utils::isalnum<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isalnum(static_cast<unsigned char>(i)) != 0, utils::isalnum<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isalnum<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isalpha)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isalpha(static_cast<unsigned char>(i)) != 0, utils::isalpha<char>(static_cast<char>(i)));
EXPECT_EQ(::isalpha(static_cast<unsigned char>(i)) != 0, utils::isalpha<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isalpha(static_cast<unsigned char>(i)) != 0, utils::isalpha<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isalpha<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_iscntrl)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::iscntrl(static_cast<unsigned char>(i)) != 0, utils::iscntrl<char>(static_cast<char>(i)));
EXPECT_EQ(::iscntrl(static_cast<unsigned char>(i)) != 0, utils::iscntrl<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::iscntrl(static_cast<unsigned char>(i)) != 0, utils::iscntrl<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::iscntrl<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isdigit)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isdigit(static_cast<unsigned char>(i)) != 0, utils::isdigit<char>(static_cast<char>(i)));
EXPECT_EQ(::isdigit(static_cast<unsigned char>(i)) != 0, utils::isdigit<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isdigit(static_cast<unsigned char>(i)) != 0, utils::isdigit<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isdigit<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isgraph)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isgraph(static_cast<unsigned char>(i)) != 0, utils::isgraph<char>(static_cast<char>(i)));
EXPECT_EQ(::isgraph(static_cast<unsigned char>(i)) != 0, utils::isgraph<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isgraph(static_cast<unsigned char>(i)) != 0, utils::isgraph<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isgraph<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_islower)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::islower(static_cast<unsigned char>(i)) != 0, utils::islower<char>(static_cast<char>(i)));
EXPECT_EQ(::islower(static_cast<unsigned char>(i)) != 0, utils::islower<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::islower(static_cast<unsigned char>(i)) != 0, utils::islower<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::islower<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isupper)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isupper(static_cast<unsigned char>(i)) != 0, utils::isupper<char>(static_cast<char>(i)));
EXPECT_EQ(::isupper(static_cast<unsigned char>(i)) != 0, utils::isupper<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isupper(static_cast<unsigned char>(i)) != 0, utils::isupper<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isupper<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isprint)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isprint(static_cast<unsigned char>(i)) != 0, utils::isprint<char>(static_cast<char>(i)));
EXPECT_EQ(::isprint(static_cast<unsigned char>(i)) != 0, utils::isprint<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isprint(static_cast<unsigned char>(i)) != 0, utils::isprint<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isprint<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_ispunct)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::ispunct(static_cast<unsigned char>(i)) != 0, utils::ispunct<char>(static_cast<char>(i)));
EXPECT_EQ(::ispunct(static_cast<unsigned char>(i)) != 0, utils::ispunct<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::ispunct(static_cast<unsigned char>(i)) != 0, utils::ispunct<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::ispunct<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isspace)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isspace(static_cast<unsigned char>(i)) != 0, utils::isspace<char>(static_cast<char>(i)));
EXPECT_EQ(::isspace(static_cast<unsigned char>(i)) != 0, utils::isspace<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isspace(static_cast<unsigned char>(i)) != 0, utils::isspace<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isspace<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isblank)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isblank(static_cast<unsigned char>(i)) != 0, utils::isblank<char>(static_cast<char>(i)));
EXPECT_EQ(::isblank(static_cast<unsigned char>(i)) != 0, utils::isblank<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isblank(static_cast<unsigned char>(i)) != 0, utils::isblank<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isblank<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_isxdigit)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::isxdigit(static_cast<unsigned char>(i)) != 0, utils::isxdigit<char>(static_cast<char>(i)));
EXPECT_EQ(::isxdigit(static_cast<unsigned char>(i)) != 0, utils::isxdigit<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::isxdigit(static_cast<unsigned char>(i)) != 0, utils::isxdigit<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_FALSE(utils::isxdigit<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_tolower)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::tolower(static_cast<unsigned char>(i)), utils::tolower<char>(static_cast<char>(i)));
EXPECT_EQ(::tolower(static_cast<unsigned char>(i)), utils::tolower<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::tolower(static_cast<unsigned char>(i)), utils::tolower<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_EQ(EOF, utils::tolower<u16>(static_cast<u16>(i)));
}
}
}
TEST(CctypeTest, Test_toupper)
{
for (int i = std::numeric_limits<char>::min(); i <= std::numeric_limits<char>::max(); i++)
{
EXPECT_EQ(::toupper(static_cast<unsigned char>(i)), utils::toupper<char>(static_cast<char>(i)));
EXPECT_EQ(::toupper(static_cast<unsigned char>(i)), utils::toupper<s8>(static_cast<s8>(i)));
}
for (u32 i = 0; i <= std::numeric_limits<u16>::max(); i++)
{
if (i < 256)
{
EXPECT_EQ(::toupper(static_cast<unsigned char>(i)), utils::toupper<u16>(static_cast<u16>(i)));
}
else
{
EXPECT_EQ(EOF, utils::toupper<u16>(static_cast<u16>(i)));
}
}
}
}
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include "types.hpp"
#include <cctype>
#include <concepts>
namespace utils
{
template <typename T>
concept cctype_char = std::integral<T> && (std::is_same_v<T, char> || std::is_same_v<T, s8> || std::is_unsigned_v<T>);
template <cctype_char T>
constexpr bool check_cctype_arg(T c)
{
if constexpr (std::is_same_v<T, char>)
{
return true;
}
else
{
return c <= std::numeric_limits<unsigned char>::max();
}
}
template <cctype_char T> constexpr bool isalnum(T c) { return check_cctype_arg(c) && ::isalnum(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isalpha(T c) { return check_cctype_arg(c) && ::isalpha(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool iscntrl(T c) { return check_cctype_arg(c) && ::iscntrl(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isdigit(T c) { return check_cctype_arg(c) && ::isdigit(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isgraph(T c) { return check_cctype_arg(c) && ::isgraph(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool islower(T c) { return check_cctype_arg(c) && ::islower(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isupper(T c) { return check_cctype_arg(c) && ::isupper(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isprint(T c) { return check_cctype_arg(c) && ::isprint(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool ispunct(T c) { return check_cctype_arg(c) && ::ispunct(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isspace(T c) { return check_cctype_arg(c) && ::isspace(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isblank(T c) { return check_cctype_arg(c) && ::isblank(static_cast<unsigned char>(c)); }
template <cctype_char T> constexpr bool isxdigit(T c) { return check_cctype_arg(c) && ::isxdigit(static_cast<unsigned char>(c)); }
template <cctype_char T>
constexpr int tolower(T c)
{
if (!check_cctype_arg(c)) return EOF;
return ::tolower(static_cast<unsigned char>(c));
}
template <cctype_char T>
constexpr int toupper(T c)
{
if (!check_cctype_arg(c)) return EOF;
return ::toupper(static_cast<unsigned char>(c));
}
}