mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Add struct_fields_zipped and enum_fields_zipped (allowing for iteration through an #soa slice)
This commit is contained in:
+63
-21
@@ -33,6 +33,8 @@ Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector;
|
|||||||
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer;
|
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer;
|
||||||
Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice;
|
Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice;
|
||||||
|
|
||||||
|
Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value;
|
||||||
|
|
||||||
|
|
||||||
Type_Kind :: enum {
|
Type_Kind :: enum {
|
||||||
Invalid,
|
Invalid,
|
||||||
@@ -111,7 +113,7 @@ backing_type_kind :: proc(T: typeid) -> Type_Kind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
|
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == nil { return nil; }
|
if info == nil { return nil; }
|
||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
@@ -125,7 +127,7 @@ type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type_info_core :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
|
type_info_core :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == nil { return nil; }
|
if info == nil { return nil; }
|
||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
@@ -344,7 +346,7 @@ Struct_Tag :: distinct string;
|
|||||||
|
|
||||||
Struct_Field :: struct {
|
Struct_Field :: struct {
|
||||||
name: string,
|
name: string,
|
||||||
type: typeid,
|
type: ^Type_Info,
|
||||||
tag: Struct_Tag,
|
tag: Struct_Tag,
|
||||||
offset: uintptr,
|
offset: uintptr,
|
||||||
is_using: bool,
|
is_using: bool,
|
||||||
@@ -355,7 +357,7 @@ struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) {
|
|||||||
if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
|
if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
|
||||||
if 0 <= i && i < len(s.names) {
|
if 0 <= i && i < len(s.names) {
|
||||||
field.name = s.names[i];
|
field.name = s.names[i];
|
||||||
field.type = s.types[i].id;
|
field.type = s.types[i];
|
||||||
field.tag = Struct_Tag(s.tags[i]);
|
field.tag = Struct_Tag(s.tags[i]);
|
||||||
field.offset = s.offsets[i];
|
field.offset = s.offsets[i];
|
||||||
field.is_using = s.usings[i];
|
field.is_using = s.usings[i];
|
||||||
@@ -370,7 +372,7 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) {
|
|||||||
for fname, i in s.names {
|
for fname, i in s.names {
|
||||||
if fname == name {
|
if fname == name {
|
||||||
field.name = s.names[i];
|
field.name = s.names[i];
|
||||||
field.type = s.types[i].id;
|
field.type = s.types[i];
|
||||||
field.tag = Struct_Tag(s.tags[i]);
|
field.tag = Struct_Tag(s.tags[i]);
|
||||||
field.offset = s.offsets[i];
|
field.offset = s.offsets[i];
|
||||||
field.is_using = s.usings[i];
|
field.is_using = s.usings[i];
|
||||||
@@ -381,7 +383,7 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_field_value_by_name :: proc(a: any, field: string, recurse := false) -> any {
|
struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) -> any {
|
||||||
if a == nil { return nil; }
|
if a == nil { return nil; }
|
||||||
|
|
||||||
ti := runtime.type_info_base(type_info_of(a.id));
|
ti := runtime.type_info_base(type_info_of(a.id));
|
||||||
@@ -395,13 +397,13 @@ struct_field_value_by_name :: proc(a: any, field: string, recurse := false) -> a
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if recurse && s.usings[i] {
|
if allow_using && s.usings[i] {
|
||||||
f := any{
|
f := any{
|
||||||
rawptr(uintptr(a.data) + s.offsets[i]),
|
rawptr(uintptr(a.data) + s.offsets[i]),
|
||||||
s.types[i].id,
|
s.types[i].id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if res := struct_field_value_by_name(f, field, recurse); res != nil {
|
if res := struct_field_value_by_name(f, field, allow_using); res != nil {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,7 +422,7 @@ struct_field_names :: proc(T: typeid) -> []string {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_field_types :: proc(T: typeid) -> []^runtime.Type_Info {
|
struct_field_types :: proc(T: typeid) -> []^Type_Info {
|
||||||
ti := runtime.type_info_base(type_info_of(T));
|
ti := runtime.type_info_base(type_info_of(T));
|
||||||
if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
|
if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
|
||||||
return s.types;
|
return s.types;
|
||||||
@@ -445,6 +447,20 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) {
|
||||||
|
ti := runtime.type_info_base(type_info_of(T));
|
||||||
|
if s, ok := ti.variant.(runtime.Type_Info_Struct); ok {
|
||||||
|
return soa_zip(
|
||||||
|
name = s.names,
|
||||||
|
type = s.types,
|
||||||
|
tag = transmute([]Struct_Tag)s.tags,
|
||||||
|
offset = s.offsets,
|
||||||
|
is_using = s.usings,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) {
|
struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) {
|
||||||
@@ -468,7 +484,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, o
|
|||||||
switch t[i] {
|
switch t[i] {
|
||||||
case ':', '"':
|
case ':', '"':
|
||||||
break loop;
|
break loop;
|
||||||
case 0x00 ..< ' ', 0x7f .. 0x9f: // break if control character is found
|
case 0x00 ..< ' ', 0x7f ..= 0x9f: // break if control character is found
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -516,7 +532,7 @@ enum_string :: proc(a: any) -> string {
|
|||||||
if e, ok := ti.variant.(runtime.Type_Info_Enum); ok {
|
if e, ok := ti.variant.(runtime.Type_Info_Enum); ok {
|
||||||
v, _ := as_i64(a);
|
v, _ := as_i64(a);
|
||||||
for value, i in e.values {
|
for value, i in e.values {
|
||||||
if value == runtime.Type_Info_Enum_Value(v) {
|
if value == Type_Info_Enum_Value(v) {
|
||||||
return e.names[i];
|
return e.names[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -528,26 +544,24 @@ enum_string :: proc(a: any) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Given a enum type and a value name, get the enum value.
|
// Given a enum type and a value name, get the enum value.
|
||||||
enum_from_name :: proc($EnumType: typeid, name: string) -> (value: EnumType, ok: bool) {
|
enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) {
|
||||||
ti := type_info_base(type_info_of(EnumType));
|
ti := type_info_base(type_info_of(Enum_Type));
|
||||||
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
||||||
for value_name, i in eti.names {
|
for value_name, i in eti.names {
|
||||||
if value_name != name {
|
if value_name != name {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
v := eti.values[i];
|
v := eti.values[i];
|
||||||
value = EnumType(v);
|
value = Enum_Type(v);
|
||||||
ok = true;
|
ok = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
panic("expected enum type to reflect.enum_from_name");
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum_from_name_any :: proc(EnumType: typeid, name: string) -> (value: runtime.Type_Info_Enum_Value, ok: bool) {
|
enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info_Enum_Value, ok: bool) {
|
||||||
ti := runtime.type_info_base(type_info_of(EnumType));
|
ti := runtime.type_info_base(type_info_of(Enum_Type));
|
||||||
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
||||||
for value_name, i in eti.names {
|
for value_name, i in eti.names {
|
||||||
if value_name != name {
|
if value_name != name {
|
||||||
@@ -557,14 +571,42 @@ enum_from_name_any :: proc(EnumType: typeid, name: string) -> (value: runtime.Ty
|
|||||||
ok = true;
|
ok = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
panic("expected enum type to reflect.enum_from_name_any");
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
union_variant_type_info :: proc(a: any) -> ^runtime.Type_Info {
|
enum_field_names :: proc(Enum_Type: typeid) -> []string {
|
||||||
|
ti := runtime.type_info_base(type_info_of(Enum_Type));
|
||||||
|
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
||||||
|
return eti.names;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value {
|
||||||
|
ti := runtime.type_info_base(type_info_of(Enum_Type));
|
||||||
|
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
||||||
|
return eti.values;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum_Field :: struct {
|
||||||
|
name: string,
|
||||||
|
value: Type_Info_Enum_Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) {
|
||||||
|
ti := runtime.type_info_base(type_info_of(Enum_Type));
|
||||||
|
if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
|
||||||
|
return soa_zip(name=eti.names, value=eti.values);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
union_variant_type_info :: proc(a: any) -> ^Type_Info {
|
||||||
id := union_variant_typeid(a);
|
id := union_variant_typeid(a);
|
||||||
return type_info_of(id);
|
return type_info_of(id);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user