From c752d0b541f5cc92fe44f510a4db1e7e02469fd6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 27 Apr 2024 09:16:18 +0100 Subject: [PATCH] Fix printing of big endian integers in a `bit_field` --- core/fmt/fmt.odin | 5 +++- core/reflect/types.odin | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index ba749d102..018c66bd3 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -2526,8 +2526,11 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit bit_offset := info.bit_offsets[i] bit_size := info.bit_sizes[i] - value := read_bits(([^]byte)(v.data), bit_offset, bit_size) type := info.types[i] + value := read_bits(([^]byte)(v.data), bit_offset, bit_size) + if reflect.is_endian_big(type) { + value <<= u64(8*type.size) - u64(bit_size) + } if !reflect.is_unsigned(runtime.type_info_core(type)) { // Sign Extension diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 9cff46a00..f242dfd5c 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -408,7 +408,68 @@ is_relative_multi_pointer :: proc(info: ^Type_Info) -> bool { } +@(require_results) +is_endian_platform :: proc(info: ^Type_Info) -> bool { + if info == nil { return false} + info := info + info = type_info_core(info) + #partial switch v in info.variant { + case Type_Info_Integer: + return v.endianness == .Platform + case Type_Info_Bit_Set: + if v.underlying != nil { + return is_endian_platform(v.underlying) + } + return true + case Type_Info_Pointer: + return true + } + return false +} +@(require_results) +is_endian_little :: proc(info: ^Type_Info) -> bool { + if info == nil { return false} + info := info + info = type_info_core(info) + #partial switch v in info.variant { + case Type_Info_Integer: + if v.endianness == .Platform { + return ODIN_ENDIAN == .Little + } + return v.endianness == .Little + case Type_Info_Bit_Set: + if v.underlying != nil { + return is_endian_platform(v.underlying) + } + return ODIN_ENDIAN == .Little + case Type_Info_Pointer: + return ODIN_ENDIAN == .Little + } + return ODIN_ENDIAN == .Little +} + +@(require_results) +is_endian_big :: proc(info: ^Type_Info) -> bool { + if info == nil { return false} + info := info + info = type_info_core(info) + #partial switch v in info.variant { + case Type_Info_Integer: + if v.endianness == .Platform { + return ODIN_ENDIAN == .Big + } + return v.endianness == .Big + case Type_Info_Bit_Set: + if v.underlying != nil { + return is_endian_platform(v.underlying) + } + return ODIN_ENDIAN == .Big + case Type_Info_Pointer: + return ODIN_ENDIAN == .Big + } + return ODIN_ENDIAN == .Big +}