diff --git a/inkcpp/value.cpp b/inkcpp/value.cpp index 1105efa6..3b189d45 100644 --- a/inkcpp/value.cpp +++ b/inkcpp/value.cpp @@ -358,15 +358,16 @@ namespace ink // if both values are aligned: check if both have the same type else if (left._data[l_i].type == right._data[r_i].type) { + bool tmp_res = true; switch(left._data[l_i].type) { case data_type::int32: - res = left._data[l_i].integer_value == right._data[r_i].integer_value; + tmp_res = left._data[l_i].integer_value == right._data[r_i].integer_value; break; case data_type::uint32: - res = left._data[l_i].uint_value == right._data[r_i].uint_value; + tmp_res = left._data[l_i].uint_value == right._data[r_i].uint_value; break; case data_type::float32: - res = left._data[l_i].float_value == right._data[r_i].float_value; + tmp_res = left._data[l_i].float_value == right._data[r_i].float_value; break; case data_type::string_table_pointer: case data_type::allocated_string_pointer: @@ -375,6 +376,11 @@ namespace ink break; default: break; } + // check if maybe the missing part is in next data + if (!tmp_res) { + convert_to_string(r_c, right._data[r_i], r_number); + convert_to_string(l_c, left._data[l_i], l_number); + } } // convert both to string and compare else @@ -395,7 +401,22 @@ namespace ink if (!*r_c){ ++r_i; } } // if one value not complete compared -> leftover witch not match - if (l_i != r_i) { return false; } + if (res && l_i != r_i) { + const value& v = l_i < r_i ? left : right; + int i = l_i < r_i ? l_i : r_i; + // check if leftover fields all empty + while(v._data[i].type != data_type::none) { + if (v._data[i].type != data_type::string_table_pointer + && v._data[i].type != data_type::allocated_string_pointer) { + if (*v._data[i].string_val != 0) { + return false; + } + } else { + return false; + } + ++i; + } + } return res; } diff --git a/inkcpp_test/CMakeLists.txt b/inkcpp_test/CMakeLists.txt index 7e666ab4..0faa9301 100644 --- a/inkcpp_test/CMakeLists.txt +++ b/inkcpp_test/CMakeLists.txt @@ -4,8 +4,9 @@ add_executable(inkcpp_test catch.hpp Main.cpp Stack.cpp Callstack.cpp Restorable.cpp + Value.cpp ) target_link_libraries(inkcpp_test PUBLIC inkcpp) -add_test(NAME UnitTests COMMAND $) \ No newline at end of file +add_test(NAME UnitTests COMMAND $) diff --git a/inkcpp_test/Value.cpp b/inkcpp_test/Value.cpp new file mode 100644 index 00000000..e1afb2fd --- /dev/null +++ b/inkcpp_test/Value.cpp @@ -0,0 +1,100 @@ +#include "catch.hpp" + +#include "../inkcpp/value.h" +#include "../inkcpp/string_table.h" +#include "../inkcpp/output.h" + +using value = ink::runtime::internal::value; +using data_type = ink::runtime::internal::data_type; +using string_table = ink::runtime::internal::string_table; +using stream = ink::runtime::internal::stream<128>; + +void cp_str(char* dst, const char* src) { + while(*src) { *dst++ = *src++; } + *dst = 0; +} + +SCENARIO("compare concatenated values") +{ + GIVEN("just single strings") + { + const char str_1[] = "Hello World!"; + const char str_1_again[] = "Hello World!"; + const char str_2[] = "Bye World!"; + WHEN("equal") + { + value v1(str_1); + value v2(str_1_again); + value res = v1 == v2; + THEN("== results in true") + { + REQUIRE(res.get_data_type() == data_type::int32); + REQUIRE(res.get() == 1); + } + } + WHEN("not equal") + { + value v1(str_1); + value v2(str_2); + value res = v1 == v2; + THEN("== results in false") + { + REQUIRE(res.get_data_type() == data_type::int32); + REQUIRE(res.get() == 0); + } + } + } + GIVEN("string and numbers") + { + string_table str_table; + stream out{}; + char* str_hello = str_table.create(6); + cp_str(str_hello, "hello"); + char* str_5hello = str_table.create(7); + cp_str(str_5hello, "5hello"); + char* str_4 = str_table.create(2); + cp_str(str_4, "4"); + char* str_32_4 = str_table.create(33); + for (int i = 0; i < 32; ++i) { str_32_4[i] = '4'; } + str_32_4[32] = 0; + + int int_4 = 4; + int int_45 = 45; + WHEN("concatenated string representation matches (2 fields)") + { + value v1 = value::add(value(int_4), value(str_5hello), out, str_table); + value v2 = value::add(value(int_45), value(str_hello), out, str_table); + value res = v1 == v2; + THEN("== returns true") + { + REQUIRE(res.get_data_type() == data_type::int32); + REQUIRE(res.get() == 1); + } + } + WHEN("concatenated string representation match (many fields)") + { + value v1 = value(str_4); + for (int i = 0; i < 31; ++i) { + v1 = value::add(v1, value(int_4), out, str_table); + } + value v2 = value(str_32_4); + value res = v1 == v2; + THEN("== results true") + { + REQUIRE(res.get_data_type() == data_type::int32); + REQUIRE(res.get() == 1); + } + } + WHEN("concatenated string representation won't match") + { + value v1 = value::add(value(int_45), value(str_5hello), out, str_table); + value v2 = value::add(value(int_4),value(str_hello), out, str_table); + value res = v1 == v2; + THEN("== returns false") + { + REQUIRE(res.get_data_type() == data_type::int32); + REQUIRE(res.get() == 0); + } + } + } +}