Browse Source

Correct #soa printing

gingerBill 3 years ago
parent
commit
5b200ccdf8
1 changed files with 103 additions and 64 deletions
  1. 103 64
      core/fmt/fmt.odin

+ 103 - 64
core/fmt/fmt.odin

@@ -1265,6 +1265,22 @@ fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: in
 
 @(private)
 handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb: ^rune, optional_len: ^int = nil) -> (do_continue: bool) {
+	handle_optional_len :: proc(data: rawptr, info: reflect.Type_Info_Struct, field_name: string, optional_len: ^int) {
+		if optional_len == nil {
+			return
+		}
+		for f, i in info.names {
+			if f != field_name {
+				continue
+			}
+			ptr := rawptr(uintptr(data) + info.offsets[i])
+			field := any{ptr, info.types[i].id}
+			if new_len, iok := reflect.as_int(field); iok {
+				optional_len^ = max(new_len, 0)
+			}
+			break
+		}
+	}
 	tag := info.tags[idx]
 	if vt, ok := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "fmt"); ok {
 		value := strings.trim_space(string(vt))
@@ -1277,21 +1293,14 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb:
 		if value == "" || value[0] == ',' {
 			verb^ = r
 			if len(value) > 0 && value[0] == ',' {
+				field_name := value[1:]
 				switch r {
 				case 's', 'q':
-					if optional_len != nil {
-						field_name := value[1:]
-						for f, i in info.names {
-							if f != field_name {
-								continue
-							}
-							ptr := rawptr(uintptr(data) + info.offsets[i])
-							field := any{ptr, info.types[i].id}
-							if new_len, iok := reflect.as_int(field); iok {
-								optional_len^ = max(new_len, 0)
-							}
-							break
-						}
+					handle_optional_len(data, info, field_name, optional_len)
+				case 'v':
+					#partial switch reflect.type_kind(info.types[idx].id) {
+					case .String, .Multi_Pointer, .Array, .Slice, .Dynamic_Array:
+						handle_optional_len(data, info, field_name, optional_len)
 					}
 				}
 			}
@@ -1300,12 +1309,12 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb:
 	return false
 }
 
-fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, b: runtime.Type_Info_Struct, type_name: string) {
+fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) {
 	if the_verb != 'v' {
 		fmt_bad_verb(fi, the_verb)
 		return
 	}
-	if b.is_raw_union {
+	if info.is_raw_union {
 		if type_name == "" {
 			io.write_string(fi.writer, "(raw union)", &fi.n)
 		} else {
@@ -1315,7 +1324,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, b: runtime.Type_Info_Struc
 		return
 	}
 
-	is_soa := b.soa_kind != .None
+	is_soa := info.soa_kind != .None
 
 	io.write_string(fi.writer, type_name, &fi.n)
 	io.write_byte(fi.writer, '[' if is_soa else '{', &fi.n)
@@ -1342,26 +1351,43 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, b: runtime.Type_Info_Struc
 		defer fi.indent -= 1
 
 		base_type_name: string
-		if v, ok := b.soa_base_type.variant.(runtime.Type_Info_Named); ok {
+		if v, ok := info.soa_base_type.variant.(runtime.Type_Info_Named); ok {
 			base_type_name = v.name
 		}
 
-		for index in 0..<uintptr(b.soa_len) {
-			if !do_trailing_comma && index > 0 { io.write_string(fi.writer, ", ", &fi.n) }
+		actual_field_count := len(info.names)
+
+		n := uintptr(info.soa_len)
+
+		if info.soa_kind == .Slice {
+			actual_field_count = len(info.names)-1 // len
+
+			n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^)
+
+		} else if info.soa_kind == .Dynamic {
+			actual_field_count = len(info.names)-3 // len, cap, allocator
+
+			n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^)
+		}
+
+
+		for index in 0..<n {
+			if !hash && index > 0 { io.write_string(fi.writer, ", ", &fi.n) }
 
 			field_count := -1
 
-			if !do_trailing_comma && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) }
+			if !hash && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) }
 
 			io.write_string(fi.writer, base_type_name, &fi.n)
 			io.write_byte(fi.writer, '{', &fi.n)
 			defer io.write_byte(fi.writer, '}', &fi.n)
 
-			for name, i in b.names {
+			for i in 0..<actual_field_count {
 				verb := 'v'
+				name := info.names[i]
 				field_count += 1
 
-				if !do_trailing_comma && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) }
+				if !hash && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) }
 				if hash {
 					fmt_write_indent(fi)
 				}
@@ -1369,24 +1395,36 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, b: runtime.Type_Info_Struc
 				io.write_string(fi.writer, name, &fi.n)
 				io.write_string(fi.writer, " = ", &fi.n)
 
