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
48 changes: 43 additions & 5 deletions coresdk/src/coresdk/basics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "basics.h"
#include "easylogging++.h"

#include <concepts>
#include <algorithm>
#include <cstdlib>

Expand Down Expand Up @@ -143,6 +144,43 @@ namespace splashkit_lib
return (*p == 0);
}

template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;

template<Numeric output, Numeric input = unsigned long>
output clamp_in_range(input number)
{
if (number > std::numeric_limits<output>::max())
{
return std::numeric_limits<output>::max();
}
else
{
return static_cast<output>(number);
}
}

template<Numeric output>
output convert_string(const string &input, int base = 10)
{
try
{
if constexpr (std::floating_point<output>)
{
return clamp_in_range<output, double>(std::stod(input));
}
else
{
return clamp_in_range<output>(std::stoul(input, nullptr, base));
}
}
catch (const std::exception& error)
{
LOG(ERROR) << "Invalid string \"" << input << "\" passed to conversion function. Returning 0.";
return 0;
}
}

int convert_to_integer(const string &text)
{
return std::stoi(text);
Expand Down Expand Up @@ -206,7 +244,7 @@ namespace splashkit_lib
return 0;
}

return stoi(bin_str, nullptr, 2);
return convert_string<unsigned int>(bin_str, 2);
}

string hex_to_bin(const string &hex_str)
Expand Down Expand Up @@ -300,18 +338,18 @@ namespace splashkit_lib
return 0;
}

return stoi(octal_string, nullptr, 8);
return convert_string<unsigned int>(octal_string, 8);
}

unsigned int hex_to_dec(const string &hex_string)
{
if (!is_hex(hex_string))
{
LOG(ERROR) << "Invalid octal string \"" << hex_string << "\" passed to hex_to_dec. Returning 0.";
LOG(ERROR) << "Invalid hex string \"" << hex_string << "\" passed to hex_to_dec. Returning 0.";
return 0;
}

return stoi(hex_string, nullptr, 16);
return convert_string<unsigned int>(hex_string, 16);
}

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

}
}
23 changes: 15 additions & 8 deletions coresdk/src/coresdk/basics.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ using std::vector;

namespace splashkit_lib
{

/**
* Return a new string that removes the spaces from the start and end of
* the input string.
Expand Down Expand Up @@ -101,7 +101,7 @@ namespace splashkit_lib

/**
* Returns true if the string contains the substring.
*
*
* @param text The text to search
* @param subtext The substring to search for
* @returns True if the substring is found in the text.
Expand All @@ -110,7 +110,7 @@ namespace splashkit_lib

/**
* Returns the index of the first occurrence of the substring in the text.
*
*
* @param text The text to search
* @param subtext The substring to search for
* @returns The index of the first occurrence of the substring in the text, or -1 if the substring is not found.
Expand All @@ -119,7 +119,7 @@ namespace splashkit_lib

/**
* Replace all occurrences of a substring in a string with another string.
*
*
* @param text The text to search
* @param substr The substring to find and replace
* @param new_text The string to replace the substring with
Expand All @@ -129,7 +129,7 @@ namespace splashkit_lib

/**
* Split a string into an array of strings based on a delimiter.
*
*
* @param text The text to split
* @param delimiter The character to split the text on
* @returns An array of strings
Expand Down Expand Up @@ -169,7 +169,7 @@ namespace splashkit_lib
* @returns True if the string is a valid octal string, false otherwise
*/
bool is_octal(const string &octal_str);

/**
* @brief Converts a decimal (unsigned integer) to a binary string
*
Expand All @@ -187,6 +187,8 @@ namespace splashkit_lib
*
* Converts the provided binary string into an unsigned integer.
* For example, "1010" will be converted to 10.
* Any input that exceedes the max value of unsigned integer will silently truncate and not be treated as an error.
* Any out of range error that occurs will result in the value being returned being 0.
*
* @param bin Binary string to convert
*
Expand Down Expand Up @@ -235,6 +237,8 @@ namespace splashkit_lib
*
* Converts the provided octal string into its decimal representation.
* For example, "100" will be converted to 64.
* Any input that exceedes the max value of unsigned integer will silently truncate and not be treated as an error.
* Any out of range error that occurs will result in the value being returned being 0.
*
* @param octal_string Octal string to convert
*
Expand Down Expand Up @@ -280,9 +284,12 @@ namespace splashkit_lib

/**
* @brief Convert a hexadecimal string to its numeric value.
*
* For example, "A" will be converted to 10.
* Any input that exceedes the max value of unsigned integer will silently truncate and not be treated as an error.
* Any out of range error that occurs will result in the value being returned being 0.
*
* @param hex_string the data to convert
*
*
* @return unsigned int the numeric value of the hex string
*/
unsigned int hex_to_dec(const string &hex_string);
Expand Down
62 changes: 62 additions & 0 deletions coresdk/src/test/test_terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Copyright © 2016 Andrew Cain. All rights reserved.
*/

#include <limits>
#include "terminal.h"
#include "utils.h"
#include <iostream>
Expand Down Expand Up @@ -124,6 +125,9 @@ void bin_to_dec()
// High values (32-bit boundaries)
assert(bin_to_dec("10000000000000000000000000000000") == 2147483648);

// Test for over unsigned int max
assert(bin_to_dec("1111111111111111111111111111111111111111111111111111111111111111") == std::numeric_limits<unsigned int>::max());

// Mixed bits
assert(bin_to_dec("1111011") == 123);
assert(bin_to_dec("10000000001") == 1025);
Expand All @@ -143,6 +147,7 @@ void bin_to_dec()
assert(bin_to_dec("abcde") != 2147483647);
assert(bin_to_dec("a1b2b3i4f02") != 1234);


string bin_input1 = "1111011";
int result1 = bin_to_dec(bin_input1);
write_line("1111011 in decimal is " + to_string(result1));
Expand Down Expand Up @@ -203,6 +208,59 @@ void hex_to_bin()
write_line("-------------------------------------");
}

