From: Brendan Hansen Date: Mon, 12 Jun 2023 01:59:59 +0000 (-0500) Subject: added: `conv.encode_hex` `conv.decode_hex` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=443bab76236edddc77b12a0469d2d16f2a596ea7;p=onyx.git added: `conv.encode_hex` `conv.decode_hex` --- diff --git a/CHANGELOG b/CHANGELOG index ce3268b3..447b4024 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,10 +6,16 @@ Additions: - New syntax for declaring quoted code blocks. - `[captures] { body }` for blocks. - `[captures] ( expr )` for expressions. +- User-level stack trace. + - Enable with `--stack-trace` + - Use `runtime.info.get_stack_trace()` to get the current stack trace. + - Used in assertions and heap allocator for better error reporting - `Optional.with` for running a block of code with the value in an Optional, if one is present. - `iter.flatten` - `-Dvariable=value` command line option to add symbols to the `runtime.vars` package. - `--no-type-info` command line option to omit type information from the binary. +- `conv.encode_hex` and `conv.decode_hex` + - Quickly convrt a byte array to and from its hex equivalent. Removals: - Remove old syntax for quoted blocks, `#quote` and `#()`. diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index 7ef8932e..c9508f29 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -15,8 +15,9 @@ use core // Enable this to enable checking for invalid blocks and other corruptions // that may happen on the heap, with the added overhead of checking that // on every alloc/resize/free. -Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug ) -Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory) +#local Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug ) +#local Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory) +#local Enable_Stack_Trace :: runtime.Stack_Trace_Enabled #load "core/intrinsics/wasm" @@ -195,18 +196,31 @@ get_freed_size :: () => { #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex); #if Enable_Debug { + // RELOCATE + trace :: macro () { + #if Enable_Stack_Trace { + trace := runtime.info.get_stack_trace(); + for trace { + log(.Error, "Core", core.tprintf("in {} ({}:{})", it.func_name, it.file, it.line)); + } + } + } + if cast(uintptr) hb_ptr < cast(uintptr) __heap_start { log(.Error, "Core", "FREEING STATIC DATA"); + trace(); return; } if hb_ptr.size & Allocated_Flag != Allocated_Flag { log(.Error, "Core", "INVALID DOUBLE FREE"); + trace(); return; } if hb_ptr.magic_number != Alloc_Block_Magic_Number { log(.Error, "Core", "FREEING INVALID BLOCK"); + trace(); return; } } diff --git a/core/conv/conv.onyx b/core/conv/conv.onyx index fc483c3e..8f835720 100644 --- a/core/conv/conv.onyx +++ b/core/conv/conv.onyx @@ -331,3 +331,39 @@ parse_float :: str_to_f64 format_int :: i64_to_str format_uint :: u64_to_str format_float :: f64_to_str + + + + +encode_hex :: (s: str, allocator := context.allocator) -> str { + #persist encode_map := u8.['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; + + new_str := make([] u8, s.count * 2, allocator); + for i: s.count { + new_str[2 * i + 0] = encode_map[(s[i] & 0xf0) >> 4]; + new_str[2 * i + 1] = encode_map[s[i] & 0xf]; + } + + return new_str; +} + +decode_hex :: (s: str, allocator := context.allocator) -> str { + assert(s.count & 1 == 0, "Expected string of even length"); + + new_str := make([] u8, s.count >> 1, allocator); + for i: range.{0, s.count, 2} { + new_str[i >> 1] = ~~((digit_to_value(s[i + 0]) << 4) | (digit_to_value(s[i + 1]))); + } + + return new_str; + + digit_to_value :: (it: u8) -> u32 { + switch it { + case #char "0" .. #char "9" do return ~~(it - #char "0"); + case #char "a" .. #char "f" do return ~~(it - #char "a" + 10); + case #char "A" .. #char "F" do return ~~(it - #char "A" + 10); + } + + return 0; + } +} \ No newline at end of file diff --git a/core/runtime/common.onyx b/core/runtime/common.onyx index 1b41acdf..0f36e8b6 100644 --- a/core/runtime/common.onyx +++ b/core/runtime/common.onyx @@ -16,9 +16,23 @@ __assert_handler :: (msg: str, site: CallSite) { __output_string("Assert failed: "); __output_string(msg); - if site.file.data != null { - __output_string(" in "); - __output_string(site.file); + + #if Stack_Trace_Enabled { + __output_string("\n"); + trace := info.get_stack_trace(); + for trace[1..trace.length] { + __output_string(" in "); + __output_string(it.func_name); + __output_string(" ("); + __output_string(it.file); + __output_string(")\n"); + } + + } else { + if site.file.data != null { + __output_string(" in "); + __output_string(site.file); + } } __output_string("\n"); diff --git a/tests/hex_autocoder b/tests/hex_autocoder new file mode 100644 index 00000000..75b9c425 --- /dev/null +++ b/tests/hex_autocoder @@ -0,0 +1,3 @@ +The quick brown fox jumps over the lazy dog +54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67 +The quick brown fox jumps over the lazy dog diff --git a/tests/hex_autocoder.onyx b/tests/hex_autocoder.onyx new file mode 100644 index 00000000..cbcbbd3d --- /dev/null +++ b/tests/hex_autocoder.onyx @@ -0,0 +1,13 @@ + +use core {*} + +main :: () { + s := "The quick brown fox jumps over the lazy dog"; + println(s); + + encoded := conv.encode_hex(s); + println(encoded); + + decoded := conv.decode_hex(encoded); + println(decoded); +}