Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 44 additions & 84 deletions coresdk/src/coresdk/basics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

#include <algorithm>
#include <cstdlib>
#include <string_view>
#include <format>
#include <ranges>

#include <functional>
#include <cctype>
Expand Down Expand Up @@ -78,7 +81,10 @@ namespace splashkit_lib
{
size_t pos = text.find(subtext);
if (pos == string::npos)
{
return -1;
}

return static_cast<int>(pos);
}

Expand All @@ -99,21 +105,26 @@ namespace splashkit_lib

vector<string> split(const string &text, char delimiter)
{
vector<string> result;
string::size_type start = 0;
string::size_type end = text.find(delimiter);
while (end != string::npos)
// To check to keep the same functionality required on line 523 of unit_test_utilities.cpp
// Will return an empty vector without this check
if (text.empty())
{
return vector<string>{ text };
}

vector<string> result{};
for(const auto& strings : std::views::split(text, delimiter))
{
result.push_back(text.substr(start, end - start));
start = end + 1;
end = text.find(delimiter, start);
result.emplace_back(strings.begin(), strings.end());
}
result.push_back(text.substr(start));

return result;
// To future maintainers: if the codebase gets upgraded to C++23 or newer,
// remove the above code and uncomment the code bellow
// return text | std::views::split(delimiter) | std::ranges::to<std::vector<std::string>>();
}

// integer check see: https://stackoverflow.com/questions/2844817/how-do-i-check-if-a-c-string-is-an-int#2845275

bool is_integer(const string &text)
{
string s = trim(text);
Expand Down Expand Up @@ -153,49 +164,44 @@ namespace splashkit_lib
return std::stod(text);
}

bool is_valid_input(std::string_view input, std::string_view valid_characters)
{
return input.find_first_not_of(valid_characters) == std::string_view::npos;
}

bool is_binary(const string &bin_str)
{
for (char c : bin_str)
if (bin_str.empty())
{
if (c != '0' && c != '1')
return false;
return false;
}
return !bin_str.empty();

return is_valid_input(bin_str, "01");
}

bool is_hex(const string &hex_str)
{
for (char c : hex_str)
if (hex_str.empty())
{
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')))
return false;
return false;
}
return !hex_str.empty();

return is_valid_input(hex_str, "0123456789aAbBcCdDeEfF");
}

bool is_octal(const string &octal_str)
{
for (char c : octal_str)
if (octal_str.empty())
{
if (c < '0' || c > '7')
return false;
return false;
}
return !octal_str.empty();

return is_valid_input(octal_str, "01234567");
}

string dec_to_bin(unsigned int a_dec)
{
// Without this check, dec to bin will not work if dec is 0
if (a_dec == 0)
return "0";

string bin_string;
while (a_dec > 0)
{
bin_string = ((a_dec & 1) ? "1" : "0") + bin_string;
a_dec >>= 1;
}
return bin_string;
return std::format("{:b}", a_dec);
}

unsigned int bin_to_dec(const string &bin_str)
Expand Down Expand Up @@ -278,18 +284,7 @@ namespace splashkit_lib

string dec_to_oct(unsigned int decimal_value)
{
if (decimal_value == 0)
{
return "0";
}

string octal_string;
while (decimal_value > 0)
{
octal_string = std::to_string(decimal_value % 8) + octal_string;
decimal_value /= 8;
}
return octal_string;
return std::format("{:o}", decimal_value);
}

unsigned int oct_to_dec(const string &octal_string)
Expand Down Expand Up @@ -322,20 +317,7 @@ namespace splashkit_lib
return "";
}

string bin_string;
for (char oct_char : octal_str)
{
int oct_val = oct_char - '0';

// Convert each octal digit to a 3-bit binary representation
for (int i = 2; i >= 0; i--)
{
bin_string += ((oct_val >> i) & 1) ? '1' : '0';
}
}

