mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 11:50:07 +00:00
Merge branch 'master' into fract_trunc_classify_#1574
Resolve conflicts with [9848e88] & sameify Makefile & tests/common/common.odin
This commit is contained in:
@@ -14,7 +14,6 @@ package siphash
|
||||
|
||||
import "core:crypto"
|
||||
import "core:crypto/util"
|
||||
import "core:mem"
|
||||
|
||||
/*
|
||||
High level API
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others.
|
||||
|
||||
Author of this Odin package: Jeroen van Rijn
|
||||
|
||||
Example:
|
||||
```odin
|
||||
import "core:encoding/varint"
|
||||
import "core:fmt"
|
||||
|
||||
main :: proc() {
|
||||
buf: [varint.LEB128_MAX_BYTES]u8
|
||||
|
||||
value := u128(42)
|
||||
|
||||
encode_size, encode_err := varint.encode_uleb128(buf[:], value)
|
||||
assert(encode_size == 1 && encode_err == .None)
|
||||
|
||||
fmt.println(buf[:encode_size])
|
||||
|
||||
decoded_val, decode_size, decode_err := varint.decode_uleb128(buf[:encode_size])
|
||||
assert(decoded_val == value && decode_size == encode_size && decode_err == .None)
|
||||
}
|
||||
```
|
||||
|
||||
*/
|
||||
package varint
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
Jeroen van Rijn: Initial implementation.
|
||||
*/
|
||||
|
||||
// package varint implements variable length integer encoding and decoding using
|
||||
// the LEB128 format as used by DWARF debug info, Android .dex and other file formats.
|
||||
package varint
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
|
||||
// Instead we'll set limits on the values we'll encode/decode
|
||||
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`.
|
||||
LEB128_MAX_BYTES :: 19
|
||||
|
||||
Error :: enum {
|
||||
None = 0,
|
||||
Buffer_Too_Small = 1,
|
||||
Value_Too_Large = 2,
|
||||
}
|
||||
|
||||
// Decode a slice of bytes encoding an unsigned LEB128 integer into value and number of bytes used.
|
||||
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
|
||||
decode_uleb128 :: proc(buf: []u8) -> (val: u128, size: int, err: Error) {
|
||||
more := true
|
||||
|
||||
for v, i in buf {
|
||||
size = i + 1
|
||||
|
||||
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be 0b0000_0011.
|
||||
if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && v > 0b0000_0011 {
|
||||
return 0, 0, .Value_Too_Large
|
||||
}
|
||||
|
||||
val |= u128(v & 0x7f) << uint(i * 7)
|
||||
|
||||
if v < 128 {
|
||||
more = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If the buffer runs out before the number ends, return an error.
|
||||
if more {
|
||||
return 0, 0, .Buffer_Too_Small
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Decode a slice of bytes encoding a signed LEB128 integer into value and number of bytes used.
|
||||
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
|
||||
decode_ileb128 :: proc(buf: []u8) -> (val: i128, size: int, err: Error) {
|
||||
shift: uint
|
||||
|
||||
if len(buf) == 0 {
|
||||
return 0, 0, .Buffer_Too_Small
|
||||
}
|
||||
|
||||
for v in buf {
|
||||
size += 1
|
||||
|
||||
// 18 * 7 bits = 126, which including sign means we can have a 19th byte.
|
||||
if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && v > 0x7f {
|
||||
return 0, 0, .Value_Too_Large
|
||||
}
|
||||
|
||||
val |= i128(v & 0x7f) << shift
|
||||
shift += 7
|
||||
|
||||
if v < 128 { break }
|
||||
}
|
||||
|
||||
if buf[size - 1] & 0x40 == 0x40 {
|
||||
val |= max(i128) << shift
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Encode `val` into `buf` as an unsigned LEB128 encoded series of bytes.
|
||||
// `buf` must be appropriately sized.
|
||||
encode_uleb128 :: proc(buf: []u8, val: u128) -> (size: int, err: Error) {
|
||||
val := val
|
||||
|
||||
for {
|
||||
size += 1
|
||||
|
||||
if size > len(buf) {
|
||||
fmt.println(val, buf[:size - 1])
|
||||
return 0, .Buffer_Too_Small
|
||||
}
|
||||
|
||||
low := val & 0x7f
|
||||
val >>= 7
|
||||
|
||||
if val > 0 {
|
||||
low |= 0x80 // more bytes to follow
|
||||
}
|
||||
buf[size - 1] = u8(low)
|
||||
|
||||
if val == 0 { break }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(private)
|
||||
SIGN_MASK :: (i128(1) << 121) // sign extend mask
|
||||
|
||||
// Encode `val` into `buf` as a signed LEB128 encoded series of bytes.
|
||||
// `buf` must be appropriately sized.
|
||||
encode_ileb128 :: proc(buf: []u8, val: i128) -> (size: int, err: Error) {
|
||||
val := val
|
||||
more := true
|
||||
|
||||
for more {
|
||||
size += 1
|
||||
|
||||
if size > len(buf) {
|
||||
return 0, .Buffer_Too_Small
|
||||
}
|
||||
|
||||
low := val & 0x7f
|
||||
val >>= 7
|
||||
|
||||
low = (low ~ SIGN_MASK) - SIGN_MASK
|
||||
|
||||
if (val == 0 && low & 0x40 != 0x40) || (val == -1 && low & 0x40 == 0x40) {
|
||||
more = false
|
||||
} else {
|
||||
low |= 0x80
|
||||
}
|
||||
|
||||
buf[size - 1] = u8(low)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -680,6 +680,7 @@ make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(i32(code))
|
||||
}
|
||||
|
||||
|
||||
@@ -419,6 +419,7 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
|
||||
@@ -802,6 +802,7 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ package os
|
||||
|
||||
foreign import libc "system:c"
|
||||
|
||||
import "core:runtime"
|
||||
import "core:strings"
|
||||
import "core:c"
|
||||
import "core:runtime"
|
||||
|
||||
Handle :: distinct i32
|
||||
Pid :: distinct i32
|
||||
@@ -658,6 +658,7 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
_unix_exit(c.int(code))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package os
|
||||
|
||||
import "core:sys/wasm/wasi"
|
||||
import "core:runtime"
|
||||
|
||||
Handle :: distinct i32
|
||||
Errno :: distinct i32
|
||||
@@ -93,5 +94,6 @@ heap_free :: proc(ptr: rawptr) {
|
||||
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
wasi.proc_exit(wasi.exitcode_t(code))
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
package os
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:runtime"
|
||||
|
||||
Handle :: distinct uintptr
|
||||
File_Time :: distinct u64
|
||||
@@ -128,6 +129,7 @@ get_page_size :: proc() -> int {
|
||||
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
win32.ExitProcess(win32.DWORD(code))
|
||||
}
|
||||
|
||||
|
||||
@@ -459,6 +459,11 @@ _cleanup_runtime :: proc() {
|
||||
default_temp_allocator_destroy(&global_default_temp_allocator_data)
|
||||
}
|
||||
|
||||
_cleanup_runtime_contextless :: proc "contextless" () {
|
||||
context = default_context()
|
||||
_cleanup_runtime()
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
/////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user