From 2d220fc821af918ec8464dec1def088d297f2b86 Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Mon, 8 Feb 2021 17:59:21 +0100 Subject: [PATCH 1/3] Fix B006 --- inkcpp/output.cpp | 2 +- inkcpp/runner_impl.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/inkcpp/output.cpp b/inkcpp/output.cpp index bdfce373..4dd02de1 100644 --- a/inkcpp/output.cpp +++ b/inkcpp/output.cpp @@ -158,7 +158,7 @@ namespace ink const char* iter = str; while (*iter != '\0') { - if (is_whitespace(*iter)) + if (is_whitespace(*iter, false)) // newlines are required (B006) { // pass over whitespace bool start = iter == str; diff --git a/inkcpp/runner_impl.cpp b/inkcpp/runner_impl.cpp index 2536f981..5969eef1 100644 --- a/inkcpp/runner_impl.cpp +++ b/inkcpp/runner_impl.cpp @@ -545,8 +545,7 @@ namespace ink::runtime::internal int val = read(); if (bEvaluationMode) _eval.push(val); - else - _output << val; + // TEST-CASE B006 don't print integers } break; case Command::FLOAT: @@ -554,8 +553,7 @@ namespace ink::runtime::internal float val = read(); if (bEvaluationMode) _eval.push(val); - else - _output << val; + // TEST-CASE B006 don't print floats } break; From 89dac4725ae6d7663ec1bd2d74004c7d124d9f1e Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Mon, 8 Feb 2021 21:01:38 +0100 Subject: [PATCH 2/3] Adapt for B007 --- inkcpp/value.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++-- inkcpp/value.h | 3 +- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/inkcpp/value.cpp b/inkcpp/value.cpp index 3cf9004e..5dd88487 100644 --- a/inkcpp/value.cpp +++ b/inkcpp/value.cpp @@ -303,6 +303,82 @@ namespace ink inkFail("Invalid type for mod"); } + void convert(const char*& c, const data& d, char* number) { + switch(d.type) { + case data_type::int32: + snprintf(number, 32, "%d", d.integer_value); + break; + case data_type::uint32: + snprintf(number, 32, "%d", d.uint_value); + break; + case data_type::float32: + snprintf(number, 32, "%f", d.float_value); + break; + case data_type::newline: + number[0] = '\n'; + number[1] = 0; + break; + case data_type::string_table_pointer: + case data_type::allocated_string_pointer: + c = d.string_val; + break; + default: number[0] = 0; + } + } + bool value::compare_string(const value& left, const value& right) { + size_t l_i = 0; + size_t r_i = 0; + char l_number[32]; l_number[0] = 0; + char r_number[32]; r_number[0] = 0; + const char* l_c = l_number; + const char* r_c = r_number; + bool res = true; + while(res && l_i < VALUE_DATA_LENGTH && r_i < VALUE_DATA_LENGTH) { + if (*l_c || *r_c) { + if (*l_c) { + r_c = r_number; + convert(r_c, right._data[r_i], r_number); + } else { + l_c = l_number; + convert(l_c, left._data[l_i], l_number); + } + } else if (left._data[l_i].type == right._data[r_i].type) { + switch(left._data[l_i].type) { + case data_type::int32: + 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; + break; + case data_type::float32: + res = left._data[l_i].float_value == right._data[r_i].float_value; + break; + case data_type::string_table_pointer: + l_c = left._data[l_i].string_val; + r_c = right._data[r_i].string_val; + case data_type::allocated_string_pointer: + break; + default: break; + } + } else { + r_c = r_number; + convert(r_c, right._data[r_i], r_number); + l_c = l_number; + convert(l_c, left._data[l_i], l_number); + } + while(*l_c && *r_c) { + if (*l_c != *r_c) { + res = false; break; + } + ++l_c; ++r_c; + } + if (!*l_c){ ++l_i; } + if (!*r_c){ ++r_i; } + } + if (l_i != r_i) { return false; } + return res; + } + value value::is_equal(value left, value right) { // Cast as needed @@ -315,7 +391,7 @@ namespace ink case value_type::decimal: return left.as_float() == right.as_float(); case value_type::string: - break; // TODO: data[] operators? + return compare_string(left, right); case value_type::divert: return left.as_divert() == right.as_divert(); } @@ -367,4 +443,4 @@ namespace ink } } } -} \ No newline at end of file +} diff --git a/inkcpp/value.h b/inkcpp/value.h index 0bf82824..b8fef0cf 100644 --- a/inkcpp/value.h +++ b/inkcpp/value.h @@ -141,6 +141,7 @@ namespace ink private: static void cast(value&, value_type, value_type); static value_type maybe_cast(value& left, value& right); + static bool compare_string(const value& left, const value& right); private: // Maximum sequential data a value can have @@ -200,4 +201,4 @@ namespace ink #endif } } -} \ No newline at end of file +} From d36711d32a3fca8e1f4891bb402f1ce178b23d50 Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Tue, 9 Feb 2021 10:53:11 +0100 Subject: [PATCH 3/3] Add comments + minor fixes --- inkcpp/value.cpp | 46 +++++++++++++++++++++++++++++++++------------- inkcpp/value.h | 3 +++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/inkcpp/value.cpp b/inkcpp/value.cpp index 5dd88487..1105efa6 100644 --- a/inkcpp/value.cpp +++ b/inkcpp/value.cpp @@ -303,7 +303,8 @@ namespace ink inkFail("Invalid type for mod"); } - void convert(const char*& c, const data& d, char* number) { + void convert_to_string(const char*& c, const data& d, char* number) { + c = number; switch(d.type) { case data_type::int32: snprintf(number, 32, "%d", d.integer_value); @@ -325,24 +326,38 @@ namespace ink default: number[0] = 0; } } + + bool value::compare_string(const value& left, const value& right) { + // convert fields to string representation and start comparison + // when the end of one field is reached, the other still has + // bytes left -> convert the next field and continue comparison + + // iterator for data fields of left and right value size_t l_i = 0; size_t r_i = 0; + // buffer to store string representation of numeric fields char l_number[32]; l_number[0] = 0; char r_number[32]; r_number[0] = 0; + // current compare position, if *l = 0 -> field compare finish const char* l_c = l_number; const char* r_c = r_number; bool res = true; + // while no different found and fields to check remain while(res && l_i < VALUE_DATA_LENGTH && r_i < VALUE_DATA_LENGTH) { - if (*l_c || *r_c) { + // if one field has left overs + if (*l_c || *r_c) + { + // fetch the next field of the value without leftover if (*l_c) { - r_c = r_number; - convert(r_c, right._data[r_i], r_number); + convert_to_string(r_c, right._data[r_i], r_number); } else { - l_c = l_number; - convert(l_c, left._data[l_i], l_number); + convert_to_string(l_c, left._data[l_i], l_number); } - } else if (left._data[l_i].type == right._data[r_i].type) { + } + // if both values are aligned: check if both have the same type + else if (left._data[l_i].type == right._data[r_i].type) + { switch(left._data[l_i].type) { case data_type::int32: res = left._data[l_i].integer_value == right._data[r_i].integer_value; @@ -354,27 +369,32 @@ namespace ink 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: l_c = left._data[l_i].string_val; r_c = right._data[r_i].string_val; - case data_type::allocated_string_pointer: break; default: break; } - } else { - r_c = r_number; - convert(r_c, right._data[r_i], r_number); - l_c = l_number; - convert(l_c, left._data[l_i], l_number); } + // convert both to string and compare + else + { + convert_to_string(r_c, right._data[r_i], r_number); + convert_to_string(l_c, left._data[l_i], l_number); + } + // compare string representation until one reaches the end while(*l_c && *r_c) { + // if different found: stop and set result to false if (*l_c != *r_c) { res = false; break; } ++l_c; ++r_c; } + // if field is finished advance to the next if (!*l_c){ ++l_i; } if (!*r_c){ ++r_i; } } + // if one value not complete compared -> leftover witch not match if (l_i != r_i) { return false; } return res; } diff --git a/inkcpp/value.h b/inkcpp/value.h index b8fef0cf..b6f087d8 100644 --- a/inkcpp/value.h +++ b/inkcpp/value.h @@ -141,6 +141,9 @@ namespace ink private: static void cast(value&, value_type, value_type); static value_type maybe_cast(value& left, value& right); + /** + * @brief compare if the string representation of values are equal. + */ static bool compare_string(const value& left, const value& right); private: