Sfoglia il codice sorgente

Add `reflect.struct_field_count` that returns the number of fields in a struct type

Example:
```odin
package struct_count_example

import "core:fmt"
import "core:reflect"
import "core:dynlib"

Foo :: struct{
	one: int,
	two: f32,
}

Bar :: struct {
	three: int,
	four:  bool,
	five:  f64,
}

Game_Api :: struct {
	init:      proc(api: ^Game_Api),
	update:    proc(api: ^Game_Api),

	using foo: Foo,
	bar:       Bar,

	// Private stuff
	reload_count: int,
	__handle:     rawptr,
}
API_PRIVATE_COUNT :: 2

game_api: Game_Api

main :: proc() {
	fmt.printfln("Game_Api, .Top:       %v", reflect.struct_field_count(Game_Api))              // 6
	fmt.printfln("Game_Api, .Using:     %v", reflect.struct_field_count(Game_Api, .Using))      // 8
	fmt.printfln("Game_Api, .Recursive: %v", reflect.struct_field_count(Game_Api, .Recursive))  // 11

	symbols_loaded, _  := dynlib.initialize_symbols(&game_api, "game.dll")
	symbols_expected   := reflect.struct_field_count(Game_Api) - API_PRIVATE_COUNT

	if symbols_loaded == -1 {
		fmt.eprintln("Couldn't load game.dll")
		return
	} else if symbols_loaded != symbols_expected {
		fmt.eprintfln("Expected %v symbols, got %v", symbols_expected, symbols_loaded)
		return
	}
}
```
Jeroen van Rijn 1 anno fa
parent
commit
4902288a5a
1 ha cambiato i file con 56 aggiunte e 0 eliminazioni
  1. 56 0
      core/reflect/reflect.odin

+ 56 - 0
core/reflect/reflect.odin

@@ -496,6 +496,62 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr {
 	return nil
 }
 
+Struct_Field_Count_Method :: enum {
+	Top_Level,
+	Using,
+	Recursive,
+}
+
+/*
+Counts the number of fields in a struct
+
+This procedure returns the number of fields in a struct, counting in one of three ways:
+- .Top_Level: Only counts the top-level fields
+- .Using:     Same count as .Top_Level, and adds the field count of any `using s: Struct` it encounters (in addition to itself)
+- .Recursive: The count of all top-level fields, plus the count of any child struct's fields, recursively
+
+Inputs:
+- T:      The struct type
+- method: The counting method
+
+Returns:
+- The `count`, enumerated using the `method`, which will be `0` if the type is not a struct
+
+Example:
+	expected_count := reflect.struct_field_count(Game_API) - API_PRIVATE_COUNT
+	if symbols_loaded != expected_count {
+		fmt.eprintf("Expected %v symbols, got %v", expected_count, symbols_loaded)
+		return
+	}
+*/
+@(require_results)
+struct_field_count :: proc(T: typeid, method := Struct_Field_Count_Method.Top_Level) -> (count: int) {
+	ti := runtime.type_info_base(type_info_of(T))
+	if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
+		switch method {
+		case .Top_Level:
+			return int(s.field_count)
+
+		case .Using:
+			count = int(s.field_count)
+			for type, i in s.types[:s.field_count] {
+				if s.usings[i] {
+					count += struct_field_count(type.id)
+				}
+			}
+
+		case .Recursive:
+			count = int(s.field_count)
+			for type in s.types[:s.field_count] {
+				count += struct_field_count(type.id)
+			}
+
+		case: return 0
+		}
+	}
+	return
+}
+
 @(require_results)
 struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) {
 	ti := runtime.type_info_base(type_info_of(T))