aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2024-08-06 18:56:24 +0100
committerGitHub <noreply@github.com>2024-08-06 18:56:24 +0100
commit94ded29b5f8e37bd4104d30c193636d9f5e75777 (patch)
tree7deaf5adff407a8085cd8151113f729e83ef7a9f
parentbed18a17e6fbad407ac0304e5ca0b3058e1d9276 (diff)
parent17ebaffce8f97b895c651bf57567b13f2685f849 (diff)
Merge pull request #4030 from Kelimion/struct_field_count
Add `reflect.struct_field_count` that returns the number of fields in a struct type
-rw-r--r--core/reflect/reflect.odin58
1 files changed, 58 insertions, 0 deletions
diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin
index 23c0f803e..aff82136a 100644
--- a/core/reflect/reflect.odin
+++ b/core/reflect/reflect.odin
@@ -496,6 +496,64 @@ 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:
+ symbols_loaded, ok := dynlib.initialize_symbols(&game_api, "game.dll")
+ symbols_expected := reflect.struct_field_count(Game_Api) - API_PRIVATE_COUNT
+
+ if symbols_loaded != symbols_expected {
+ fmt.eprintf("Expected %v symbols, got %v", symbols_expected, 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))