size_t first_one = bin_string.find_first_not_of('0');
return (first_one == string::npos) ? "0" : bin_string.substr(first_one);
return dec_to_bin(oct_to_dec(octal_str));
}

string bin_to_oct(const string &bin_str)
Expand All @@ -346,27 +328,7 @@ namespace splashkit_lib
return "";
}

string octal_string;

// Pad binary string with leading zeros to make its length a multiple of 3
int padding = (3 - (bin_str.length() % 3)) % 3;
string padded_bin_str = string(padding, '0') + bin_str;

for (size_t i = 0; i < padded_bin_str.length(); i += 3)
{
int oct_val = 0;
for (size_t j = 0; j < 3; j++)
{
oct_val <<= 1;
if (padded_bin_str[i + j] == '1')
oct_val |= 1;
}

octal_string += '0' + oct_val;
}

size_t first_non_zero = octal_string.find_first_not_of('0');
return (first_non_zero == string::npos) ? "0" : octal_string.substr(first_non_zero);
return dec_to_oct(bin_to_dec(bin_str));
}

string hex_to_oct(const string &hex_str)
Expand All @@ -377,8 +339,7 @@ namespace splashkit_lib
return "";
}

string bin_str = hex_to_bin(hex_str);
return bin_to_oct(bin_str);
return bin_to_oct(hex_to_bin(hex_str));
}

string oct_to_hex(const string &octal_str)
Expand All @@ -389,8 +350,7 @@ namespace splashkit_lib
return "";
}

string bin_str = oct_to_bin(octal_str);
return bin_to_hex(bin_str);
return bin_to_hex(oct_to_bin(octal_str));
}

string base64_encode(const string &input)
Expand Down Expand Up @@ -496,4 +456,4 @@ namespace splashkit_lib
return abs(number1 * number2) / greatest_common_divisor(number1, number2);
}

}
}
20 changes: 17 additions & 3 deletions coresdk/src/test/unit_tests/unit_test_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ TEST_CASE("verify that string is double", "[is_double]")
}
TEST_CASE("verify that string is integer", "[is_integer]")
{
SECTION("Edge Cases")
{
REQUIRE_FALSE(is_integer("1+2"));
REQUIRE_FALSE(is_integer("+-2"));
REQUIRE_FALSE(is_integer("--5"));
REQUIRE_FALSE(is_integer("5--"));
REQUIRE_FALSE(is_integer("5-"));
}
SECTION("string is an integer")
{
REQUIRE(is_integer("123"));
Expand Down Expand Up @@ -393,6 +401,12 @@ TEST_CASE("verify that string is integer", "[is_integer]")
}
TEST_CASE("verify that string is number", "[is_number]")
{
SECTION("Edge Cases")
{
REQUIRE_FALSE(is_number("1.2.3"));
REQUIRE_FALSE(is_number("1.+2"));
REQUIRE_FALSE(is_number("1.-2"));
}
SECTION("string is a double")
{
REQUIRE(is_number("123.456"));
Expand Down Expand Up @@ -717,7 +731,7 @@ TEST_CASE("gets the number of milliseconds that have passed since the program wa
TEST_CASE("program is put to sleep for a specified number of milliseconds", "[delay]")
{
constexpr long long DELAY_THRESHOLD = 80;

SECTION("milliseconds is 0")
{
auto start = std::chrono::steady_clock::now();
Expand Down Expand Up @@ -747,7 +761,7 @@ TEST_CASE("return a SplashKit resource of resource_kind with name filename as a
{
const resource_kind RESOURCE = resource_kind::BUNDLE_RESOURCE;
const string RESOURCE_PATH = "blah.txt";

SECTION("filename is a valid file")
{
string result = file_as_string(RESOURCE_PATH, RESOURCE);
Expand Down Expand Up @@ -1017,4 +1031,4 @@ TEST_CASE("calculates the lcm of two numbers", "[least_common_multiple]")
{
REQUIRE(least_common_multiple(42, 42) == 42);
}
}
}