mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 21:10:30 +00:00
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
}
}
```
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user