Browse Source

Add `including_indirect_array_recursion` argument to `reflect.equal`

gingerBill 4 years ago
parent
commit
11ae87cc2f
1 changed files with 62 additions and 7 deletions
  1. 62 7
      core/reflect/reflect.odin

+ 62 - 7
core/reflect/reflect.odin

@@ -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;