-				t := b.types[i].variant.(runtime.Type_Info_Array).elem
-				t_size := uintptr(t.size)
-				if reflect.is_any(t) {
-					io.write_string(fi.writer, "any{}", &fi.n)
+				if info.soa_kind == .Fixed {
+					t := info.types[i].variant.(runtime.Type_Info_Array).elem
+					t_size := uintptr(t.size)
+					if reflect.is_any(t) {
+						io.write_string(fi.writer, "any{}", &fi.n)
+					} else {
+						data := rawptr(uintptr(v.data) + info.offsets[i] + index*t_size)
+						fmt_arg(fi, any{data, t.id}, verb)
+					}
 				} else {
-					data := rawptr(uintptr(v.data) + b.offsets[i] + index*t_size)
-					fmt_arg(fi, any{data, t.id}, verb)
+					t := info.types[i].variant.(runtime.Type_Info_Pointer).elem
+					t_size := uintptr(t.size)
+					if reflect.is_any(t) {
+						io.write_string(fi.writer, "any{}", &fi.n)
+					} else {
+						field_ptr := (^^byte)(uintptr(v.data) + info.offsets[i])^
+						data := rawptr(uintptr(field_ptr) + index*t_size)
+						fmt_arg(fi, any{data, t.id}, verb)
+					}
 				}
 
-				if do_trailing_comma { io.write_string(fi.writer, ",\n", &fi.n) }
+				if hash { io.write_string(fi.writer, ",\n", &fi.n) }
 			}
 		}
 	} else {
 		field_count := -1
-		for name, i in b.names {
+		for name, i in info.names {
 			optional_len: int = -1
 			verb := 'v'
-			if handle_tag(v.data, b, i, &verb, &optional_len) {
+			if handle_tag(v.data, info, i, &verb, &optional_len) {
 				continue
 			}
 			field_count += 1
@@ -1406,10 +1444,10 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, b: runtime.Type_Info_Struc
 			io.write_string(fi.writer, name, &fi.n)
 			io.write_string(fi.writer, " = ", &fi.n)
 
-			if t := b.types[i]; reflect.is_any(t) {
+			if t := info.types[i]; reflect.is_any(t) {
 				io.write_string(fi.writer, "any{}", &fi.n)
 			} else {
-				data := rawptr(uintptr(v.data) + b.offsets[i])
+				data := rawptr(uintptr(v.data) + info.offsets[i])
 				fmt_arg(fi, any{data, t.id}, verb)
 			}
 
@@ -1687,18 +1725,6 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		}
 		fmt_pointer(fi, ptr, verb)
 
-	case runtime.Type_Info_Array:
-		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
-			n := info.count
-			if ol, ok := fi.optional_len.?; ok {
-				n = min(n, ol)
-			}
-			s := strings.string_from_ptr((^byte)(v.data), n)
-			fmt_string(fi, s, verb)
-		} else {
-			fmt_write_array(fi, v.data, info.count, info.elem_size, info.elem.id, verb)
-		}
-
 	case runtime.Type_Info_Enumerated_Array:
 		if fi.hash {
 			io.write_string(fi.writer, "[\n", &fi.n)
@@ -1748,19 +1774,46 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 			}
 		}
 
+	case runtime.Type_Info_Array:
+		n := info.count
+		if ol, ok := fi.optional_len.?; ok {
+			n = min(n, ol)
+		}
+		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
+			s := strings.string_from_ptr((^byte)(v.data), n)
+			fmt_string(fi, s, verb)
+		} else {
+			fmt_write_array(fi, v.data, n, info.elem_size, info.elem.id, verb)
+		}
+
+	case runtime.Type_Info_Slice:
+		slice := cast(^mem.Raw_Slice)v.data
+		n := slice.len
+		if ol, ok := fi.optional_len.?; ok {
+			n = min(n, ol)
+		}
+		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
+			s := strings.string_from_ptr((^byte)(slice.data), n)
+			fmt_string(fi, s, verb)
+		} else if verb == 'p' {
+			fmt_pointer(fi, slice.data, 'p')
+		} else {
+			fmt_write_array(fi, slice.data, n, info.elem_size, info.elem.id, verb)
+		}
+
 	case runtime.Type_Info_Dynamic_Array:
 		array := cast(^mem.Raw_Dynamic_Array)v.data
+		n := array.len
+		if ol, ok := fi.optional_len.?; ok {
+			n = min(n, ol)
+		}
 		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
-			n := array.len
-			if ol, ok := fi.optional_len.?; ok {
-				n = min(n, ol)
-			}
 			s := strings.string_from_ptr((^byte)(array.data), n)
 			fmt_string(fi, s, verb)
 		} else if verb == 'p' {
 			fmt_pointer(fi, array.data, 'p')
 		} else {
-			fmt_write_array(fi, array.data, array.len, info.elem_size, info.elem.id, verb)
+			fmt_write_array(fi, array.data, n, info.elem_size, info.elem.id, verb)
 		}
 
 	case runtime.Type_Info_Simd_Vector:
@@ -1774,20 +1827,6 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		}
 
 
-	case runtime.Type_Info_Slice:
-		slice := cast(^mem.Raw_Slice)v.data
-		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
-			n := slice.len
-			if ol, ok := fi.optional_len.?; ok {
-				n = min(n, ol)
-			}
-			s := strings.string_from_ptr((^byte)(slice.data), n)
-			fmt_string(fi, s, verb)
-		} else if verb == 'p' {
-			fmt_pointer(fi, slice.data, 'p')
-		} else {
-			fmt_write_array(fi, slice.data, slice.len, info.elem_size, info.elem.id, verb)
-		}
 	case runtime.Type_Info_Map:
 		if verb != 'v' {
 			fmt_bad_verb(fi, verb)