From 87956676f52a56db98e263d1074b490b71141f0b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 20 Nov 2020 16:01:16 +0000 Subject: [PATCH] Add %s support for arrays and slices of bytes --- core/fmt/fmt.odin | 25 ++++++++++++++++--------- core/reflect/types.odin | 8 ++++++++ core/runtime/core_builtin.odin | 16 +++++++++++++++- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 7eca5f503..fae380de5 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1599,13 +1599,18 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } case runtime.Type_Info_Array: - strings.write_byte(fi.buf, '['); - defer strings.write_byte(fi.buf, ']'); - for i in 0.. 0 { strings.write_string(fi.buf, ", "); } + if verb == 's' && reflect.is_byte(info.elem) { + s := strings.string_from_ptr((^byte)(v.data), info.count); + fmt_string(fi, s, verb); + } else { + strings.write_byte(fi.buf, '['); + defer strings.write_byte(fi.buf, ']'); + for i in 0.. 0 { strings.write_string(fi.buf, ", "); } - data := uintptr(v.data) + uintptr(i*info.elem_size); - fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + data := uintptr(v.data) + uintptr(i*info.elem_size); + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + } } case runtime.Type_Info_Enumerated_Array: @@ -1658,13 +1663,15 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { case runtime.Type_Info_Slice: - if verb == 'p' { - slice := cast(^mem.Raw_Slice)v.data; + slice := cast(^mem.Raw_Slice)v.data; + if verb == 's' && reflect.is_byte(info.elem) { + s := strings.string_from_ptr((^byte)(slice.data), slice.len); + fmt_string(fi, s, verb); + } else if verb == 'p' { fmt_pointer(fi, slice.data, 'p'); } else { strings.write_byte(fi.buf, '['); defer strings.write_byte(fi.buf, ']'); - slice := cast(^mem.Raw_Slice)v.data; for i in 0.. 0 { strings.write_string(fi.buf, ", "); } diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 91de8ee0b..348d516b4 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -218,6 +218,14 @@ is_unsigned :: proc(info: ^Type_Info) -> bool { return false; } +is_byte :: proc(info: ^Type_Info) -> bool { + if info == nil { return false; } + #partial switch i in type_info_base(info).variant { + case Type_Info_Integer: return info.size == 1; + } + return false; +} + is_integer :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index 0d430345e..35d082ac9 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -160,6 +160,8 @@ delete :: proc{ }; +// The new built-in procedure allocates memory. The first argument is a type, not a value, and the value +// return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator @builtin new :: inline proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T { ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc)); @@ -222,6 +224,10 @@ make_map :: proc($T: typeid/map[$K]$E, auto_cast cap: int = 16, allocator := con return m; } +// The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only) +// Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the +// type of its argument, not a pointer to it. +// Make uses the specified allocator, default is context.allocator, default is context.allocator @builtin make :: proc{ make_slice, @@ -253,6 +259,8 @@ reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) { } } +// The delete_key built-in procedure deletes the element with the specified key (m[key]) from the map. +// If m is nil, or there is no such element, this procedure is a no-op @builtin delete_key :: proc(m: ^$T/map[$K]$V, key: K) { if m != nil { @@ -286,6 +294,7 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { a.len += arg_len; } } + @builtin append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) { if array == nil { @@ -313,6 +322,8 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) a.len += arg_len; } } + +// The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type @builtin append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) { args := transmute([]E)arg; @@ -523,6 +534,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l } } +// The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type @builtin append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) { for arg in args { @@ -530,8 +542,10 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_ } } - +// The append built-in procedure appends elements to the end of a dynamic array @builtin append :: proc{append_elem, append_elems, append_elem_string}; + +// The append_soa built-in procedure appends elements to the end of an #soa dynamic array @builtin append_soa :: proc{append_soa_elem, append_soa_elems}; @builtin