diff --git a/src/operators/ops_dummy_binary.cpp b/src/operators/ops_dummy_binary.cpp index f3bf9c0c..7d10b69e 100644 --- a/src/operators/ops_dummy_binary.cpp +++ b/src/operators/ops_dummy_binary.cpp @@ -27,7 +27,6 @@ void sqf::operators::ops_dummy_binary(sqf::runtime::runtime& runtime) runtime.register_sqfop(binary(4, "enablereload", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "enablereload")); return {}; })); runtime.register_sqfop(binary(4, "setpilotlight", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setpilotlight")); return {}; })); runtime.register_sqfop(binary(4, "setvisibleiftreecollapsed", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setvisibleiftreecollapsed")); return {}; })); - runtime.register_sqfop(binary(4, "isequaltypeall", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "isequaltypeall")); return {}; })); runtime.register_sqfop(binary(4, "camconstuctionsetparams", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "camconstuctionsetparams")); return {}; })); runtime.register_sqfop(binary(4, "commandsuppressivefire", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "commandsuppressivefire")); return {}; })); runtime.register_sqfop(binary(4, "tvtext", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "tvtext")); return {}; })); @@ -487,7 +486,6 @@ void sqf::operators::ops_dummy_binary(sqf::runtime::runtime& runtime) runtime.register_sqfop(binary(4, "setsize", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setsize")); return {}; })); runtime.register_sqfop(binary(4, "setunitpos", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setunitpos")); return {}; })); runtime.register_sqfop(binary(4, "animatedoor", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "animatedoor")); return {}; })); - runtime.register_sqfop(binary(4, "isequaltypeparams", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "isequaltypeparams")); return {}; })); runtime.register_sqfop(binary(4, "ctfindheaderrows", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "ctfindheaderrows")); return {}; })); runtime.register_sqfop(binary(4, "gethit", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "gethit")); return {}; })); runtime.register_sqfop(binary(4, "drawarrow", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "drawarrow")); return {}; })); @@ -594,7 +592,6 @@ void sqf::operators::ops_dummy_binary(sqf::runtime::runtime& runtime) runtime.register_sqfop(binary(4, "menuvalue", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "menuvalue")); return {}; })); runtime.register_sqfop(binary(4, "settaskresult", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "settaskresult")); return {}; })); runtime.register_sqfop(binary(4, "setlightuseflare", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setlightuseflare")); return {}; })); - runtime.register_sqfop(binary(4, "isequaltypeany", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "isequaltypeany")); return {}; })); runtime.register_sqfop(binary(4, "drawtriangle", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "drawtriangle")); return {}; })); runtime.register_sqfop(binary(4, "lbsetselectcolor", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "lbsetselectcolor")); return {}; })); runtime.register_sqfop(binary(4, "mapcenteroncamera", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "mapcenteroncamera")); return {}; })); @@ -889,7 +886,6 @@ void sqf::operators::ops_dummy_binary(sqf::runtime::runtime& runtime) runtime.register_sqfop(binary(4, "moveingunner", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "moveingunner")); return {}; })); runtime.register_sqfop(binary(4, "campreparepos", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "campreparepos")); return {}; })); runtime.register_sqfop(binary(4, "disablecollisionwith", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "disablecollisionwith")); return {}; })); - runtime.register_sqfop(binary(4, "isequaltypearray", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "isequaltypearray")); return {}; })); runtime.register_sqfop(binary(4, "setvehiclelock", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "setvehiclelock")); return {}; })); runtime.register_sqfop(binary(4, "addprimaryweaponitem", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "addprimaryweaponitem")); return {}; })); runtime.register_sqfop(binary(4, "lbsetcursel", t_any(), t_any(), "", [](sqf::runtime::runtime& runtime, value::cref l, value::cref r) -> value { runtime.__logmsg(logmessage::runtime::ErrorMessage(runtime.context_active().current_frame().diag_info_from_position(), "NOT IMPLEMENTED", "lbsetcursel")); return {}; })); diff --git a/src/operators/ops_logic.cpp b/src/operators/ops_logic.cpp index 3a010be6..e2aca492 100644 --- a/src/operators/ops_logic.cpp +++ b/src/operators/ops_logic.cpp @@ -6,6 +6,7 @@ #include "../runtime/d_scalar.h" #include "../runtime/d_boolean.h" #include "../runtime/d_code.h" +#include "../runtime/d_array.h" #include "../runtime/value.h" @@ -100,6 +101,79 @@ namespace { return left.type() == right.type(); } + value isequaltypeall_array_any(runtime& runtime, value::cref left, value::cref right) + { + auto type = right.type(); + auto arr = left.data(); + + if (arr->size() == 0) + { + return false; + } + + for (const auto &item : arr->value()) { + if (item.type() != type) { + return false; + } + } + + return true; + } + value isequaltypeany_any_array(runtime& runtime, value::cref left, value::cref right) + { + auto type = left.type(); + auto arr = right.data(); + + for (const auto &item : arr->value()) { + if (item.type() == type) { + return true; + } + } + + return false; + } + value isequaltypearray_array_array(runtime& runtime, value::cref left, value::cref right) + { + auto l = left.data(); + auto r = right.data(); + + return std::equal(l->value().begin(), l->value().end(), r->value().begin(), r->value().end(), + [](value left, value right) { return left.type() == right.type(); }); + } + value isequaltypeparams_any_array(runtime& runtime, value::cref left, value::cref right) + { + if (!left.is(t_array())) { + return false; + } + + auto l = left.data(); + auto r = right.data(); + + // Early exit if input does not cover all templates + if (l->size() < r->size()) + { + return false; + } + + // Only input which is defined in templates needs to be validated + for (int i = 0; i < r->size(); i++) + { + auto left = l->at(i); + auto right = r->at(i); + + // Template which is nil accepts all types + if (right.empty()) { + continue; + } + + if (left.type() != right.type()) + { + return false; + } + } + + return true; + } value true_(runtime& runtime) { @@ -162,4 +236,8 @@ void sqf::operators::ops_logic(sqf::runtime::runtime& runtime) runtime.register_sqfop(binary(3, "!=", t_location(), t_location(), "Returns whether one value is not equal to another.", notequals_any_any)); runtime.register_sqfop(binary(4, "isEqualTo", t_any(), t_any(), "Check if one value is equal to another. Both values need to be of the same type.", isequalto_any_any)); runtime.register_sqfop(binary(4, "isEqualType", t_any(), t_any(), "Compares 2 values by their type. A much faster alternative to typeName a == typeName b.", isequaltype_any_any)); + runtime.register_sqfop(binary(4, "isEqualTypeAll", t_array(), t_any(), "Compares types of all elements of an array to the type of a single value.", isequaltypeall_array_any)); + runtime.register_sqfop(binary(4, "isEqualTypeAny", t_any(), t_array(), "Compares type of given value to every type in the given array and if match is found, true is returned.", isequaltypeany_any_array)); + runtime.register_sqfop(binary(4, "isEqualTypeArray", t_array(), t_array(), "Compares types of all elements of one array to types of all elements of another array.", isequaltypearray_array_array)); + runtime.register_sqfop(binary(4, "isEqualTypeParams", t_any(), t_array(), "Compares types of all elements of input array to types of all elements of template array.", isequaltypeparams_any_array)); } diff --git a/tests/sqf/isEqualType.sqf b/tests/sqf/isEqualType.sqf new file mode 100644 index 00000000..577e06bd --- /dev/null +++ b/tests/sqf/isEqualType.sqf @@ -0,0 +1,77 @@ +[ ["assertTrue", { true isEqualType true }], + ["assertTrue", { true isEqualType false }], + ["assertTrue", { false isEqualType true }], + ["assertTrue", { false isEqualType false }], + ["assertTrue", { 1 isEqualType 2 }], + ["assertTrue", { 2 isEqualType 1 }], + ["assertTrue", { 1 isEqualType 1 }], + ["assertTrue", { [] isEqualType [] }], + ["assertTrue", { [1] isEqualType [1] }], + ["assertTrue", { [true] isEqualType [true] }], + ["assertTrue", { [true] isEqualType [false] }], + ["assertTrue", { [false] isEqualType [true] }], + ["assertTrue", { [false] isEqualType [false] }], + ["assertTrue", { [[1,2,3],[1,2,3]] isEqualType [[1,2,3],[1,2,3]] }], + ["assertTrue", { [[1,2,3]] isEqualType [[1,2,3],[1,2,3]] }], + ["assertTrue", { [nil] isEqualType [nil] }], + ["assertTrue", { private _arr = [nil]; _arr isEqualType _arr }], + ["assertTrue", { [player] isEqualType [player] }], + ["assertTrue", { ["test"] isEqualType ["test"] }], + ["assertTrue", { ["test"] isEqualType ["TEST"] }], + + ["assertFalse", { [] isEqualTypeAll "" }], + ["assertFalse", { [] isEqualTypeAll 1 }], + ["assertFalse", { [] isEqualTypeAll player }], + ["assertFalse", { [] isEqualTypeAll true }], + ["assertTrue", { ["1"] isEqualTypeAll "2" }], + ["assertFalse", { ["1", 2] isEqualTypeAll "3" }], + ["assertTrue", { [1] isEqualTypeAll 2 }], + ["assertFalse", { [1, "2"] isEqualTypeAll 3 }], + ["assertTrue", { [player] isEqualTypeAll player }], + ["assertFalse", { [player, "player"] isEqualTypeAll player }], + ["assertTrue", { [true] isEqualTypeAll false }], + ["assertFalse", { [true, "true"] isEqualTypeAll false }], + + ["assertFalse", { "" isEqualTypeAny [] }], + ["assertFalse", { 1 isEqualTypeAny [] }], + ["assertFalse", { player isEqualTypeAny [] }], + ["assertFalse", { true isEqualTypeAny [] }], + ["assertTrue", { "1" isEqualTypeAny ["2"] }], + ["assertTrue", { "1" isEqualTypeAny ["2", 3] }], + ["assertTrue", { 1 isEqualTypeAny [2] }], + ["assertTrue", { 1 isEqualTypeAny [2, "3"] }], + ["assertTrue", { player isEqualTypeAny [player] }], + ["assertTrue", { player isEqualTypeAny [player, "player"] }], + ["assertTrue", { true isEqualTypeAny [false] }], + ["assertTrue", { true isEqualTypeAny [false, "true"] }], + + ["assertTrue", { [] isEqualTypeArray [] }], + ["assertTrue", { ["1"] isEqualTypeArray ["2"] }], + ["assertFalse", { ["1"] isEqualTypeArray [] }], + ["assertFalse", { ["1"] isEqualTypeArray ["2", "3"] }], + ["assertTrue", { [1] isEqualTypeArray [2] }], + ["assertFalse", { [1] isEqualTypeArray [] }], + ["assertFalse", { [1] isEqualTypeArray [2, 3] }], + ["assertTrue", { [player] isEqualTypeArray [player] }], + ["assertFalse", { [player] isEqualTypeArray [] }], + ["assertTrue", { [true] isEqualTypeArray [false] }], + ["assertFalse", { [true] isEqualTypeArray [] }], + ["assertFalse", { [true] isEqualTypeArray [false, true] }], + + ["assertTrue", { [] isEqualTypeParams [] }], + ["assertFalse", { [] isEqualTypeParams [nil] }], + ["assertTrue", { [nil] isEqualTypeParams [] }], + ["assertTrue", { [nil] isEqualTypeParams [nil] }], + ["assertFalse", { 1 isEqualTypeParams [2] }], + ["assertTrue", { [1] isEqualTypeParams [2] }], + ["assertTrue", { [1, 2] isEqualTypeParams [3] }], + ["assertTrue", { [1, 2] isEqualTypeParams [3, 4] }], + ["assertFalse", { [1, 2] isEqualTypeParams [3, "4"] }], + // From Biki + ["assertTrue", { [1, 2, player, "10"] isEqualTypeParams [0, 0, objNull, ""] }], + ["assertFalse", { 123 isEqualTypeParams [0, 0, objNull, ""] }], + ["assertFalse", { [] isEqualTypeParams [0, 0, objNull, ""] }], + ["assertFalse", { [1, 2,player] isEqualTypeParams [0, 0, objNull, ""] }], + ["assertTrue", { [1, 2, player, "10", true] isEqualTypeParams [0, 0, nil, ""] }], + ["assertTrue", { [1, 2, getPos player, "10", true] isEqualTypeParams [0, 0, nil, ""] }] +]