void hex_to_dec_tests()
{
write_line("Testing hexadecimal to decimal conversion");

// Basic cases
assert(hex_to_dec("0") == 0);
assert(hex_to_dec("1") == 1);
assert(hex_to_dec("A") == 10);
assert(hex_to_dec("F") == 15);
assert(hex_to_dec("10") == 16);
assert(hex_to_dec("FF") == 255);
assert(hex_to_dec("100") == 256);
assert(hex_to_dec("ABC") == 2748);
assert(hex_to_dec("1234") == 4660);

// Larger hexadecimal values
assert(hex_to_dec("FFFF") == 65535);
assert(hex_to_dec("FFFFFFFF") == 4294967295);
assert(hex_to_dec("1FFFFFF") == 33554431);
assert(hex_to_dec("ABCDEF") == 11259375);

// Tests for inequality
assert(hex_to_dec("0") != 1);
assert(hex_to_dec("1") != 0);
assert(hex_to_dec("A") != 11);
assert(hex_to_dec("F") != 16);
assert(hex_to_dec("10") != 10);
assert(hex_to_dec("FF") != 256);
assert(hex_to_dec("100") != 255);
assert(hex_to_dec("ABC") != 2749);
assert(hex_to_dec("1234") != 4670);
assert(hex_to_dec("FFFF") != 100);
assert(hex_to_dec("FFFFFFFF") != 200);
assert(hex_to_dec("1FFFFFF") != 300);
assert(hex_to_dec("GGGGGG") != 400);

// Test over unsigned int
assert(hex_to_dec("100000000") == 4294967295);
// Test over unsigned long
assert(hex_to_dec("10000000000000000") == 0);

const string hex_input1 = "ABCDEF";
const unsigned int result1 = hex_to_dec(hex_input1);
write_line("ABCDEF in decimal is " + to_string(result1));

const string hex_input2 = "1234";
const unsigned int result2 = hex_to_dec(hex_input2);
write_line("1234 in decimal is " + to_string(result2));

write_line("All hexadecimal to decimal tests passed!");
write_line("-------------------------------------");
}

void bin_to_hex()
{
write_line("Testing binary to hexadecimal conversion");
Expand Down Expand Up @@ -341,6 +399,9 @@ void test_oct_to_dec()
assert(oct_to_dec("abcde") != 2147483647);
assert(oct_to_dec("a1b2b3i4f02") != 1234);

// Test over unsigned int max
assert(oct_to_dec("1777777777777777777777") == std::numeric_limits<unsigned int>::max());

string oct_input1 = "173";
int result1 = oct_to_dec(oct_input1);
write_line("173 in decimal is " + to_string(result1));
Expand Down Expand Up @@ -885,6 +946,7 @@ void run_terminal_test()
dec_to_bin();
bin_to_dec();
hex_to_bin();
hex_to_dec_tests();
bin_to_hex();
test_dec_to_oct();
test_oct_to_dec();
Expand Down