Add including_indirect_array_recursion argument to reflect.equal

This commit is contained in:
gingerBill
2021-09-03 12:00:43 +01:00
parent b0f1b1ca16
commit 11ae87cc2f

View File

@@ -1279,10 +1279,12 @@ as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) {
eq :: equal;
ne :: not_equal;
not_equal :: proc(a, b: any) -> bool {
return !equal(a, b);
DEFAULT_EQUAL_MAX_RECURSION_LEVEL :: 32;
not_equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool {
return !equal(a, b, including_indirect_array_recursion, recursion_level);
}
equal :: proc(a, b: any) -> bool {
equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool {
if a == nil && b == nil {
return true;
}
@@ -1307,6 +1309,11 @@ equal :: proc(a, b: any) -> bool {
if .Simple_Compare in t.flags {
return mem.compare_byte_ptrs((^byte)(a.data), (^byte)(b.data), t.size) == 0;
}
including_indirect_array_recursion := including_indirect_array_recursion;
if recursion_level >= DEFAULT_EQUAL_MAX_RECURSION_LEVEL {
including_indirect_array_recursion = false;
}
t = runtime.type_info_core(t);
@@ -1321,23 +1328,25 @@ equal :: proc(a, b: any) -> bool {
y := (^string)(b.data)^;
return x == y;
}
return true;
case Type_Info_Array:
for i in 0..<v.count {
x := rawptr(uintptr(a.data) + uintptr(v.elem_size*i));
y := rawptr(uintptr(b.data) + uintptr(v.elem_size*i));
if !equal(any{x, v.elem.id}, any{y, v.elem.id}) {
if !equal(any{x, v.elem.id}, any{y, v.elem.id}, including_indirect_array_recursion, recursion_level) {
return false;
}
}
return true;
case Type_Info_Enumerated_Array:
for i in 0..<v.count {
x := rawptr(uintptr(a.data) + uintptr(v.elem_size*i));
y := rawptr(uintptr(b.data) + uintptr(v.elem_size*i));
if !equal(any{x, v.elem.id}, any{y, v.elem.id}) {
if !equal(any{x, v.elem.id}, any{y, v.elem.id}, including_indirect_array_recursion, recursion_level) {
return false;
}
}
return true;
case Type_Info_Struct:
if v.equal != nil {
return v.equal(a.data, b.data);
@@ -1346,11 +1355,57 @@ equal :: proc(a, b: any) -> bool {
x := rawptr(uintptr(a.data) + offset);
y := rawptr(uintptr(b.data) + offset);
id := v.types[i].id;
if !equal(any{x, id}, any{y, id}) {
if !equal(any{x, id}, any{y, id}, including_indirect_array_recursion, recursion_level) {
return false;
}
}
return true;
}
case Type_Info_Union:
if v.equal != nil {
return v.equal(a.data, b.data);
}
return false;
case Type_Info_Slice:
if !including_indirect_array_recursion {
break;
}
array_a := (^mem.Raw_Slice)(a.data);
array_b := (^mem.Raw_Slice)(b.data);
if array_a.len != array_b.len {
return false;
}
if array_a.data == array_b.data {
return true;
}
for i in 0..<array_a.len {
x := rawptr(uintptr(array_a.data) + uintptr(v.elem_size*i));
y := rawptr(uintptr(array_b.data) + uintptr(v.elem_size*i));
if !equal(any{x, v.elem.id}, any{y, v.elem.id}, including_indirect_array_recursion, recursion_level+1) {
return false;
}
}
return true;
case Type_Info_Dynamic_Array:
if !including_indirect_array_recursion {
break;
}
array_a := (^mem.Raw_Dynamic_Array)(a.data);
array_b := (^mem.Raw_Dynamic_Array)(b.data);
if array_a.len != array_b.len {
return false;
}
if array_a.data == array_b.data {
return true;
}
for i in 0..<array_a.len {
x := rawptr(uintptr(array_a.data) + uintptr(v.elem_size*i));
y := rawptr(uintptr(array_b.data) + uintptr(v.elem_size*i));
if !equal(any{x, v.elem.id}, any{y, v.elem.id}, including_indirect_array_recursion, recursion_level+1) {
return false;
}
}
return true;
}
return true;