aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2024-04-27 09:16:18 +0100
committergingerBill <bill@gingerbill.org>2024-04-27 09:16:18 +0100
commitc752d0b541f5cc92fe44f510a4db1e7e02469fd6 (patch)
tree4d395d54dace07adf77024a0efab04d7e10c5719
parent5969796fbfaa62ea6aba8f0e3915ab8282bb71b5 (diff)
Fix printing of big endian integers in a `bit_field`
-rw-r--r--core/fmt/fmt.odin5
-rw-r--r--core/reflect/types.odin61
2 files changed, 65 insertions, 1 deletions
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
+}