diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2023-05-12 19:26:29 +0200 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2023-05-14 03:23:24 +0200 |
| commit | a38184603411e3ce5a22040196b8b3e482c0987e (patch) | |
| tree | 7cc3e1babe3d0304bf257b70dd46bd40cafb2bf0 /core/encoding/hex/hex.odin | |
| parent | 8693a045bbba40c5614ff5912137540c91e61cb0 (diff) | |
add encoding/hex and use it to expand the percent decoding chars
Diffstat (limited to 'core/encoding/hex/hex.odin')
| -rw-r--r-- | core/encoding/hex/hex.odin | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/core/encoding/hex/hex.odin b/core/encoding/hex/hex.odin new file mode 100644 index 000000000..f66febbff --- /dev/null +++ b/core/encoding/hex/hex.odin @@ -0,0 +1,74 @@ +package hex + +import "core:strings" + +encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check { + dst := make([]byte, len(src) * 2, allocator) + for i := 0; i < len(src); i += 1 { + v := src[i] + dst[i] = HEXTABLE[v>>4] + dst[i+1] = HEXTABLE[v&0x0f] + i += 2 + } + + return dst +} + + +decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check { + if len(src) % 2 == 1 { + return + } + + dst = make([]byte, len(src) / 2, allocator) + for i, j := 0, 1; j < len(src); j += 2 { + p := src[j-1] + q := src[j] + + a := hex_digit(p) or_return + b := hex_digit(q) or_return + + dst[i] = (a << 4) | b + i += 1 + } + + return dst, true +} + +// Decodes the given sequence into one byte. +// Should be called with one rune worth of the source, eg: 0x23 -> '#'. +decode_sequence :: proc(str: string) -> (byte, bool) { + no_prefix_str := strings.trim_prefix(str, "0x") + val: byte + for i := 0; i < len(no_prefix_str); i += 1 { + index := (len(no_prefix_str) - 1) - i // reverse the loop. + + hd, ok := hex_digit(no_prefix_str[i]) + if !ok { + return 0, false + } + + val += u8(hd) << uint(4 * index) + } + + return val, true +} + +@(private) +HEXTABLE := [16]byte { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f', +} + +@(private) +hex_digit :: proc(char: byte) -> (u8, bool) { + switch char { + case '0' ..= '9': return char - '0', true + case 'a' ..= 'f': return char - 'a' + 10, true + case 'A' ..= 'F': return char - 'A' + 10, true + case: return 0, false + } +} + |