aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorftphikari <ftphikari@gmail.com>2023-07-25 15:32:18 +0300
committerGitHub <noreply@github.com>2023-07-25 15:32:18 +0300
commit699aec331d44da58bceddfb788bf349995473ad9 (patch)
tree3f5ce42c72c18fff1fc79f0229797be72f0e7638 /core
parentd2375a79f29d8377c813484bce3127ae9c205974 (diff)
parent5ac7fe453f5fbf0995c24f0c1c12ed439ae3aee9 (diff)
Merge branch 'odin-lang:master' into master
Diffstat (limited to 'core')
-rw-r--r--core/bufio/read_writer.odin66
-rw-r--r--core/bufio/reader.odin58
-rw-r--r--core/bufio/writer.odin59
-rw-r--r--core/bytes/buffer.odin82
-rw-r--r--core/bytes/reader.odin59
-rw-r--r--core/c/frontend/preprocessor/preprocess.odin4
-rw-r--r--core/compress/common.odin5
-rw-r--r--core/compress/gzip/gzip.odin2
-rw-r--r--core/compress/zlib/zlib.odin6
-rw-r--r--core/container/topological_sort/topological_sort.odin4
-rw-r--r--core/crypto/blake/blake.odin8
-rw-r--r--core/crypto/blake2b/blake2b.odin2
-rw-r--r--core/crypto/blake2s/blake2s.odin2
-rw-r--r--core/crypto/gost/gost.odin2
-rw-r--r--core/crypto/groestl/groestl.odin8
-rw-r--r--core/crypto/haval/haval.odin30
-rw-r--r--core/crypto/jh/jh.odin8
-rw-r--r--core/crypto/keccak/keccak.odin8
-rw-r--r--core/crypto/md2/md2.odin2
-rw-r--r--core/crypto/md4/md4.odin2
-rw-r--r--core/crypto/md5/md5.odin2
-rw-r--r--core/crypto/ripemd/ripemd.odin8
-rw-r--r--core/crypto/sha1/sha1.odin2
-rw-r--r--core/crypto/sha2/sha2.odin8
-rw-r--r--core/crypto/sha3/sha3.odin8
-rw-r--r--core/crypto/shake/shake.odin4
-rw-r--r--core/crypto/sm3/sm3.odin2
-rw-r--r--core/crypto/streebog/streebog.odin4
-rw-r--r--core/crypto/tiger/tiger.odin6
-rw-r--r--core/crypto/tiger2/tiger2.odin6
-rw-r--r--core/crypto/whirlpool/whirlpool.odin2
-rw-r--r--core/debug/pe/section.odin3
-rw-r--r--core/dynlib/lib_js.odin6
-rw-r--r--core/encoding/hxa/read.odin4
-rw-r--r--core/encoding/json/unmarshal.odin10
-rw-r--r--core/fmt/fmt.odin18
-rw-r--r--core/fmt/fmt_js.odin23
-rw-r--r--core/fmt/fmt_os.odin22
-rw-r--r--core/image/netpbm/netpbm.odin12
-rw-r--r--core/image/png/helpers.odin10
-rw-r--r--core/io/conv.odin104
-rw-r--r--core/io/io.odin440
-rw-r--r--core/io/multi.odin86
-rw-r--r--core/io/util.odin79
-rw-r--r--core/log/log.odin26
-rw-r--r--core/log/log_allocator.odin54
-rw-r--r--core/math/big/helpers.odin6
-rw-r--r--core/math/big/internal.odin4
-rw-r--r--core/math/big/radix.odin2
-rw-r--r--core/math/big/rat.odin2
-rw-r--r--core/math/cmplx/cmplx.odin513
-rw-r--r--core/math/cmplx/cmplx_invtrig.odin273
-rw-r--r--core/math/cmplx/cmplx_trig.odin409
-rw-r--r--core/math/ease/ease.odin2
-rw-r--r--core/math/math.odin74
-rw-r--r--core/math/math_basic.odin98
-rw-r--r--core/math/math_sincos.odin308
-rw-r--r--core/mem/allocators.odin12
-rw-r--r--core/mem/virtual/arena.odin10
-rw-r--r--core/mem/virtual/virtual_bsd.odin24
-rw-r--r--core/net/dns_unix.odin5
-rw-r--r--core/net/socket_darwin.odin8
-rw-r--r--core/net/socket_linux.odin8
-rw-r--r--core/os/os2/errors_windows.odin8
-rw-r--r--core/os/os2/file.odin68
-rw-r--r--core/os/os2/file_linux.odin84
-rw-r--r--core/os/os2/file_stream.odin82
-rw-r--r--core/os/os2/file_windows.odin91
-rw-r--r--core/os/os2/path_windows.odin2
-rw-r--r--core/os/os_darwin.odin25
-rw-r--r--core/os/os_linux.odin35
-rw-r--r--core/os/stream.odin98
-rw-r--r--core/reflect/reflect.odin6
-rw-r--r--core/runtime/core.odin2
-rw-r--r--core/runtime/core_builtin.odin12
-rw-r--r--core/runtime/default_allocators_js.odin4
-rw-r--r--core/runtime/default_allocators_nil.odin50
-rw-r--r--core/runtime/default_allocators_wasi.odin4
-rw-r--r--core/runtime/dynamic_map_internal.odin216
-rw-r--r--core/runtime/error_checks.odin22
-rw-r--r--core/runtime/internal.odin33
-rw-r--r--core/runtime/print.odin4
-rw-r--r--core/slice/ptr.odin20
-rw-r--r--core/slice/slice.odin30
-rw-r--r--core/strings/builder.odin41
-rw-r--r--core/strings/reader.odin58
-rw-r--r--core/strings/strings.odin8
-rw-r--r--core/sync/primitives.odin17
-rw-r--r--core/sys/unix/syscalls_linux.odin34
-rw-r--r--core/sys/windows/kernel32.odin5
-rw-r--r--core/sys/windows/ws2_32.odin10
-rw-r--r--core/testing/runner_windows.odin2
-rw-r--r--core/testing/testing.odin17
-rw-r--r--core/text/edit/text_edit.odin7
-rw-r--r--core/text/i18n/i18n.odin4
-rw-r--r--core/text/match/strlib.odin5
-rw-r--r--core/text/table/table.odin4
-rw-r--r--core/thread/thread_pool.odin2
-rw-r--r--core/unicode/tools/generate_entity_table.odin2
99 files changed, 2882 insertions, 1354 deletions
diff --git a/core/bufio/read_writer.odin b/core/bufio/read_writer.odin
index f9ae1ed45..3e6bd3aa0 100644
--- a/core/bufio/read_writer.odin
+++ b/core/bufio/read_writer.odin
@@ -14,51 +14,29 @@ read_writer_init :: proc(rw: ^Read_Writer, r: ^Reader, w: ^Writer) {
}
read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) {
- s.stream_data = rw
- s.stream_vtable = &_read_writer_vtable
+ s.procedure = _read_writer_procedure
+ s.data = rw
return
}
@(private)
-_read_writer_vtable := io.Stream_VTable{
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Read_Writer)(s.stream_data).r
- return reader_read(b, p)
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- b := (^Read_Writer)(s.stream_data).r
- return reader_unread_byte(b)
- },
- impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
- b := (^Read_Writer)(s.stream_data).r
- return reader_read_rune(b)
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- b := (^Read_Writer)(s.stream_data).r
- return reader_unread_rune(b)
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- b := (^Read_Writer)(s.stream_data).r
- return reader_write_to(b, w)
- },
- impl_flush = proc(s: io.Stream) -> io.Error {
- b := (^Read_Writer)(s.stream_data).w
- return writer_flush(b)
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Read_Writer)(s.stream_data).w
- return writer_write(b, p)
- },
- impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
- b := (^Read_Writer)(s.stream_data).w
- return writer_write_byte(b, c)
- },
- impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
- b := (^Read_Writer)(s.stream_data).w
- return writer_write_rune(b, r)
- },
- impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
- b := (^Read_Writer)(s.stream_data).w
- return writer_read_from(b, r)
- },
-}
+_read_writer_procedure := proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ rw := (^Read_Writer)(stream_data)
+ n_int: int
+ #partial switch mode {
+ case .Flush:
+ err = writer_flush(rw.w)
+ return
+ case .Read:
+ n_int, err = reader_read(rw.r, p)
+ n = i64(n_int)
+ return
+ case .Write:
+ n_int, err = writer_write(rw.w, p)
+ n = i64(n_int)
+ return
+ case .Query:
+ return io.query_utility({.Flush, .Read, .Write, .Query})
+ }
+ return 0, .Empty
+} \ No newline at end of file
diff --git a/core/bufio/reader.odin b/core/bufio/reader.odin
index 6bfc4cd9d..dc4e02c02 100644
--- a/core/bufio/reader.odin
+++ b/core/bufio/reader.odin
@@ -311,18 +311,6 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
}
m: i64
- if nr, ok := io.to_writer_to(b.rd); ok {
- m, err = io.write_to(nr, w)
- n += m
- return n, err
- }
-
- if nw, ok := io.to_reader_from(w); ok {
- m, err = io.read_from(nw, b.rd)
- n += m
- return n, err
- }
-
if b.w-b.r < len(b.buf) {
if err = _reader_read_new_chunk(b); err != nil {
return
@@ -352,48 +340,28 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
// reader_to_stream converts a Reader into an io.Stream
reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) {
- s.stream_data = b
- s.stream_vtable = &_reader_vtable
+ s.data = b
+ s.procedure = _reader_proc
return
}
@(private)
-_reader_vtable := io.Stream_VTable{
- impl_destroy = proc(s: io.Stream) -> io.Error {
- b := (^Reader)(s.stream_data)
+_reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ b := (^Reader)(stream_data)
+ #partial switch mode {
+ case .Read:
+ return io._i64_err(reader_read(b, p))
+ case .Destroy:
reader_destroy(b)
- return nil
- },
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Reader)(s.stream_data)
- return reader_read(b, p)
- },
- impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) {
- b := (^Reader)(s.stream_data)
- return reader_read_byte(b)
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- b := (^Reader)(s.stream_data)
- return reader_unread_byte(b)
- },
- impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
- b := (^Reader)(s.stream_data)
- return reader_read_rune(b)
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- b := (^Reader)(s.stream_data)
- return reader_unread_rune(b)
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- b := (^Reader)(s.stream_data)
- return reader_write_to(b, w)
- },
+ return
+ case .Query:
+ return io.query_utility({.Read, .Destroy, .Query})
+ }
+ return 0, .Empty
}
-
-
//
// Utility procedures
//
diff --git a/core/bufio/writer.odin b/core/bufio/writer.odin
index ed0d557c5..bfa8b804f 100644
--- a/core/bufio/writer.odin
+++ b/core/bufio/writer.odin
@@ -173,14 +173,6 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
if b.err != nil {
return 0, b.err
}
- if writer_buffered(b) == 0 {
- if w, ok := io.to_reader_from(b.wr); !ok {
- n, err = io.read_from(w, r)
- b.err = err
- return
- }
- }
-
for {
if writer_available(b) == 0 {
writer_flush(b) or_return
@@ -222,46 +214,35 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
// writer_to_stream converts a Writer into an io.Stream
writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
- s.stream_data = b
- s.stream_vtable = &_writer_vtable
+ s.data = b
+ s.procedure = _writer_proc
return
}
// writer_to_stream converts a Writer into an io.Stream
writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) {
- s.stream_data = b
- s.stream_vtable = &_writer_vtable
- return
+ return writer_to_stream(b)
}
-
@(private)
-_writer_vtable := io.Stream_VTable{
- impl_destroy = proc(s: io.Stream) -> io.Error {
- b := (^Writer)(s.stream_data)
+_writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ b := (^Writer)(stream_data)
+ #partial switch mode {
+ case .Flush:
+ err = writer_flush(b)
+ return
+ case .Write:
+ n_int: int
+ n_int, err = writer_write(b, p)
+ n = i64(n_int)
+ return
+ case .Destroy:
writer_destroy(b)
- return nil
- },
- impl_flush = proc(s: io.Stream) -> io.Error {
- b := (^Writer)(s.stream_data)
- return writer_flush(b)
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Writer)(s.stream_data)
- return writer_write(b, p)
- },
- impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
- b := (^Writer)(s.stream_data)
- return writer_write_byte(b, c)
- },
- impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
- b := (^Writer)(s.stream_data)
- return writer_write_rune(b, r)
- },
- impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
- b := (^Writer)(s.stream_data)
- return writer_read_from(b, r)
- },
+ return
+ case .Query:
+ return io.query_utility({.Flush, .Write, .Destroy, .Query})
+ }
+ return 0, .Empty
}
diff --git a/core/bytes/buffer.odin b/core/bytes/buffer.odin
index b60a8e877..4375d8195 100644
--- a/core/bytes/buffer.odin
+++ b/core/bytes/buffer.odin
@@ -375,69 +375,31 @@ buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #n
buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
- s.stream_data = b
- s.stream_vtable = &_buffer_vtable
+ s.data = b
+ s.procedure = _buffer_proc
return
}
@(private)
-_buffer_vtable := io.Stream_VTable{
- impl_size = proc(s: io.Stream) -> i64 {
- b := (^Buffer)(s.stream_data)
- return i64(buffer_capacity(b))
- },
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_read(b, p)
- },
- impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_read_at(b, p, int(offset))
- },
- impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_read_byte(b)
- },
- impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_read_rune(b)
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_write(b, p)
- },
- impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_write_at(b, p, int(offset))
- },
- impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
- b := (^Buffer)(s.stream_data)
- return buffer_write_byte(b, c)
- },
- impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_write_rune(b, r)
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data)
- return buffer_unread_byte(b)
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data)
- return buffer_unread_rune(b)
- },
- impl_destroy = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data)
+_buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ b := (^Buffer)(stream_data)
+ #partial switch mode {
+ case .Read:
+ return io._i64_err(buffer_read(b, p))
+ case .Read_At:
+ return io._i64_err(buffer_read_at(b, p, int(offset)))
+ case .Write:
+ return io._i64_err(buffer_write(b, p))
+ case .Write_At:
+ return io._i64_err(buffer_write_at(b, p, int(offset)))
+ case .Size:
+ n = i64(buffer_capacity(b))
+ return
+ case .Destroy:
buffer_destroy(b)
- return nil
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_write_to(b, w)
- },
- impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
- b := (^Buffer)(s.stream_data)
- return buffer_read_from(b, r)
- },
+ return
+ case .Query:
+ return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
+ }
+ return 0, .Empty
}
-
diff --git a/core/bytes/reader.odin b/core/bytes/reader.odin
index 7c37f3061..4b18345ba 100644
--- a/core/bytes/reader.odin
+++ b/core/bytes/reader.odin
@@ -16,8 +16,8 @@ reader_init :: proc(r: ^Reader, s: []byte) {
}
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
- s.stream_data = r
- s.stream_vtable = &_reader_vtable
+ s.data = r
+ s.procedure = _reader_proc
return
}
@@ -137,41 +137,22 @@ reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
@(private)
-_reader_vtable := io.Stream_VTable{
- impl_size = proc(s: io.Stream) -> i64 {
- r := (^Reader)(s.stream_data)
- return reader_size(r)
- },
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read(r, p)
- },
- impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_at(r, p, off)
- },
- impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_byte(r)
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- r := (^Reader)(s.stream_data)
- return reader_unread_byte(r)
- },
- impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_rune(r)
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- r := (^Reader)(s.stream_data)
- return reader_unread_rune(r)
- },
- impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_seek(r, offset, whence)
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_write_to(r, w)
- },
+_reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ r := (^Reader)(stream_data)
+ #partial switch mode {
+ case .Read:
+ return io._i64_err(reader_read(r, p))
+ case .Read_At:
+ return io._i64_err(reader_read_at(r, p, offset))
+ case .Seek:
+ n, err = reader_seek(r, offset, whence)
+ return
+ case .Size:
+ n = reader_size(r)
+ return
+ case .Query:
+ return io.query_utility({.Read, .Read_At, .Seek, .Size, .Query})
+ }
+ return 0, .Empty
}
+
diff --git a/core/c/frontend/preprocessor/preprocess.odin b/core/c/frontend/preprocessor/preprocess.odin
index 4cfad2c1c..b5eab0bb3 100644
--- a/core/c/frontend/preprocessor/preprocess.odin
+++ b/core/c/frontend/preprocessor/preprocess.odin
@@ -1118,7 +1118,7 @@ expand_macro :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> bool {
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
- tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
+ tpath := filepath.join({cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
if os.exists(tpath) {
return strings.clone(tpath), true
}
@@ -1136,7 +1136,7 @@ search_include_paths :: proc(cpp: ^Preprocessor, filename: string) -> (path: str
}
for include_path in cpp.include_paths {
- tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator)
+ tpath := filepath.join({include_path, filename}, allocator=context.temp_allocator)
if os.exists(tpath) {
path, ok = strings.clone(tpath), true
cpp.filepath_cache[filename] = path
diff --git a/core/compress/common.odin b/core/compress/common.odin
index 6bcc46bf2..bc56229c2 100644
--- a/core/compress/common.odin
+++ b/core/compress/common.odin
@@ -188,7 +188,8 @@ input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Erro
}
input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) {
- return io.size(z.input), nil
+ res, _ = io.size(z.input)
+ return
}
input_size :: proc{input_size_from_memory, input_size_from_stream}
@@ -215,7 +216,7 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
// TODO: REMOVE ALL USE OF context.temp_allocator here
// the is literally no need for it
b := make([]u8, size, context.temp_allocator)
- _, e := z.input->impl_read(b[:])
+ _, e := io.read(z.input, b[:])
if e == .None {
return b, .None
}
diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin
index 4de4d1b63..b0ca4491b 100644
--- a/core/compress/gzip/gzip.odin
+++ b/core/compress/gzip/gzip.odin
@@ -335,7 +335,7 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
- zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size)
+ zlib_error := zlib.inflate_raw(z, expected_output_size=expected_output_size)
if zlib_error != nil {
return zlib_error
}
diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin
index 855eef7a8..21172e8e8 100644
--- a/core/compress/zlib/zlib.odin
+++ b/core/compress/zlib/zlib.odin
@@ -471,7 +471,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
}
// Parse ZLIB stream without header.
- inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return
+ inflate_raw(ctx, expected_output_size=expected_output_size) or_return
if !raw {
compress.discard_to_next_byte_lsb(ctx)
@@ -665,7 +665,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
ctx.input_data = input
ctx.output = buf
- return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size)
+ return inflate_from_context(&ctx, raw=raw, expected_output_size=expected_output_size)
}
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
@@ -674,7 +674,7 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
ctx.input_data = input
ctx.output = buf
- return inflate_raw(z=&ctx, expected_output_size=expected_output_size)
+ return inflate_raw(&ctx, expected_output_size=expected_output_size)
}
inflate :: proc{inflate_from_context, inflate_from_byte_array}
diff --git a/core/container/topological_sort/topological_sort.odin b/core/container/topological_sort/topological_sort.odin
index 4b69930d5..314e3e070 100644
--- a/core/container/topological_sort/topological_sort.odin
+++ b/core/container/topological_sort/topological_sort.odin
@@ -32,7 +32,7 @@ init :: proc(sorter: ^$S/Sorter($K)) {
}
destroy :: proc(sorter: ^$S/Sorter($K)) {
- for _, v in &sorter.relations {
+ for _, v in sorter.relations {
delete(v.dependents)
}
delete(sorter.relations)
@@ -80,7 +80,7 @@ sort :: proc(sorter: ^$S/Sorter($K)) -> (sorted, cycled: [dynamic]K) {
}
}
- for root in &sorted do for k, _ in relations[root].dependents {
+ for root in sorted do for k, _ in relations[root].dependents {
relation := &relations[k]
relation.dependencies -= 1
if relation.dependencies == 0 {
diff --git a/core/crypto/blake/blake.odin b/core/crypto/blake/blake.odin
index 5fc0a02b9..3685109e4 100644
--- a/core/crypto/blake/blake.odin
+++ b/core/crypto/blake/blake.odin
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin
index e75d74197..8f0770f82 100644
--- a/core/crypto/blake2b/blake2b.odin
+++ b/core/crypto/blake2b/blake2b.odin
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_blake2.update(&ctx, buf[:read])
}
diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin
index 831335081..6a2d4ab9b 100644
--- a/core/crypto/blake2s/blake2s.odin
+++ b/core/crypto/blake2s/blake2s.odin
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_blake2.update(&ctx, buf[:read])
}
diff --git a/core/crypto/gost/gost.odin b/core/crypto/gost/gost.odin
index 1d0274fae..5aca8ce95 100644
--- a/core/crypto/gost/gost.odin
+++ b/core/crypto/gost/gost.odin
@@ -65,7 +65,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/groestl/groestl.odin b/core/crypto/groestl/groestl.odin
index 8e5a2440d..61460808f 100644
--- a/core/crypto/groestl/groestl.odin
+++ b/core/crypto/groestl/groestl.odin
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/haval/haval.odin b/core/crypto/haval/haval.odin
index 811ecf95d..b98facb33 100644
--- a/core/crypto/haval/haval.odin
+++ b/core/crypto/haval/haval.odin
@@ -79,7 +79,7 @@ hash_stream_128_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -164,7 +164,7 @@ hash_stream_128_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -249,7 +249,7 @@ hash_stream_128_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -334,7 +334,7 @@ hash_stream_160_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -419,7 +419,7 @@ hash_stream_160_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -504,7 +504,7 @@ hash_stream_160_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -589,7 +589,7 @@ hash_stream_192_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -674,7 +674,7 @@ hash_stream_192_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -759,7 +759,7 @@ hash_stream_192_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -844,7 +844,7 @@ hash_stream_224_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -929,7 +929,7 @@ hash_stream_224_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -1014,7 +1014,7 @@ hash_stream_224_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -1099,7 +1099,7 @@ hash_stream_256_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -1184,7 +1184,7 @@ hash_stream_256_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
@@ -1270,7 +1270,7 @@ hash_stream_256_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read]))
if read > 0 {
update(&ctx, buf[:read])
diff --git a/core/crypto/jh/jh.odin b/core/crypto/jh/jh.odin
index 42c2d1d34..5dc6c4e6b 100644
--- a/core/crypto/jh/jh.odin
+++ b/core/crypto/jh/jh.odin
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/keccak/keccak.odin b/core/crypto/keccak/keccak.odin
index aeb5aac52..4c74858d2 100644
--- a/core/crypto/keccak/keccak.odin
+++ b/core/crypto/keccak/keccak.odin
@@ -77,7 +77,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -159,7 +159,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -241,7 +241,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -323,7 +323,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
diff --git a/core/crypto/md2/md2.odin b/core/crypto/md2/md2.odin
index 711e6e9f6..4942183e1 100644
--- a/core/crypto/md2/md2.odin
+++ b/core/crypto/md2/md2.odin
@@ -64,7 +64,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/md4/md4.odin b/core/crypto/md4/md4.odin
index b2651225b..8efdbb5a5 100644
--- a/core/crypto/md4/md4.odin
+++ b/core/crypto/md4/md4.odin
@@ -68,7 +68,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/md5/md5.odin b/core/crypto/md5/md5.odin
index 30a556102..858480b04 100644
--- a/core/crypto/md5/md5.odin
+++ b/core/crypto/md5/md5.odin
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/ripemd/ripemd.odin b/core/crypto/ripemd/ripemd.odin
index 702d29037..f9edb121b 100644
--- a/core/crypto/ripemd/ripemd.odin
+++ b/core/crypto/ripemd/ripemd.odin
@@ -69,7 +69,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -145,7 +145,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -221,7 +221,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -297,7 +297,7 @@ hash_stream_320 :: proc(s: io.Stream) -> ([DIGEST_SIZE_320]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/sha1/sha1.odin b/core/crypto/sha1/sha1.odin
index b0dbd7dc8..599d1791e 100644
--- a/core/crypto/sha1/sha1.odin
+++ b/core/crypto/sha1/sha1.odin
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin
index 9792a4cb8..0f55c4be1 100644
--- a/core/crypto/sha2/sha2.odin
+++ b/core/crypto/sha2/sha2.odin
@@ -74,7 +74,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -153,7 +153,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -232,7 +232,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -311,7 +311,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/sha3/sha3.odin b/core/crypto/sha3/sha3.odin
index 1202f8b23..5d8ad2106 100644
--- a/core/crypto/sha3/sha3.odin
+++ b/core/crypto/sha3/sha3.odin
@@ -73,7 +73,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -152,7 +152,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -231,7 +231,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -310,7 +310,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
diff --git a/core/crypto/shake/shake.odin b/core/crypto/shake/shake.odin
index 525dcfbd3..020ba68f3 100644
--- a/core/crypto/shake/shake.odin
+++ b/core/crypto/shake/shake.odin
@@ -73,7 +73,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
@@ -155,7 +155,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin
index 74c9f22e2..9e684ff08 100644
--- a/core/crypto/sm3/sm3.odin
+++ b/core/crypto/sm3/sm3.odin
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/streebog/streebog.odin b/core/crypto/streebog/streebog.odin
index f85977cba..42da1e695 100644
--- a/core/crypto/streebog/streebog.odin
+++ b/core/crypto/streebog/streebog.odin
@@ -70,7 +70,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
@@ -146,7 +146,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/crypto/tiger/tiger.odin b/core/crypto/tiger/tiger.odin
index cf6159fad..614926129 100644
--- a/core/crypto/tiger/tiger.odin
+++ b/core/crypto/tiger/tiger.odin
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
diff --git a/core/crypto/tiger2/tiger2.odin b/core/crypto/tiger2/tiger2.odin
index e8f2c4edb..ead874d56 100644
--- a/core/crypto/tiger2/tiger2.odin
+++ b/core/crypto/tiger2/tiger2.odin
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
_tiger.update(&ctx, buf[:read])
}
diff --git a/core/crypto/whirlpool/whirlpool.odin b/core/crypto/whirlpool/whirlpool.odin
index 0cfef7c6b..cf0bf6490 100644
--- a/core/crypto/whirlpool/whirlpool.odin
+++ b/core/crypto/whirlpool/whirlpool.odin
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf)
read := 1
for read > 0 {
- read, _ = s->impl_read(buf)
+ read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
diff --git a/core/debug/pe/section.odin b/core/debug/pe/section.odin
index 809da8bb4..926306dbb 100644
--- a/core/debug/pe/section.odin
+++ b/core/debug/pe/section.odin
@@ -1,8 +1,5 @@
package debug_pe
-import "core:runtime"
-import "core:io"
-
Section_Header32 :: struct {
name: [8]u8,
virtual_size: u32le,
diff --git a/core/dynlib/lib_js.odin b/core/dynlib/lib_js.odin
index 37dab8758..ace1b0939 100644
--- a/core/dynlib/lib_js.odin
+++ b/core/dynlib/lib_js.odin
@@ -3,13 +3,13 @@
package dynlib
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
- return
+ return nil, false
}
_unload_library :: proc(library: Library) -> bool {
- return
+ return false
}
_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
- return
+ return nil, false
}
diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin
index abe295530..8a8636f19 100644
--- a/core/encoding/hxa/read.odin
+++ b/core/encoding/hxa/read.odin
@@ -83,7 +83,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
meta_data = make([]Meta, int(capacity))
count := 0
defer meta_data = meta_data[:count]
- for m in &meta_data {
+ for &m in meta_data {
m.name = read_name(r) or_return
type := read_value(r, Meta_Value_Type) or_return
@@ -116,7 +116,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
layer_count := 0
layers = make(Layer_Stack, stack_count)
defer layers = layers[:layer_count]
- for layer in &layers {
+ for &layer in layers {
layer.name = read_name(r) or_return
layer.components = read_value(r, u8) or_return
type := read_value(r, Layer_Data_Type) or_return
diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin
index e6c61d8fa..678f2dcfa 100644
--- a/core/encoding/json/unmarshal.odin
+++ b/core/encoding/json/unmarshal.odin
@@ -72,7 +72,7 @@ unmarshal_string :: proc(data: string, ptr: ^$T, spec := DEFAULT_SPECIFICATION,
@(private)
assign_bool :: proc(val: any, b: bool) -> bool {
v := reflect.any_core(val)
- switch dst in &v {
+ switch &dst in v {
case bool: dst = bool(b)
case b8: dst = b8 (b)
case b16: dst = b16 (b)
@@ -85,7 +85,7 @@ assign_bool :: proc(val: any, b: bool) -> bool {
@(private)
assign_int :: proc(val: any, i: $T) -> bool {
v := reflect.any_core(val)
- switch dst in &v {
+ switch &dst in v {
case i8: dst = i8 (i)
case i16: dst = i16 (i)
case i16le: dst = i16le (i)
@@ -122,7 +122,7 @@ assign_int :: proc(val: any, i: $T) -> bool {
@(private)
assign_float :: proc(val: any, f: $T) -> bool {
v := reflect.any_core(val)
- switch dst in &v {
+ switch &dst in v {
case f16: dst = f16 (f)
case f16le: dst = f16le(f)
case f16be: dst = f16be(f)
@@ -150,7 +150,7 @@ assign_float :: proc(val: any, f: $T) -> bool {
@(private)
unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool {
val := val
- switch dst in &val {
+ switch &dst in val {
case string:
dst = str
return true
@@ -215,7 +215,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
}
}
- switch dst in &v {
+ switch &dst in v {
// Handle json.Value as an unknown type
case Value:
dst = parse_value(p) or_return
diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin
index 61f7b5d99..f1f94b1b3 100644
--- a/core/fmt/fmt.odin
+++ b/core/fmt/fmt.odin
@@ -123,7 +123,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
aprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.builder_init(&str)
- sbprint(buf=&str, args=args, sep=sep)
+ sbprint(&str, ..args, sep=sep)
return strings.to_string(str)
}
// Creates a formatted string with a newline character at the end
@@ -139,7 +139,7 @@ aprint :: proc(args: ..any, sep := " ") -> string {
aprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.builder_init(&str)
- sbprintln(buf=&str, args=args, sep=sep)
+ sbprintln(&str, ..args, sep=sep)
return strings.to_string(str)
}
// Creates a formatted string using a format string and arguments
@@ -171,7 +171,7 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
tprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.builder_init(&str, context.temp_allocator)
- sbprint(buf=&str, args=args, sep=sep)
+ sbprint(&str, ..args, sep=sep)
return strings.to_string(str)
}
// Creates a formatted string with a newline character at the end
@@ -187,7 +187,7 @@ tprint :: proc(args: ..any, sep := " ") -> string {
tprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.builder_init(&str, context.temp_allocator)
- sbprintln(buf=&str, args=args, sep=sep)
+ sbprintln(&str, ..args, sep=sep)
return strings.to_string(str)
}
// Creates a formatted string using a format string and arguments
@@ -217,7 +217,7 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
//
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_bytes(buf[0:len(buf)])
- return sbprint(buf=&sb, args=args, sep=sep)
+ return sbprint(&sb, ..args, sep=sep)
}
// Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer.
//
@@ -230,7 +230,7 @@ bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
//
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_bytes(buf[0:len(buf)])
- return sbprintln(buf=&sb, args=args, sep=sep)
+ return sbprintln(&sb, ..args, sep=sep)
}
// Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer.
//
@@ -327,7 +327,7 @@ ctprintf :: proc(format: string, args: ..any) -> cstring {
// Returns: A formatted string
//
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
- wprint(w=strings.to_writer(buf), args=args, sep=sep)
+ wprint(strings.to_writer(buf), ..args, sep=sep)
return strings.to_string(buf^)
}
// Formats and writes to a strings.Builder buffer using the default print settings
@@ -340,7 +340,7 @@ sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string
//
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
- wprintln(w=strings.to_writer(buf), args=args, sep=sep)
+ wprintln(strings.to_writer(buf), ..args, sep=sep)
return strings.to_string(buf^)
}
// Formats and writes to a strings.Builder buffer according to the specified format string
@@ -353,7 +353,7 @@ sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string
//
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
- wprintf(w=strings.to_writer(buf), fmt=fmt, args=args)
+ wprintf(strings.to_writer(buf), fmt, ..args)
return strings.to_string(buf^)
}
// Formats and writes to an io.Writer using the default print settings
diff --git a/core/fmt/fmt_js.odin b/core/fmt/fmt_js.odin
index 5e06041f5..881cde867 100644
--- a/core/fmt/fmt_js.odin
+++ b/core/fmt/fmt_js.odin
@@ -11,27 +11,24 @@ foreign odin_env {
}
@(private="file")
-write_vtable := io.Stream_VTable{
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- fd := u32(uintptr(s.stream_data))
+write_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ if mode == .Write {
+ fd := u32(uintptr(stream_data))
write(fd, p)
- return len(p), nil
- },
+ return i64(len(p)), nil
+ }
+ return 0, .Empty
}
@(private="file")
stdout := io.Writer{
- stream = {
- stream_vtable = &write_vtable,
- stream_data = rawptr(uintptr(1)),
- },
+ procedure = write_stream_proc,
+ data = rawptr(uintptr(1)),
}
@(private="file")
stderr := io.Writer{
- stream = {
- stream_vtable = &write_vtable,
- stream_data = rawptr(uintptr(2)),
- },
+ procedure = write_stream_proc,
+ data = rawptr(uintptr(2)),
}
// print formats using the default print settings and writes to stdout
diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin
index 861b0c3b9..840fd1545 100644
--- a/core/fmt/fmt_os.odin
+++ b/core/fmt/fmt_os.odin
@@ -12,9 +12,9 @@ fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
b: bufio.Writer
defer bufio.writer_flush(&b)
- bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
+ bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
- return wprint(w=w, args=args, sep=sep)
+ return wprint(w, ..args, sep=sep)
}
// fprintln formats using the default print settings and writes to fd
@@ -23,10 +23,10 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
b: bufio.Writer
defer bufio.writer_flush(&b)
- bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
+ bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
- return wprintln(w=w, args=args, sep=sep)
+ return wprintln(w, ..args, sep=sep)
}
// fprintf formats according to the specified format string and writes to fd
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
@@ -34,7 +34,7 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
b: bufio.Writer
defer bufio.writer_flush(&b)
- bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
+ bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprintf(w, fmt, ..args)
@@ -44,7 +44,7 @@ fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> (n: int, err: io
b: bufio.Writer
defer bufio.writer_flush(&b)
- bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
+ bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprint_type(w, info)
@@ -54,22 +54,22 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
b: bufio.Writer
defer bufio.writer_flush(&b)
- bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
+ bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprint_typeid(w, id)
}
// print formats using the default print settings and writes to os.stdout
-print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
+print :: proc(args: ..any, sep := " ") -> int { return fprint(os.stdout, ..args, sep=sep) }
// println formats using the default print settings and writes to os.stdout
-println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
+println :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stdout, ..args, sep=sep) }
// printf formats according to the specified format string and writes to os.stdout
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
// eprint formats using the default print settings and writes to os.stderr
-eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
+eprint :: proc(args: ..any, sep := " ") -> int { return fprint(os.stderr, ..args, sep=sep) }
// eprintln formats using the default print settings and writes to os.stderr
-eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
+eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stderr, ..args, sep=sep) }
// eprintf formats according to the specified format string and writes to os.stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin
index cb07b1e3a..74e482cb4 100644
--- a/core/image/netpbm/netpbm.odin
+++ b/core/image/netpbm/netpbm.odin
@@ -161,18 +161,18 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
// convert from native endianness
if img.depth == 16 {
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
- for p in &pixels {
+ for &p in pixels {
p = u16be(transmute(u16) p)
}
} else if header.format in PFM {
if header.little_endian {
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
- for p in &pixels {
+ for &p in pixels {
p = f32le(transmute(f32) p)
}
} else {
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
- for p in &pixels {
+ for &p in pixels {
p = f32be(transmute(f32) p)
}
}
@@ -578,18 +578,18 @@ decode_image :: proc(img: ^Image, header: Header, data: []byte, allocator := con
if header.format in PFM {
pixels := mem.slice_data_cast([]f32, img.pixels.buf[:])
if header.little_endian {
- for p in &pixels {
+ for &p in pixels {
p = f32(transmute(f32le) p)
}
} else {
- for p in &pixels {
+ for &p in pixels {
p = f32(transmute(f32be) p)
}
}
} else {
if img.depth == 16 {
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
- for p in &pixels {
+ for &p in pixels {
p = u16(transmute(u16be) p)
}
}
diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin
index bfe56d62e..889b3cb6b 100644
--- a/core/image/png/helpers.odin
+++ b/core/image/png/helpers.odin
@@ -36,7 +36,7 @@ destroy :: proc(img: ^Image) {
bytes.buffer_destroy(&img.pixels)
if v, ok := img.metadata.(^image.PNG_Info); ok {
- for chunk in &v.chunks {
+ for chunk in v.chunks {
delete(chunk.data)
}
delete(v.chunks)
@@ -99,7 +99,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
case .tEXt:
ok = true
- fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator)
+ fields := bytes.split(c.data, sep=[]u8{0}, allocator=context.temp_allocator)
if len(fields) == 2 {
res.keyword = strings.clone(string(fields[0]))
res.text = strings.clone(string(fields[1]))
@@ -110,7 +110,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
case .zTXt:
ok = true
- fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
+ fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
if len(fields) != 3 || len(fields[1]) != 0 {
// Compression method must be 0=Deflate, which thanks to the split above turns
// into an empty slice
@@ -199,7 +199,7 @@ text_destroy :: proc(text: Text) {
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
- fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
+ fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
if len(fields[0]) < 1 || len(fields[0]) > 79 {
// Invalid profile name
@@ -263,7 +263,7 @@ splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
}
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
- fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
+ fields := bytes.split_n(c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
if len(fields) != 2 {
return
}
diff --git a/core/io/conv.odin b/core/io/conv.odin
index 39a72d69d..e3286baca 100644
--- a/core/io/conv.odin
+++ b/core/io/conv.odin
@@ -1,124 +1,80 @@
package io
to_reader :: proc(s: Stream) -> (r: Reader, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read == nil {
- ok = false
- }
+ r = s
+ ok = .Read in query(s)
return
}
to_writer :: proc(s: Stream) -> (w: Writer, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write == nil {
- ok = false
- }
+ w = s
+ ok = .Write in query(s)
return
}
to_closer :: proc(s: Stream) -> (c: Closer, ok: bool = true) #optional_ok {
- c.stream = s
- if s.stream_vtable == nil || s.impl_close == nil {
- ok = false
- }
+ c = s
+ ok = .Close in query(s)
return
}
to_flusher :: proc(s: Stream) -> (f: Flusher, ok: bool = true) #optional_ok {
- f.stream = s
- if s.stream_vtable == nil || s.impl_flush == nil {
- ok = false
- }
+ f = s
+ ok = .Flush in query(s)
return
}
to_seeker :: proc(s: Stream) -> (seeker: Seeker, ok: bool = true) #optional_ok {
- seeker.stream = s
- if s.stream_vtable == nil || s.impl_seek == nil {
- ok = false
- }
+ seeker = s
+ ok = .Seek in query(s)
return
}
to_read_writer :: proc(s: Stream) -> (r: Read_Writer, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil {
- ok = false
- }
+ r = s
+ ok = query(s) >= {.Read, .Write}
return
}
to_read_closer :: proc(s: Stream) -> (r: Read_Closer, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read == nil || s.impl_close == nil {
- ok = false
- }
+ r = s
+ ok = query(s) >= {.Read, .Close}
return
}
to_read_write_closer :: proc(s: Stream) -> (r: Read_Write_Closer, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_close == nil {
- ok = false
- }
+ r = s
+ ok = query(s) >= {.Read, .Write, .Close}
return
}
to_read_write_seeker :: proc(s: Stream) -> (r: Read_Write_Seeker, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_seek == nil {
- ok = false
- }
+ r = s
+ ok = query(s) >= {.Read, .Write, .Seek}
return
}
to_write_flusher :: proc(s: Stream) -> (w: Write_Flusher, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil {
- ok = false
- }
+ w = s
+ ok = query(s) >= {.Write, .Flush}
return
}
to_write_flush_closer :: proc(s: Stream) -> (w: Write_Flush_Closer, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil || s.impl_close == nil {
- ok = false
- }
+ w = s
+ ok = query(s) >= {.Write, .Flush, .Close}
return
}
to_reader_at :: proc(s: Stream) -> (r: Reader_At, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read_at == nil {
- ok = false
- }
+ r = s
+ ok = query(s) >= {.Read_At}
return
}
to_writer_at :: proc(s: Stream) -> (w: Writer_At, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write_at == nil {
- ok = false
- }
- return
-}
-to_reader_from :: proc(s: Stream) -> (r: Reader_From, ok: bool = true) #optional_ok {
- r.stream = s
- if s.stream_vtable == nil || s.impl_read_from == nil {
- ok = false
- }
- return
-}
-to_writer_to :: proc(s: Stream) -> (w: Writer_To, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write_to == nil {
- ok = false
- }
+ w = s
+ ok = query(s) >= {.Write_At}
return
}
to_write_closer :: proc(s: Stream) -> (w: Write_Closer, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write == nil || s.impl_close == nil {
- ok = false
- }
+ w = s
+ ok = query(s) >= {.Write, .Close}
return
}
to_write_seeker :: proc(s: Stream) -> (w: Write_Seeker, ok: bool = true) #optional_ok {
- w.stream = s
- if s.stream_vtable == nil || s.impl_write == nil || s.impl_seek == nil {
- ok = false
- }
+ w = s
+ ok = query(s) >= {.Write, .Seek}
return
}
diff --git a/core/io/io.odin b/core/io/io.odin
index 7faa500b1..566e13c54 100644
--- a/core/io/io.odin
+++ b/core/io/io.odin
@@ -53,137 +53,106 @@ Error :: enum i32 {
Empty = -1,
}
-Close_Proc :: proc(using s: Stream) -> Error
-Flush_Proc :: proc(using s: Stream) -> Error
-Seek_Proc :: proc(using s: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
-Size_Proc :: proc(using s: Stream) -> i64
-Read_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error)
-Read_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error)
-Read_From_Proc :: proc(using s: Stream, r: Reader) -> (n: i64, err: Error)
-Read_Byte_Proc :: proc(using s: Stream) -> (byte, Error)
-Read_Rune_Proc :: proc(using s: Stream) -> (ch: rune, size: int, err: Error)
-Unread_Byte_Proc :: proc(using s: Stream) -> Error
-Unread_Rune_Proc :: proc(using s: Stream) -> Error
-Write_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error)
-Write_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error)
-Write_To_Proc :: proc(using s: Stream, w: Writer) -> (n: i64, err: Error)
-Write_Byte_Proc :: proc(using s: Stream, c: byte) -> Error
-Write_Rune_Proc :: proc(using s: Stream, r: rune) -> (size: int, err: Error)
-Destroy_Proc :: proc(using s: Stream) -> Error
-
-
-Stream :: struct {
- using stream_vtable: ^Stream_VTable,
- stream_data: rawptr,
+Stream_Mode :: enum {
+ Close,
+ Flush,
+ Read,
+ Read_At,
+ Write,
+ Write_At,
+ Seek,
+ Size,
+ Destroy,
+ Query, // query what modes are available
}
-Stream_VTable :: struct {
- impl_close: Close_Proc,
- impl_flush: Flush_Proc,
-
- impl_seek: Seek_Proc,
- impl_size: Size_Proc,
- impl_read: Read_Proc,
- impl_read_at: Read_At_Proc,
- impl_read_byte: Read_Byte_Proc,
- impl_read_rune: Read_Rune_Proc,
- impl_write_to: Write_To_Proc,
+Stream_Mode_Set :: distinct bit_set[Stream_Mode; i64]
- impl_write: Write_Proc,
- impl_write_at: Write_At_Proc,
- impl_write_byte: Write_Byte_Proc,
- impl_write_rune: Write_Rune_Proc,
- impl_read_from: Read_From_Proc,
+Stream_Proc :: #type proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
- impl_unread_byte: Unread_Byte_Proc,
- impl_unread_rune: Unread_Rune_Proc,
-
- impl_destroy: Destroy_Proc,
+Stream :: struct {
+ procedure: Stream_Proc,
+ data: rawptr,
}
+Reader :: Stream
+Writer :: Stream
+Closer :: Stream
+Flusher :: Stream
+Seeker :: Stream
-Reader :: struct {using stream: Stream}
-Writer :: struct {using stream: Stream}
-Closer :: struct {using stream: Stream}
-Flusher :: struct {using stream: Stream}
-Seeker :: struct {using stream: Stream}
-
-Read_Writer :: struct {using stream: Stream}
-Read_Closer :: struct {using stream: Stream}
-Read_Write_Closer :: struct {using stream: Stream}
-Read_Write_Seeker :: struct {using stream: Stream}
+Read_Writer :: Stream
+Read_Closer :: Stream
+Read_Write_Closer :: Stream
+Read_Write_Seeker :: Stream
-Write_Closer :: struct {using stream: Stream}
-Write_Seeker :: struct {using stream: Stream}
-Write_Flusher :: struct {using stream: Stream}
-Write_Flush_Closer :: struct {using stream: Stream}
+Write_Closer :: Stream
+Write_Seeker :: Stream
+Write_Flusher :: Stream
+Write_Flush_Closer :: Stream
-Reader_At :: struct {using stream: Stream}
-Writer_At :: struct {using stream: Stream}
-Reader_From :: struct {using stream: Stream}
-Writer_To :: struct {using stream: Stream}
+Reader_At :: Stream
+Writer_At :: Stream
-destroy :: proc(s: Stream) -> Error {
- close_err := close({s})
- if s.stream_vtable != nil && s.impl_destroy != nil {
- return s->impl_destroy()
+destroy :: proc(s: Stream) -> (err: Error) {
+ _ = flush(s)
+ _ = close(s)
+ if s.procedure != nil {
+ _, err = s.procedure(s.data, .Destroy, nil, 0, nil)
+ } else {
+ err = .Empty
}
- if close_err != .None {
- return close_err
+ return
+}
+
+query :: proc(s: Stream) -> (set: Stream_Mode_Set) {
+ if s.procedure != nil {
+ n, _ := s.procedure(s.data, .Query, nil, 0, nil)
+ set = transmute(Stream_Mode_Set)n
+ if set != nil {
+ set += {.Query}
+ }
}
- return .Empty
+ return
+}
+
+query_utility :: #force_inline proc "contextless" (set: Stream_Mode_Set) -> (n: i64, err: Error) {
+ return transmute(i64)set, nil
}
+_i64_err :: #force_inline proc "contextless" (n: int, err: Error) -> (i64, Error) {
+ return i64(n), err
+}
+
+
// read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred.
//
// When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of
// bytes read along with the error.
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
- if s.stream_vtable != nil {
- if s.impl_read != nil {
- n, err = s->impl_read(p)
- if n_read != nil {
- n_read^ += n
- }
- return
- } else if s.impl_read_byte != nil {
- bytes_read := 0
- defer if n_read != nil {
- n_read^ += bytes_read
- }
- for _, i in p {
- p[i] = s->impl_read_byte() or_return
- bytes_read += 1
- }
- return
- }
+ if s.procedure != nil {
+ n64: i64
+ n64, err = s.procedure(s.data, .Read, p, 0, nil)
+ n = int(n64)
+ if n_read != nil { n_read^ += n }
+ } else {
+ err = .Empty
}
- return 0, .Empty
+ return
}
// write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred.
write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
- if s.stream_vtable != nil {
- if s.impl_write != nil {
- n, err = s->impl_write(p)
- if n_written != nil {
- n_written^ += n
- }
- return
- } else if s.impl_write_byte != nil {
- bytes_written := 0
- defer if n_written != nil {
- n_written^ += bytes_written
- }
- for c in p {
- s->impl_write_byte(c) or_return
- bytes_written += 1
- }
- return
- }
+ if s.procedure != nil {
+ n64: i64
+ n64, err = s.procedure(s.data, .Write, p, 0, nil)
+ n = int(n64)
+ if n_written != nil { n_written^ += n }
+ } else {
+ err = .Empty
}
- return 0, .Empty
+ return
}
// seek sets the offset of the next read or write to offset.
@@ -194,57 +163,45 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro
//
// seek returns the new offset to the start of the file/stream, and any error if occurred.
seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
- if s.stream_vtable != nil && s.impl_seek != nil {
- return s->impl_seek(offset, whence)
+ if s.procedure != nil {
+ n, err = s.procedure(s.data, .Seek, nil, offset, whence)
+ } else {
+ err = .Empty
}
- return 0, .Empty
+ return
}
// The behaviour of close after the first call is stream implementation defined.
// Different streams may document their own behaviour.
-close :: proc(s: Closer) -> Error {
- if s.stream_vtable != nil && s.impl_close != nil {
- return s->impl_close()
+close :: proc(s: Closer) -> (err: Error) {
+ if s.procedure != nil {
+ _, err = s.procedure(s.data, .Close, nil, 0, nil)
}
- // Instead of .Empty, .None is fine in this case
- return .None
+ return
}
-flush :: proc(s: Flusher) -> Error {
- if s.stream_vtable != nil && s.impl_flush != nil {
- return s->impl_flush()
+flush :: proc(s: Flusher) -> (err: Error) {
+ if s.procedure != nil {
+ _, err = s.procedure(s.data, .Flush, nil, 0, nil)
}
- // Instead of .Empty, .None is fine in this case
- return .None
+ return
}
// size returns the size of the stream. If the stream does not support querying its size, 0 will be returned.
-size :: proc(s: Stream) -> i64 {
- if s.stream_vtable == nil {
- return 0
- }
- if s.impl_size != nil {
- return s->impl_size()
- }
- if s.impl_seek == nil {
- return 0
- }
-
- curr, end: i64
- err: Error
- if curr, err = s->impl_seek(0, .Current); err != nil {
- return 0
- }
-
- if end, err = s->impl_seek(0, .End); err != nil {
- return 0
- }
-
- if _, err = s->impl_seek(curr, .Start); err != nil {
- return 0
+size :: proc(s: Stream) -> (n: i64, err: Error) {
+ if s.procedure != nil {
+ n, err = s.procedure(s.data, .Size, nil, 0, nil)
+ if err == .Empty {
+ n = 0
+ curr := seek(s, 0, .Current) or_return
+ end := seek(s, 0, .End) or_return
+ seek(s, curr, .Start) or_return
+ n = end
+ }
+ } else {
+ err = .Empty
}
-
- return end
+ return
}
@@ -256,29 +213,24 @@ size :: proc(s: Stream) -> i64 {
//
// If n == len(p), err may be either nil or .EOF
read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
- defer if n_read != nil {
- n_read^ += n
- }
-
- if r.stream_vtable == nil {
- return 0, .Empty
- }
- if r.impl_read_at != nil {
- return r->impl_read_at(p, offset)
- }
- if r.impl_seek == nil || r.impl_read == nil {
- return 0, .Empty
- }
-
- curr_offset := r->impl_seek(offset, .Current) or_return
-
- n, err = r->impl_read(p)
- _, err1 := r->impl_seek(curr_offset, .Start)
- if err1 != nil && err == nil {
- err = err1
+ if r.procedure != nil {
+ n64: i64
+ n64, err = r.procedure(r.data, .Read_At, p, offset, nil)
+ if err != .Empty {
+ n = int(n64)
+ } else {
+ curr := seek(r, offset, .Current) or_return
+ n, err = read(r, p)
+ _, err1 := seek(r, curr, .Start)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ }
+ if n_read != nil { n_read^ += n }
+ } else {
+ err = .Empty
}
return
-
}
// write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
@@ -287,97 +239,39 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
// If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
// seek offset.
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
- defer if n_written != nil {
- n_written^ += n
- }
-
- if w.stream_vtable == nil {
- return 0, .Empty
- }
- if w.impl_write_at != nil {
- return w->impl_write_at(p, offset)
- }
- if w.impl_seek == nil || w.impl_write == nil {
- return 0, .Empty
- }
-
- curr_offset: i64
- curr_offset, err = w->impl_seek(offset, .Current)
- if err != nil {
- return 0, err
- }
-
- n, err = w->impl_write(p)
- _, err1 := w->impl_seek(curr_offset, .Start)
- if err1 != nil && err == nil {
- err = err1
+ if w.procedure != nil {
+ n64: i64
+ n64, err = w.procedure(w.data, .Write_At, p, offset, nil)
+ if err != .Empty {
+ n = int(n64)
+ } else {
+ curr := seek(w, offset, .Current) or_return
+ n, err = write(w, p)
+ _, err1 := seek(w, curr, .Start)
+ if err1 != nil && err == nil {
+ err = err1
+ }
+ }
+ if n_written != nil { n_written^ += n }
+ } else {
+ err = .Empty
}
return
}
-write_to :: proc(r: Writer_To, w: Writer) -> (n: i64, err: Error) {
- if r.stream_vtable == nil || w.stream_vtable == nil {
- return 0, .Empty
- }
- if r.impl_write_to != nil {
- return r->impl_write_to(w)
- }
- return 0, .Empty
-}
-read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
- if r.stream_vtable == nil || w.stream_vtable == nil {
- return 0, .Empty
- }
- if r.impl_read_from != nil {
- return w->impl_read_from(r)
- }
- return 0, .Empty
-}
-
-
// read_byte reads and returns the next byte from r.
read_byte :: proc(r: Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
- defer if err == nil && n_read != nil {
- n_read^ += 1
- }
-
- if r.stream_vtable == nil {
- return 0, .Empty
- }
- if r.impl_read_byte != nil {
- return r->impl_read_byte()
- }
- if r.impl_read == nil {
- return 0, .Empty
- }
-
buf: [1]byte
- _, err = r->impl_read(buf[:])
- return buf[0], err
+ _, err = read(r, buf[:], n_read)
+ b = buf[0]
+ return
}
write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> Error {
- return _write_byte(auto_cast w, c, n_written)
-}
-
-@(private)
-_write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> (err: Error) {
- defer if err == nil && n_written != nil {
- n_written^ += 1
- }
- if w.stream_vtable == nil {
- return .Empty
- }
- if w.impl_write_byte != nil {
- return w->impl_write_byte(c)
- }
- if w.impl_write == nil {
- return .Empty
- }
-
- b := [1]byte{c}
- _, err = w->impl_write(b[:])
- return err
+ buf: [1]byte
+ buf[0] = c
+ write(w, buf[:], n_written) or_return
+ return nil
}
// read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
@@ -385,19 +279,9 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
defer if err == nil && n_read != nil {
n_read^ += size
}
- if br.stream_vtable == nil {
- return 0, 0, .Empty
- }
- if br.impl_read_rune != nil {
- return br->impl_read_rune()
- }
- if br.impl_read == nil {
- return 0, 0, .Empty
- }
b: [utf8.UTF_MAX]byte
- _, err = br->impl_read(b[:1])
-
+ _, err = read(br, b[:1])
s0 := b[0]
ch = rune(s0)
@@ -415,7 +299,7 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
return
}
sz := int(x&7)
- size, err = br->impl_read(b[1:sz])
+ size, err = read(br, b[1:sz])
if err != nil || size+1 < sz {
ch = utf8.RUNE_ERROR
return
@@ -425,28 +309,6 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
return
}
-unread_byte :: proc(s: Stream) -> Error {
- if s.stream_vtable == nil {
- return .Empty
- }
- if s.impl_unread_byte != nil {
- return s->impl_unread_byte()
- }
- if s.impl_seek != nil {
- _, err := s->impl_seek(-1, .Current)
- return err
- }
-
- return .Empty
-}
-unread_rune :: proc(s: Writer) -> Error {
- if s.stream_vtable != nil && s.impl_unread_rune != nil {
- return s->impl_unread_rune()
- }
- return .Empty
-}
-
-
// write_string writes the contents of the string s to w.
write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
return write(s, transmute([]byte)str, n_written)
@@ -457,14 +319,6 @@ write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err
defer if err == nil && n_written != nil {
n_written^ += size
}
-
- if s.stream_vtable == nil {
- return 0, .Empty
- }
- if s.impl_write_rune != nil {
- return s->impl_write_rune(r)
- }
-
if r < utf8.RUNE_SELF {
err = write_byte(s, byte(r))
if err == nil {
@@ -542,21 +396,15 @@ copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) {
@(private)
_copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
- if dst.stream_vtable == nil || src.stream_vtable == nil {
+ if dst.procedure == nil || src.procedure == nil {
return 0, .Empty
}
- if src.impl_write_to != nil {
- return src->impl_write_to(dst)
- }
- if src.impl_read_from != nil {
- return dst->impl_read_from(src)
- }
buf := buf
if buf == nil {
DEFAULT_SIZE :: 4 * 1024
size := DEFAULT_SIZE
- if src.stream_vtable == _limited_reader_vtable {
- l := (^Limited_Reader)(src.stream_data)
+ if src.procedure == _limited_reader_proc {
+ l := (^Limited_Reader)(src.data)
if i64(size) > l.n {
if l.n < 1 {
size = 1
diff --git a/core/io/multi.odin b/core/io/multi.odin
index 64c533e37..e85114a7a 100644
--- a/core/io/multi.odin
+++ b/core/io/multi.odin
@@ -5,33 +5,37 @@ Multi_Reader :: struct {
}
@(private)
-_multi_reader_vtable := &Stream_VTable{
- impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
- mr := (^Multi_Reader)(s.stream_data)
- for len(mr.readers) > 0 {
- r := mr.readers[0]
- n, err = read(r, p)
- if err == .EOF {
- ordered_remove(&mr.readers, 0)
- }
- if n > 0 || err != .EOF {
- if err == .EOF && len(mr.readers) > 0 {
- // Don't return EOF yet, more readers remain
- err = nil
- }
- return
+_multi_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
+ if mode == .Query {
+ return query_utility({.Read, .Query})
+ } else if mode != .Read {
+ return 0, .Empty
+ }
+ mr := (^Multi_Reader)(stream_data)
+ for len(mr.readers) > 0 {
+ r := mr.readers[0]
+ n, err = _i64_err(read(r, p))
+ if err == .EOF {
+ ordered_remove(&mr.readers, 0)
+ }
+ if n > 0 || err != .EOF {
+ if err == .EOF && len(mr.readers) > 0 {
+ // Don't return EOF yet, more readers remain
+ err = nil
}
+ return
}
- return 0, .EOF
- },
+ }
+ return 0, .EOF
}
+
multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := context.allocator) -> (r: Reader) {
all_readers := make([dynamic]Reader, 0, len(readers), allocator)
for w in readers {
- if w.stream_vtable == _multi_reader_vtable {
- other := (^Multi_Reader)(w.stream_data)
+ if w.procedure == _multi_reader_proc {
+ other := (^Multi_Reader)(w.data)
append(&all_readers, ..other.readers[:])
} else {
append(&all_readers, w)
@@ -40,8 +44,8 @@ multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := con
mr.readers = all_readers
- r.stream_vtable = _multi_reader_vtable
- r.stream_data = mr
+ r.procedure = _multi_reader_proc
+ r.data = mr
return
}
@@ -55,38 +59,42 @@ Multi_Writer :: struct {
}
@(private)
-_multi_writer_vtable := &Stream_VTable{
- impl_write = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
- mw := (^Multi_Writer)(s.stream_data)
- for w in mw.writers {
- n, err = write(w, p)
- if err != nil {
- return
- }
- if n != len(p) {
- err = .Short_Write
- return
- }
+_multi_writer_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
+ if mode == .Query {
+ return query_utility({.Write, .Query})
+ } else if mode != .Write {
+ return 0, .Empty
+ }
+ mw := (^Multi_Writer)(stream_data)
+ for w in mw.writers {
+ n, err = _i64_err(write(w, p))
+ if err != nil {
+ return
+ }
+ if n != i64(len(p)) {
+ err = .Short_Write
+ return
}
+ }
- return len(p), nil
- },
+ return i64(len(p)), nil
}
+
multi_writer_init :: proc(mw: ^Multi_Writer, writers: ..Writer, allocator := context.allocator) -> (out: Writer) {
mw.writers = make([dynamic]Writer, 0, len(writers), allocator)
for w in writers {
- if w.stream_vtable == _multi_writer_vtable {
- other := (^Multi_Writer)(w.stream_data)
+ if w.procedure == _multi_writer_proc {
+ other := (^Multi_Writer)(w.data)
append(&mw.writers, ..other.writers[:])
} else {
append(&mw.writers, w)
}
}
- out.stream_vtable = _multi_writer_vtable
- out.stream_data = mw
+ out.procedure = _multi_writer_proc
+ out.data = mw
return
}
diff --git a/core/io/util.odin b/core/io/util.odin
index cfd7d3608..c77d0be9d 100644
--- a/core/io/util.odin
+++ b/core/io/util.odin
@@ -292,17 +292,21 @@ Tee_Reader :: struct {
}
@(private)
-_tee_reader_vtable := &Stream_VTable{
- impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
- t := (^Tee_Reader)(s.stream_data)
- n, err = read(t.r, p)
+_tee_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
+ t := (^Tee_Reader)(stream_data)
+ #partial switch mode {
+ case .Read:
+ n, err = _i64_err(read(t.r, p))
if n > 0 {
if wn, werr := write(t.w, p[:n]); werr != nil {
- return wn, werr
+ return i64(wn), werr
}
}
return
- },
+ case .Query:
+ return query_utility({.Read, .Query})
+ }
+ return 0, .Empty
}
// tee_reader_init returns a Reader that writes to 'w' what it reads from 'r'
@@ -317,8 +321,8 @@ tee_reader_init :: proc(t: ^Tee_Reader, r: Reader, w: Writer, allocator := conte
}
tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) {
- r.stream_data = t
- r.stream_vtable = _tee_reader_vtable
+ r.data = t
+ r.procedure = _tee_reader_proc
return
}
@@ -332,9 +336,10 @@ Limited_Reader :: struct {
}
@(private)
-_limited_reader_vtable := &Stream_VTable{
- impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
- l := (^Limited_Reader)(s.stream_data)
+_limited_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
+ l := (^Limited_Reader)(stream_data)
+ #partial switch mode {
+ case .Read:
if l.n <= 0 {
return 0, .EOF
}
@@ -342,10 +347,13 @@ _limited_reader_vtable := &Stream_VTable{
if i64(len(p)) > l.n {
p = p[0:l.n]
}
- n, err = read(l.r, p)
+ n, err = _i64_err(read(l.r, p))
l.n -= i64(n)
return
- },
+ case .Query:
+ return query_utility({.Read, .Query})
+ }
+ return 0, .Empty
}
limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
@@ -355,8 +363,8 @@ limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
}
limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) {
- r.stream_vtable = _limited_reader_vtable
- r.stream_data = l
+ r.procedure = _limited_reader_proc
+ r.data = l
return
}
@@ -375,15 +383,16 @@ section_reader_init :: proc(s: ^Section_Reader, r: Reader_At, off: i64, n: i64)
return
}
section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) {
- out.stream_data = s
- out.stream_vtable = _section_reader_vtable
+ out.data = s
+ out.procedure = _section_reader_proc
return
}
@(private)
-_section_reader_vtable := &Stream_VTable{
- impl_read = proc(stream: Stream, p: []byte) -> (n: int, err: Error) {
- s := (^Section_Reader)(stream.stream_data)
+_section_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
+ s := (^Section_Reader)(stream_data)
+ #partial switch mode {
+ case .Read:
if s.off >= s.limit {
return 0, .EOF
}
@@ -391,13 +400,11 @@ _section_reader_vtable := &Stream_VTable{
if max := s.limit - s.off; i64(len(p)) > max {
p = p[0:max]
}
- n, err = read_at(s.r, p, s.off)
+ n, err = _i64_err(read_at(s.r, p, s.off))
s.off += i64(n)
return
- },
- impl_read_at = proc(stream: Stream, p: []byte, off: i64) -> (n: int, err: Error) {
- s := (^Section_Reader)(stream.stream_data)
- p, off := p, off
+ case .Read_At:
+ p, off := p, offset
if off < 0 || off >= s.limit - s.base {
return 0, .EOF
@@ -405,17 +412,15 @@ _section_reader_vtable := &Stream_VTable{
off += s.base
if max := s.limit - off; i64(len(p)) > max {
p = p[0:max]
- n, err = read_at(s.r, p, off)
+ n, err = _i64_err(read_at(s.r, p, off))
if err == nil {
err = .EOF
}
return
}
- return read_at(s.r, p, off)
- },
- impl_seek = proc(stream: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
- s := (^Section_Reader)(stream.stream_data)
+ return _i64_err(read_at(s.r, p, off))
+ case .Seek:
offset := offset
switch whence {
case:
@@ -433,10 +438,12 @@ _section_reader_vtable := &Stream_VTable{
s.off = offset
n = offset - s.base
return
- },
- impl_size = proc(stream: Stream) -> i64 {
- s := (^Section_Reader)(stream.stream_data)
- return s.limit - s.base
- },
-}
+ case .Size:
+ n = s.limit - s.base
+ return
+ case .Query:
+ return query_utility({.Read, .Read_At, .Seek, .Size, .Query})
+ }
+ return 0, nil
+}
diff --git a/core/log/log.odin b/core/log/log.odin
index a699247b8..f3554791b 100644
--- a/core/log/log.odin
+++ b/core/log/log.odin
@@ -76,43 +76,43 @@ nil_logger :: proc() -> Logger {
}
debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
- logf(level=.Debug, fmt_str=fmt_str, args=args, location=location)
+ logf(.Debug, fmt_str, ..args, location=location)
}
infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
- logf(level=.Info, fmt_str=fmt_str, args=args, location=location)
+ logf(.Info, fmt_str, ..args, location=location)
}
warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
- logf(level=.Warning, fmt_str=fmt_str, args=args, location=location)
+ logf(.Warning, fmt_str, ..args, location=location)
}
errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
- logf(level=.Error, fmt_str=fmt_str, args=args, location=location)
+ logf(.Error, fmt_str, ..args, location=location)
}
fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
- logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location)
+ logf(.Fatal, fmt_str, ..args, location=location)
}
debug :: proc(args: ..any, sep := " ", location := #caller_location) {
- log(level=.Debug, args=args, sep=sep, location=location)
+ log(.Debug, ..args, sep=sep, location=location)
}
info :: proc(args: ..any, sep := " ", location := #caller_location) {
- log(level=.Info, args=args, sep=sep, location=location)
+ log(.Info, ..args, sep=sep, location=location)
}
warn :: proc(args: ..any, sep := " ", location := #caller_location) {
- log(level=.Warning, args=args, sep=sep, location=location)
+ log(.Warning, ..args, sep=sep, location=location)
}
error :: proc(args: ..any, sep := " ", location := #caller_location) {
- log(level=.Error, args=args, sep=sep, location=location)
+ log(.Error, ..args, sep=sep, location=location)
}
fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
- log(level=.Fatal, args=args, sep=sep, location=location)
+ log(.Fatal, ..args, sep=sep, location=location)
}
panic :: proc(args: ..any, location := #caller_location) -> ! {
- log(level=.Fatal, args=args, location=location)
+ log(.Fatal, ..args, location=location)
runtime.panic("log.panic", location)
}
panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
- logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location)
+ logf(.Fatal, fmt_str, ..args, location=location)
runtime.panic("log.panicf", location)
}
@@ -127,7 +127,7 @@ log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location)
if level < logger.lowest_level {
return
}
- str := fmt.tprint(args=args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
+ str := fmt.tprint(..args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
logger.procedure(logger.data, level, str, logger.options, location)
}
diff --git a/core/log/log_allocator.odin b/core/log/log_allocator.odin
index f4d1841db..934f0d643 100644
--- a/core/log/log_allocator.odin
+++ b/core/log/log_allocator.odin
@@ -38,60 +38,60 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
switch mode {
case .Alloc:
logf(
- level=la.level,
- fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)",
- args = {la.prefix, padding, size, alignment},
+ la.level,
+ "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)",
+ la.prefix, padding, size, alignment,
location = location,
)
case .Alloc_Non_Zeroed:
logf(
- level=la.level,
- fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)",
- args = {la.prefix, padding, size, alignment},
+ la.level,
+ "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)",
+ la.prefix, padding, size, alignment,
location = location,
)
case .Free:
if old_size != 0 {
logf(
- level=la.level,
- fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)",
- args = {la.prefix, padding, old_memory, old_size},
+ la.level,
+ "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)",
+ la.prefix, padding, old_memory, old_size,
location = location,
)
} else {
logf(
- level=la.level,
- fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)",
- args = {la.prefix, padding, old_memory},
+ la.level,
+ "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)",
+ la.prefix, padding, old_memory,
location = location,
)
}
case .Free_All:
logf(
- level=la.level,
- fmt_str = "%s%s<<< ALLOCATOR(mode=.Free_All)",
- args = {la.prefix, padding},
+ la.level,
+ "%s%s<<< ALLOCATOR(mode=.Free_All)",
+ la.prefix, padding,
location = location,
)
case .Resize:
logf(
- level=la.level,
- fmt_str = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)",
- args = {la.prefix, padding, old_memory, old_size, size, alignment},
+ la.level,
+ "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)",
+ la.prefix, padding, old_memory, old_size, size, alignment,
location = location,
)
case .Query_Features:
logf(
- level=la.level,
- fmt_str = "%s%ALLOCATOR(mode=.Query_Features)",
- args = {la.prefix, padding},
+ la.level,
+ "%s%ALLOCATOR(mode=.Query_Features)",
+ la.prefix, padding,
location = location,
)
case .Query_Info:
logf(
- level=la.level,
- fmt_str = "%s%ALLOCATOR(mode=.Query_Info)",
- args = {la.prefix, padding},
+ la.level,
+ "%s%ALLOCATOR(mode=.Query_Info)",
+ la.prefix, padding,
location = location,
)
}
@@ -103,9 +103,9 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
defer la.locked = false
if err != nil {
logf(
- level=la.level,
- fmt_str = "%s%ALLOCATOR ERROR=%v",
- args = {la.prefix, padding, error},
+ la.level,
+ "%s%ALLOCATOR ERROR=%v",
+ la.prefix, padding, error,
location = location,
)
}
diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin
index 6c4b5dd01..a4313a244 100644
--- a/core/math/big/helpers.odin
+++ b/core/math/big/helpers.odin
@@ -19,7 +19,7 @@ import rnd "core:math/rand"
int_destroy :: proc(integers: ..^Int) {
integers := integers
- for a in &integers {
+ for a in integers {
assert_if_nil(a)
}
#force_inline internal_int_destroy(..integers)
@@ -408,7 +408,7 @@ clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocato
args := args
assert_if_nil(..args)
- for i in &args {
+ for i in args {
#force_inline internal_clear_if_uninitialized_single(i, allocator) or_return
}
return err
@@ -435,7 +435,7 @@ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err
assert_if_nil(..integers)
integers := integers
- for a in &integers {
+ for a in integers {
#force_inline internal_clear(a, true, allocator) or_return
}
return nil
diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin
index 13aa96bef..968a26f8f 100644
--- a/core/math/big/internal.odin
+++ b/core/math/big/internal.odin
@@ -1857,7 +1857,7 @@ internal_root_n :: proc { internal_int_root_n, }
internal_int_destroy :: proc(integers: ..^Int) {
integers := integers
- for a in &integers {
+ for &a in integers {
if internal_int_allocated_cap(a) > 0 {
mem.zero_slice(a.digit[:])
free(&a.digit[0])
@@ -2909,7 +2909,7 @@ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator
context.allocator = allocator
integers := integers
- for a in &integers {
+ for a in integers {
internal_clear(a) or_return
}
return nil
diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin
index 2b758dc35..d15ce0e98 100644
--- a/core/math/big/radix.odin
+++ b/core/math/big/radix.odin
@@ -429,7 +429,7 @@ internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(
len = l,
}
- ok := os.write_entire_file(name=filename, data=data, truncate=true)
+ ok := os.write_entire_file(filename, data, truncate=true)
return nil if ok else .Cannot_Write_File
}
diff --git a/core/math/big/rat.odin b/core/math/big/rat.odin
index c3efc30aa..35618affb 100644
--- a/core/math/big/rat.odin
+++ b/core/math/big/rat.odin
@@ -137,7 +137,7 @@ rat_copy :: proc(dst, src: ^Rat, minimize := false, allocator := context.allocat
internal_rat_destroy :: proc(rationals: ..^Rat) {
rationals := rationals
- for z in &rationals {
+ for &z in rationals {
internal_int_destroy(&z.a, &z.b)
}
}
diff --git a/core/math/cmplx/cmplx.odin b/core/math/cmplx/cmplx.odin
new file mode 100644
index 000000000..c029be30c
--- /dev/null
+++ b/core/math/cmplx/cmplx.odin
@@ -0,0 +1,513 @@
+package math_cmplx
+
+import "core:builtin"
+import "core:math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+
+abs :: builtin.abs
+conj :: builtin.conj
+real :: builtin.real
+imag :: builtin.imag
+jmag :: builtin.jmag
+kmag :: builtin.kmag
+
+
+sin :: proc{
+ sin_complex128,
+}
+cos :: proc{
+ cos_complex128,
+}
+tan :: proc{
+ tan_complex128,
+}
+cot :: proc{
+ cot_complex128,
+}
+
+
+sinh :: proc{
+ sinh_complex128,
+}
+cosh :: proc{
+ cosh_complex128,
+}
+tanh :: proc{
+ tanh_complex128,
+}
+
+
+
+// sqrt returns the square root of x.
+// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x).
+sqrt :: proc{
+ sqrt_complex32,
+ sqrt_complex64,
+ sqrt_complex128,
+}
+ln :: proc{
+ ln_complex32,
+ ln_complex64,
+ ln_complex128,
+}
+log10 :: proc{
+ log10_complex32,
+ log10_complex64,
+ log10_complex128,
+}
+
+exp :: proc{
+ exp_complex32,
+ exp_complex64,
+ exp_complex128,
+}
+
+pow :: proc{
+ pow_complex32,
+ pow_complex64,
+ pow_complex128,
+}
+
+phase :: proc{
+ phase_complex32,
+ phase_complex64,
+ phase_complex128,
+}
+
+polar :: proc{
+ polar_complex32,
+ polar_complex64,
+ polar_complex128,
+}
+
+is_inf :: proc{
+ is_inf_complex32,
+ is_inf_complex64,
+ is_inf_complex128,
+}
+
+is_nan :: proc{
+ is_nan_complex32,
+ is_nan_complex64,
+ is_nan_complex128,
+}
+
+
+
+// sqrt_complex32 returns the square root of x.
+// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x).
+sqrt_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return complex32(sqrt_complex128(complex128(x)))
+}
+
+// sqrt_complex64 returns the square root of x.
+// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x).
+sqrt_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return complex64(sqrt_complex128(complex128(x)))
+}
+
+
+// sqrt_complex128 returns the square root of x.
+// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x).
+sqrt_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // The original C code, the long comment, and the constants
+ // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+ // The go code is a simplified version of the original C.
+ //
+ // Cephes Math Library Release 2.8: June, 2000
+ // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+ //
+ // The readme file at http://netlib.sandia.gov/cephes/ says:
+ // Some software in this archive may be from the book _Methods and
+ // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+ // International, 1989) or from the Cephes Mathematical Library, a
+ // commercial product. In either event, it is copyrighted by the author.
+ // What you see here may be used freely but it comes with no support or
+ // guarantee.
+ //
+ // The two known misprints in the book are repaired here in the
+ // source listings for the gamma function and the incomplete beta
+ // integral.
+ //
+ // Stephen L. Moshier
+ // moshier@na-net.ornl.gov
+
+ // Complex square root
+ //
+ // DESCRIPTION:
+ //
+ // If z = x + iy, r = |z|, then
+ //
+ // 1/2
+ // Re w = [ (r + x)/2 ] ,
+ //
+ // 1/2
+ // Im w = [ (r - x)/2 ] .
+ //
+ // Cancellation error in r-x or r+x is avoided by using the
+ // identity 2 Re w Im w = y.
+ //
+ // Note that -w is also a square root of z. The root chosen
+ // is always in the right half plane and Im w has the same sign as y.
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // DEC -10,+10 25000 3.2e-17 9.6e-18
+ // IEEE -10,+10 1,000,000 2.9e-16 6.1e-17
+
+ if imag(x) == 0 {
+ // Ensure that imag(r) has the same sign as imag(x) for imag(x) == signed zero.
+ if real(x) == 0 {
+ return complex(0, imag(x))
+ }
+ if real(x) < 0 {
+ return complex(0, math.copy_sign(math.sqrt(-real(x)), imag(x)))
+ }
+ return complex(math.sqrt(real(x)), imag(x))
+ } else if math.is_inf(imag(x), 0) {
+ return complex(math.inf_f64(1.0), imag(x))
+ }
+ if real(x) == 0 {
+ if imag(x) < 0 {
+ r := math.sqrt(-0.5 * imag(x))
+ return complex(r, -r)
+ }
+ r := math.sqrt(0.5 * imag(x))
+ return complex(r, r)
+ }
+ a := real(x)
+ b := imag(x)
+ scale: f64
+ // Rescale to avoid internal overflow or underflow.
+ if abs(a) > 4 || abs(b) > 4 {
+ a *= 0.25
+ b *= 0.25
+ scale = 2
+ } else {
+ a *= 1.8014398509481984e16 // 2**54
+ b *= 1.8014398509481984e16
+ scale = 7.450580596923828125e-9 // 2**-27
+ }
+ r := math.hypot(a, b)
+ t: f64
+ if a > 0 {
+ t = math.sqrt(0.5*r + 0.5*a)
+ r = scale * abs((0.5*b)/t)
+ t *= scale
+ } else {
+ r = math.sqrt(0.5*r - 0.5*a)
+ t = scale * abs((0.5*b)/r)
+ r *= scale
+ }
+ if b < 0 {
+ return complex(t, -r)
+ }
+ return complex(t, r)
+}
+
+ln_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return complex(math.ln(abs(x)), phase(x))
+}
+ln_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return complex(math.ln(abs(x)), phase(x))
+}
+ln_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ return complex(math.ln(abs(x)), phase(x))
+}
+
+
+exp_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ switch re, im := real(x), imag(x); {
+ case math.is_inf(re, 0):
+ switch {
+ case re > 0 && im == 0:
+ return x
+ case math.is_inf(im, 0) || math.is_nan(im):
+ if re < 0 {
+ return complex(0, math.copy_sign(0, im))
+ } else {
+ return complex(math.inf_f64(1.0), math.nan_f64())
+ }
+ }
+ case math.is_nan(re):
+ if im == 0 {
+ return complex(math.nan_f16(), im)
+ }
+ }
+ r := math.exp(real(x))
+ s, c := math.sincos(imag(x))
+ return complex(r*c, r*s)
+}
+exp_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ switch re, im := real(x), imag(x); {
+ case math.is_inf(re, 0):
+ switch {
+ case re > 0 && im == 0:
+ return x
+ case math.is_inf(im, 0) || math.is_nan(im):
+ if re < 0 {
+ return complex(0, math.copy_sign(0, im))
+ } else {
+ return complex(math.inf_f64(1.0), math.nan_f64())
+ }
+ }
+ case math.is_nan(re):
+ if im == 0 {
+ return complex(math.nan_f32(), im)
+ }
+ }
+ r := math.exp(real(x))
+ s, c := math.sincos(imag(x))
+ return complex(r*c, r*s)
+}
+exp_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ switch re, im := real(x), imag(x); {
+ case math.is_inf(re, 0):
+ switch {
+ case re > 0 && im == 0:
+ return x
+ case math.is_inf(im, 0) || math.is_nan(im):
+ if re < 0 {
+ return complex(0, math.copy_sign(0, im))
+ } else {
+ return complex(math.inf_f64(1.0), math.nan_f64())
+ }
+ }
+ case math.is_nan(re):
+ if im == 0 {
+ return complex(math.nan_f64(), im)
+ }
+ }
+ r := math.exp(real(x))
+ s, c := math.sincos(imag(x))
+ return complex(r*c, r*s)
+}
+
+
+pow_complex32 :: proc "contextless" (x, y: complex32) -> complex32 {
+ if x == 0 { // Guaranteed also true for x == -0.
+ if is_nan(y) {
+ return nan_complex32()
+ }
+ r, i := real(y), imag(y)
+ switch {
+ case r == 0:
+ return 1
+ case r < 0:
+ if i == 0 {
+ return complex(math.inf_f16(1), 0)
+ }
+ return inf_complex32()
+ case r > 0:
+ return 0
+ }
+ unreachable()
+ }
+ modulus := abs(x)
+ if modulus == 0 {
+ return complex(0, 0)
+ }
+ r := math.pow(modulus, real(y))
+ arg := phase(x)
+ theta := real(y) * arg
+ if imag(y) != 0 {
+ r *= math.exp(-imag(y) * arg)
+ theta += imag(y) * math.ln(modulus)
+ }
+ s, c := math.sincos(theta)
+ return complex(r*c, r*s)
+}
+pow_complex64 :: proc "contextless" (x, y: complex64) -> complex64 {
+ if x == 0 { // Guaranteed also true for x == -0.
+ if is_nan(y) {
+ return nan_complex64()
+ }
+ r, i := real(y), imag(y)
+ switch {
+ case r == 0:
+ return 1
+ case r < 0:
+ if i == 0 {
+ return complex(math.inf_f32(1), 0)
+ }
+ return inf_complex64()
+ case r > 0:
+ return 0
+ }
+ unreachable()
+ }
+ modulus := abs(x)
+ if modulus == 0 {
+ return complex(0, 0)
+ }
+ r := math.pow(modulus, real(y))
+ arg := phase(x)
+ theta := real(y) * arg
+ if imag(y) != 0 {
+ r *= math.exp(-imag(y) * arg)
+ theta += imag(y) * math.ln(modulus)
+ }
+ s, c := math.sincos(theta)
+ return complex(r*c, r*s)
+}
+pow_complex128 :: proc "contextless" (x, y: complex128) -> complex128 {
+ if x == 0 { // Guaranteed also true for x == -0.
+ if is_nan(y) {
+ return nan_complex128()
+ }
+ r, i := real(y), imag(y)
+ switch {
+ case r == 0:
+ return 1
+ case r < 0:
+ if i == 0 {
+ return complex(math.inf_f64(1), 0)
+ }
+ return inf_complex128()
+ case r > 0:
+ return 0
+ }
+ unreachable()
+ }
+ modulus := abs(x)
+ if modulus == 0 {
+ return complex(0, 0)
+ }
+ r := math.pow(modulus, real(y))
+ arg := phase(x)
+ theta := real(y) * arg
+ if imag(y) != 0 {
+ r *= math.exp(-imag(y) * arg)
+ theta += imag(y) * math.ln(modulus)
+ }
+ s, c := math.sincos(theta)
+ return complex(r*c, r*s)
+}
+
+
+
+log10_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return math.LN10*ln(x)
+}
+log10_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return math.LN10*ln(x)
+}
+log10_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ return math.LN10*ln(x)
+}
+
+
+phase_complex32 :: proc "contextless" (x: complex32) -> f16 {
+ return math.atan2(imag(x), real(x))
+}
+phase_complex64 :: proc "contextless" (x: complex64) -> f32 {
+ return math.atan2(imag(x), real(x))
+}
+phase_complex128 :: proc "contextless" (x: complex128) -> f64 {
+ return math.atan2(imag(x), real(x))
+}
+
+
+rect_complex32 :: proc "contextless" (r, θ: f16) -> complex32 {
+ s, c := math.sincos(θ)
+ return complex(r*c, r*s)
+}
+rect_complex64 :: proc "contextless" (r, θ: f32) -> complex64 {
+ s, c := math.sincos(θ)
+ return complex(r*c, r*s)
+}
+rect_complex128 :: proc "contextless" (r, θ: f64) -> complex128 {
+ s, c := math.sincos(θ)
+ return complex(r*c, r*s)
+}
+
+polar_complex32 :: proc "contextless" (x: complex32) -> (r, θ: f16) {
+ return abs(x), phase(x)
+}
+polar_complex64 :: proc "contextless" (x: complex64) -> (r, θ: f32) {
+ return abs(x), phase(x)
+}
+polar_complex128 :: proc "contextless" (x: complex128) -> (r, θ: f64) {
+ return abs(x), phase(x)
+}
+
+
+
+
+nan_complex32 :: proc "contextless" () -> complex32 {
+ return complex(math.nan_f16(), math.nan_f16())
+}
+nan_complex64 :: proc "contextless" () -> complex64 {
+ return complex(math.nan_f32(), math.nan_f32())
+}
+nan_complex128 :: proc "contextless" () -> complex128 {
+ return complex(math.nan_f64(), math.nan_f64())
+}
+
+
+inf_complex32 :: proc "contextless" () -> complex32 {
+ inf := math.inf_f16(1)
+ return complex(inf, inf)
+}
+inf_complex64 :: proc "contextless" () -> complex64 {
+ inf := math.inf_f32(1)
+ return complex(inf, inf)
+}
+inf_complex128 :: proc "contextless" () -> complex128 {
+ inf := math.inf_f64(1)
+ return complex(inf, inf)
+}
+
+
+is_inf_complex32 :: proc "contextless" (x: complex32) -> bool {
+ return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
+}
+is_inf_complex64 :: proc "contextless" (x: complex64) -> bool {
+ return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
+}
+is_inf_complex128 :: proc "contextless" (x: complex128) -> bool {
+ return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
+}
+
+
+is_nan_complex32 :: proc "contextless" (x: complex32) -> bool {
+ if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
+ return false
+ }
+ return math.is_nan(real(x)) || math.is_nan(imag(x))
+}
+is_nan_complex64 :: proc "contextless" (x: complex64) -> bool {
+ if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
+ return false
+ }
+ return math.is_nan(real(x)) || math.is_nan(imag(x))
+}
+is_nan_complex128 :: proc "contextless" (x: complex128) -> bool {
+ if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
+ return false
+ }
+ return math.is_nan(real(x)) || math.is_nan(imag(x))
+}
diff --git a/core/math/cmplx/cmplx_invtrig.odin b/core/math/cmplx/cmplx_invtrig.odin
new file mode 100644
index 000000000..a746a370f
--- /dev/null
+++ b/core/math/cmplx/cmplx_invtrig.odin
@@ -0,0 +1,273 @@
+package math_cmplx
+
+import "core:builtin"
+import "core:math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+
+acos :: proc{
+ acos_complex32,
+ acos_complex64,
+ acos_complex128,
+}
+acosh :: proc{
+ acosh_complex32,
+ acosh_complex64,
+ acosh_complex128,
+}
+
+asin :: proc{
+ asin_complex32,
+ asin_complex64,
+ asin_complex128,
+}
+asinh :: proc{
+ asinh_complex32,
+ asinh_complex64,
+ asinh_complex128,
+}
+
+atan :: proc{
+ atan_complex32,
+ atan_complex64,
+ atan_complex128,
+}
+
+atanh :: proc{
+ atanh_complex32,
+ atanh_complex64,
+ atanh_complex128,
+}
+
+
+acos_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ w := asin(x)
+ return complex(math.PI/2 - real(w), -imag(w))
+}
+acos_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ w := asin(x)
+ return complex(math.PI/2 - real(w), -imag(w))
+}
+acos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ w := asin(x)
+ return complex(math.PI/2 - real(w), -imag(w))
+}
+
+
+acosh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ if x == 0 {
+ return complex(0, math.copy_sign(math.PI/2, imag(x)))
+ }
+ w := acos(x)
+ if imag(w) <= 0 {
+ return complex(-imag(w), real(w))
+ }
+ return complex(imag(w), -real(w))
+}
+acosh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ if x == 0 {
+ return complex(0, math.copy_sign(math.PI/2, imag(x)))
+ }
+ w := acos(x)
+ if imag(w) <= 0 {
+ return complex(-imag(w), real(w))
+ }
+ return complex(imag(w), -real(w))
+}
+acosh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ if x == 0 {
+ return complex(0, math.copy_sign(math.PI/2, imag(x)))
+ }
+ w := acos(x)
+ if imag(w) <= 0 {
+ return complex(-imag(w), real(w))
+ }
+ return complex(imag(w), -real(w))
+}
+
+asin_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return complex32(asin_complex128(complex128(x)))
+}
+asin_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return complex64(asin_complex128(complex128(x)))
+}
+asin_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ switch re, im := real(x), imag(x); {
+ case im == 0 && abs(re) <= 1:
+ return complex(math.asin(re), im)
+ case re == 0 && abs(im) <= 1:
+ return complex(re, math.asinh(im))
+ case math.is_nan(im):
+ switch {
+ case re == 0:
+ return complex(re, math.nan_f64())
+ case math.is_inf(re, 0):
+ return complex(math.nan_f64(), re)
+ case:
+ return nan_complex128()
+ }
+ case math.is_inf(im, 0):
+ switch {
+ case math.is_nan(re):
+ return x
+ case math.is_inf(re, 0):
+ return complex(math.copy_sign(math.PI/4, re), im)
+ case:
+ return complex(math.copy_sign(0, re), im)
+ }
+ case math.is_inf(re, 0):
+ return complex(math.copy_sign(math.PI/2, re), math.copy_sign(re, im))
+ }
+ ct := complex(-imag(x), real(x)) // i * x
+ xx := x * x
+ x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
+ x2 := sqrt(x1) // x2 = sqrt(1 - x*x)
+ w := ln(ct + x2)
+ return complex(imag(w), -real(w)) // -i * w
+}
+
+asinh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return complex32(asinh_complex128(complex128(x)))
+}
+asinh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return complex64(asinh_complex128(complex128(x)))
+}
+asinh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ switch re, im := real(x), imag(x); {
+ case im == 0 && abs(re) <= 1:
+ return complex(math.asinh(re), im)
+ case re == 0 && abs(im) <= 1:
+ return complex(re, math.asin(im))
+ case math.is_inf(re, 0):
+ switch {
+ case math.is_inf(im, 0):
+ return complex(re, math.copy_sign(math.PI/4, im))
+ case math.is_nan(im):
+ return x
+ case:
+ return complex(re, math.copy_sign(0.0, im))
+ }
+ case math.is_nan(re):
+ switch {
+ case im == 0:
+ return x
+ case math.is_inf(im, 0):
+ return complex(im, re)
+ case:
+ return nan_complex128()
+ }
+ case math.is_inf(im, 0):
+ return complex(math.copy_sign(im, re), math.copy_sign(math.PI/2, im))
+ }
+ xx := x * x
+ x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
+ return ln(x + sqrt(x1)) // log(x + sqrt(1 + x*x))
+}
+
+
+atan_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ return complex32(atan_complex128(complex128(x)))
+}
+atan_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ return complex64(atan_complex128(complex128(x)))
+}
+atan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex circular arc tangent
+ //
+ // DESCRIPTION:
+ //
+ // If
+ // z = x + iy,
+ //
+ // then
+ // 1 ( 2x )
+ // Re w = - arctan(-----------) + k PI
+ // 2 ( 2 2)
+ // (1 - x - y )
+ //
+ // ( 2 2)
+ // 1 (x + (y+1) )
+ // Im w = - log(------------)
+ // 4 ( 2 2)
+ // (x + (y-1) )
+ //
+ // Where k is an arbitrary integer.
+ //
+ // catan(z) = -i catanh(iz).
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // DEC -10,+10 5900 1.3e-16 7.8e-18
+ // IEEE -10,+10 30000 2.3e-15 8.5e-17
+ // The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
+ // had peak relative error 1.5e-16, rms relative error
+ // 2.9e-17. See also clog().
+
+ switch re, im := real(x), imag(x); {
+ case im == 0:
+ return complex(math.atan(re), im)
+ case re == 0 && abs(im) <= 1:
+ return complex(re, math.atanh(im))
+ case math.is_inf(im, 0) || math.is_inf(re, 0):
+ if math.is_nan(re) {
+ return complex(math.nan_f64(), math.copy_sign(0, im))
+ }
+ return complex(math.copy_sign(math.PI/2, re), math.copy_sign(0, im))
+ case math.is_nan(re) || math.is_nan(im):
+ return nan_complex128()
+ }
+ x2 := real(x) * real(x)
+ a := 1 - x2 - imag(x)*imag(x)
+ if a == 0 {
+ return nan_complex128()
+ }
+ t := 0.5 * math.atan2(2*real(x), a)
+ w := _reduce_pi_f64(t)
+
+ t = imag(x) - 1
+ b := x2 + t*t
+ if b == 0 {
+ return nan_complex128()
+ }
+ t = imag(x) + 1
+ c := (x2 + t*t) / b
+ return complex(w, 0.25*math.ln(c))
+}
+
+atanh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
+ z := complex(-imag(x), real(x)) // z = i * x
+ z = atan(z)
+ return complex(imag(z), -real(z)) // z = -i * z
+}
+atanh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
+ z := complex(-imag(x), real(x)) // z = i * x
+ z = atan(z)
+ return complex(imag(z), -real(z)) // z = -i * z
+}
+atanh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ z := complex(-imag(x), real(x)) // z = i * x
+ z = atan(z)
+ return complex(imag(z), -real(z)) // z = -i * z
+} \ No newline at end of file
diff --git a/core/math/cmplx/cmplx_trig.odin b/core/math/cmplx/cmplx_trig.odin
new file mode 100644
index 000000000..7ca404fab
--- /dev/null
+++ b/core/math/cmplx/cmplx_trig.odin
@@ -0,0 +1,409 @@
+package math_cmplx
+
+import "core:math"
+import "core:math/bits"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+
+sin_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex circular sine
+ //
+ // DESCRIPTION:
+ //
+ // If
+ // z = x + iy,
+ //
+ // then
+ //
+ // w = sin x cosh y + i cos x sinh y.
+ //
+ // csin(z) = -i csinh(iz).
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // DEC -10,+10 8400 5.3e-17 1.3e-17
+ // IEEE -10,+10 30000 3.8e-16 1.0e-16
+ // Also tested by csin(casin(z)) = z.
+
+ switch re, im := real(x), imag(x); {
+ case im == 0 && (math.is_inf(re, 0) || math.is_nan(re)):
+ return complex(math.nan_f64(), im)
+ case math.is_inf(im, 0):
+ switch {
+ case re == 0:
+ return x
+ case math.is_inf(re, 0) || math.is_nan(re):
+ return complex(math.nan_f64(), im)
+ }
+ case re == 0 && math.is_nan(im):
+ return x
+ }
+ s, c := math.sincos(real(x))
+ sh, ch := _sinhcosh_f64(imag(x))
+ return complex(s*ch, c*sh)
+}
+
+cos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex circular cosine
+ //
+ // DESCRIPTION:
+ //
+ // If
+ // z = x + iy,
+ //
+ // then
+ //
+ // w = cos x cosh y - i sin x sinh y.
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // DEC -10,+10 8400 4.5e-17 1.3e-17
+ // IEEE -10,+10 30000 3.8e-16 1.0e-16
+
+ switch re, im := real(x), imag(x); {
+ case im == 0 && (math.is_inf(re, 0) || math.is_nan(re)):
+ return complex(math.nan_f64(), -im*math.copy_sign(0, re))
+ case math.is_inf(im, 0):
+ switch {
+ case re == 0:
+ return complex(math.inf_f64(1), -re*math.copy_sign(0, im))
+ case math.is_inf(re, 0) || math.is_nan(re):
+ return complex(math.inf_f64(1), math.nan_f64())
+ }
+ case re == 0 && math.is_nan(im):
+ return complex(math.nan_f64(), 0)
+ }
+ s, c := math.sincos(real(x))
+ sh, ch := _sinhcosh_f64(imag(x))
+ return complex(c*ch, -s*sh)
+}
+
+sinh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex hyperbolic sine
+ //
+ // DESCRIPTION:
+ //
+ // csinh z = (cexp(z) - cexp(-z))/2
+ // = sinh x * cos y + i cosh x * sin y .
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // IEEE -10,+10 30000 3.1e-16 8.2e-17
+
+ switch re, im := real(x), imag(x); {
+ case re == 0 && (math.is_inf(im, 0) || math.is_nan(im)):
+ return complex(re, math.nan_f64())
+ case math.is_inf(re, 0):
+ switch {
+ case im == 0:
+ return complex(re, im)
+ case math.is_inf(im, 0) || math.is_nan(im):
+ return complex(re, math.nan_f64())
+ }
+ case im == 0 && math.is_nan(re):
+ return complex(math.nan_f64(), im)
+ }
+ s, c := math.sincos(imag(x))
+ sh, ch := _sinhcosh_f64(real(x))
+ return complex(c*sh, s*ch)
+}
+
+cosh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex hyperbolic cosine
+ //
+ // DESCRIPTION:
+ //
+ // ccosh(z) = cosh x cos y + i sinh x sin y .
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // IEEE -10,+10 30000 2.9e-16 8.1e-17
+
+ switch re, im := real(x), imag(x); {
+ case re == 0 && (math.is_inf(im, 0) || math.is_nan(im)):
+ return complex(math.nan_f64(), re*math.copy_sign(0, im))
+ case math.is_inf(re, 0):
+ switch {
+ case im == 0:
+ return complex(math.inf_f64(1), im*math.copy_sign(0, re))
+ case math.is_inf(im, 0) || math.is_nan(im):
+ return complex(math.inf_f64(1), math.nan_f64())
+ }
+ case im == 0 && math.is_nan(re):
+ return complex(math.nan_f64(), im)
+ }
+ s, c := math.sincos(imag(x))
+ sh, ch := _sinhcosh_f64(real(x))
+ return complex(c*ch, s*sh)
+}
+
+tan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ // Complex circular tangent
+ //
+ // DESCRIPTION:
+ //
+ // If
+ // z = x + iy,
+ //
+ // then
+ //
+ // sin 2x + i sinh 2y
+ // w = --------------------.
+ // cos 2x + cosh 2y
+ //
+ // On the real axis the denominator is zero at odd multiples
+ // of PI/2. The denominator is evaluated by its Taylor
+ // series near these points.
+ //
+ // ctan(z) = -i ctanh(iz).
+ //
+ // ACCURACY:
+ //
+ // Relative error:
+ // arithmetic domain # trials peak rms
+ // DEC -10,+10 5200 7.1e-17 1.6e-17
+ // IEEE -10,+10 30000 7.2e-16 1.2e-16
+ // Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
+
+ switch re, im := real(x), imag(x); {
+ case math.is_inf(im, 0):
+ switch {
+ case math.is_inf(re, 0) || math.is_nan(re):
+ return complex(math.copy_sign(0, re), math.copy_sign(1, im))
+ }
+ return complex(math.copy_sign(0, math.sin(2*re)), math.copy_sign(1, im))
+ case re == 0 && math.is_nan(im):
+ return x
+ }
+ d := math.cos(2*real(x)) + math.cosh(2*imag(x))
+ if abs(d) < 0.25 {
+ d = _tan_series_f64(x)
+ }
+ if d == 0 {
+ return inf_complex128()
+ }
+ return complex(math.sin(2*real(x))/d, math.sinh(2*imag(x))/d)
+}
+
+tanh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ switch re, im := real(x), imag(x); {
+ case math.is_inf(re, 0):
+ switch {
+ case math.is_inf(im, 0) || math.is_nan(im):
+ return complex(math.copy_sign(1, re), math.copy_sign(0, im))
+ }
+ return complex(math.copy_sign(1, re), math.copy_sign(0, math.sin(2*im)))
+ case im == 0 && math.is_nan(re):
+ return x
+ }
+ d := math.cosh(2*real(x)) + math.cos(2*imag(x))
+ if d == 0 {
+ return inf_complex128()
+ }
+ return complex(math.sinh(2*real(x))/d, math.sin(2*imag(x))/d)
+}
+
+cot_complex128 :: proc "contextless" (x: complex128) -> complex128 {
+ d := math.cosh(2*imag(x)) - math.cos(2*real(x))
+ if abs(d) < 0.25 {
+ d = _tan_series_f64(x)
+ }
+ if d == 0 {
+ return inf_complex128()
+ }
+ return complex(math.sin(2*real(x))/d, -math.sinh(2*imag(x))/d)
+}
+
+
+@(private="file")
+_sinhcosh_f64 :: proc "contextless" (x: f64) -> (sh, ch: f64) {
+ if abs(x) <= 0.5 {
+ return math.sinh(x), math.cosh(x)
+ }
+ e := math.exp(x)
+ ei := 0.5 / e
+ e *= 0.5
+ return e - ei, e + ei
+}
+
+
+// taylor series of cosh(2y) - cos(2x)
+@(private)
+_tan_series_f64 :: proc "contextless" (z: complex128) -> f64 {
+ MACH_EPSILON :: 1.0 / (1 << 53)
+
+ x := abs(2 * real(z))
+ y := abs(2 * imag(z))
+ x = _reduce_pi_f64(x)
+ x, y = x * x, y * y
+ x2, y2 := 1.0, 1.0
+ f, rn, d := 1.0, 0.0, 0.0
+
+ for {
+ rn += 1
+ f *= rn
+ rn += 1
+ f *= rn
+ x2 *= x
+ y2 *= y
+ t := y2 + x2
+ t /= f
+ d += t
+
+ rn += 1
+ f *= rn
+ rn += 1
+ f *= rn
+ x2 *= x
+ y2 *= y
+ t = y2 - x2
+ t /= f
+ d += t
+ if !(abs(t/d) > MACH_EPSILON) { // don't use <=, because of floating point nonsense and NaN
+ break
+ }
+ }
+ return d
+}
+
+// _reduce_pi_f64 reduces the input argument x to the range (-PI/2, PI/2].
+// x must be greater than or equal to 0. For small arguments it
+// uses Cody-Waite reduction in 3 f64 parts based on:
+// "Elementary Function Evaluation: Algorithms and Implementation"
+// Jean-Michel Muller, 1997.
+// For very large arguments it uses Payne-Hanek range reduction based on:
+// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"
+@(private)
+_reduce_pi_f64 :: proc "contextless" (x: f64) -> f64 #no_bounds_check {
+ x := x
+
+ // REDUCE_THRESHOLD is the maximum value of x where the reduction using
+ // Cody-Waite reduction still gives accurate results. This threshold
+ // is set by t*PIn being representable as a f64 without error
+ // where t is given by t = floor(x * (1 / PI)) and PIn are the leading partial
+ // terms of PI. Since the leading terms, PI1 and PI2 below, have 30 and 32
+ // trailing zero bits respectively, t should have less than 30 significant bits.
+ // t < 1<<30 -> floor(x*(1/PI)+0.5) < 1<<30 -> x < (1<<30-1) * PI - 0.5
+ // So, conservatively we can take x < 1<<30.
+ REDUCE_THRESHOLD :: f64(1 << 30)
+
+ if abs(x) < REDUCE_THRESHOLD {
+ // Use Cody-Waite reduction in three parts.
+ // PI1, PI2 and PI3 comprise an extended precision value of PI
+ // such that PI ~= PI1 + PI2 + PI3. The parts are chosen so
+ // that PI1 and PI2 have an approximately equal number of trailing
+ // zero bits. This ensures that t*PI1 and t*PI2 are exact for
+ // large integer values of t. The full precision PI3 ensures the
+ // approximation of PI is accurate to 102 bits to handle cancellation
+ // during subtraction.
+ PI1 :: 0h400921fb40000000 // 3.141592502593994
+ PI2 :: 0h3e84442d00000000 // 1.5099578831723193e-07
+ PI3 :: 0h3d08469898cc5170 // 1.0780605716316238e-14
+
+ t := x / math.PI
+ t += 0.5
+ t = f64(i64(t)) // i64(t) = the multiple
+ return ((x - t*PI1) - t*PI2) - t*PI3
+ }
+ // Must apply Payne-Hanek range reduction
+ MASK :: 0x7FF
+ SHIFT :: 64 - 11 - 1
+ BIAS :: 1023
+ FRAC_MASK :: 1<<SHIFT - 1
+
+ // Extract out the integer and exponent such that,
+ // x = ix * 2 ** exp.
+ ix := transmute(u64)(x)
+ exp := int(ix>>SHIFT&MASK) - BIAS - SHIFT
+ ix &= FRAC_MASK
+ ix |= 1 << SHIFT
+
+ // bdpi is the binary digits of 1/PI as a u64 array,
+ // that is, 1/PI = SUM bdpi[i]*2^(-64*i).
+ // 19 64-bit digits give 1216 bits of precision
+ // to handle the largest possible f64 exponent.
+ @static bdpi := [?]u64{
+ 0x0000000000000000,
+ 0x517cc1b727220a94,
+ 0xfe13abe8fa9a6ee0,
+ 0x6db14acc9e21c820,
+ 0xff28b1d5ef5de2b0,
+ 0xdb92371d2126e970,
+ 0x0324977504e8c90e,
+ 0x7f0ef58e5894d39f,
+ 0x74411afa975da242,
+ 0x74ce38135a2fbf20,
+ 0x9cc8eb1cc1a99cfa,
+ 0x4e422fc5defc941d,
+ 0x8ffc4bffef02cc07,
+ 0xf79788c5ad05368f,
+ 0xb69b3f6793e584db,
+ 0xa7a31fb34f2ff516,
+ 0xba93dd63f5f2f8bd,
+ 0x9e839cfbc5294975,
+ 0x35fdafd88fc6ae84,
+ 0x2b0198237e3db5d5,
+ }
+
+ // Use the exponent to extract the 3 appropriate u64 digits from bdpi,
+ // B ~ (z0, z1, z2), such that the product leading digit has the exponent -64.
+ // Note, exp >= 50 since x >= REDUCE_THRESHOLD and exp < 971 for maximum f64.
+ digit, bitshift := uint(exp+64)/64, uint(exp+64)%64
+ z0 := (bdpi[digit] << bitshift) | (bdpi[digit+1] >> (64 - bitshift))
+ z1 := (bdpi[digit+1] << bitshift) | (bdpi[digit+2] >> (64 - bitshift))
+ z2 := (bdpi[digit+2] << bitshift) | (bdpi[digit+3] >> (64 - bitshift))
+
+ // Multiply mantissa by the digits and extract the upper two digits (hi, lo).
+ z2hi, _ := bits.mul(z2, ix)
+ z1hi, z1lo := bits.mul(z1, ix)
+ z0lo := z0 * ix
+ lo, c := bits.add(z1lo, z2hi, 0)
+ hi, _ := bits.add(z0lo, z1hi, c)
+
+ // Find the magnitude of the fraction.
+ lz := uint(bits.leading_zeros(hi))
+ e := u64(BIAS - (lz + 1))
+
+ // Clear implicit mantissa bit and shift into place.
+ hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1)))
+ hi >>= 64 - SHIFT
+
+ // Include the exponent and convert to a float.
+ hi |= e << SHIFT
+ x = transmute(f64)(hi)
+
+ // map to (-PI/2, PI/2]
+ if x > 0.5 {
+ x -= 1
+ }
+ return math.PI * x
+}
+
diff --git a/core/math/ease/ease.odin b/core/math/ease/ease.odin
index d5cb85dd8..0e6569bca 100644
--- a/core/math/ease/ease.odin
+++ b/core/math/ease/ease.odin
@@ -450,7 +450,7 @@ flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where i
flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
clear(&flux.keys_to_be_deleted)
- for key, tween in &flux.values {
+ for key, &tween in flux.values {
delay_remainder := f64(0)
// Update delay if necessary.
diff --git a/core/math/math.odin b/core/math/math.odin
index 05177378f..6f7a36bab 100644
--- a/core/math/math.odin
+++ b/core/math/math.odin
@@ -2158,6 +2158,80 @@ signbit :: proc{
}
+@(require_results)
+hypot_f16 :: proc "contextless" (x, y: f16) -> (r: f16) {
+ p, q := abs(x), abs(y)
+ switch {
+ case is_inf(p, 1) || is_inf(q, 1):
+ return inf_f16(1)
+ case is_nan(p) || is_nan(q):
+ return nan_f16()
+ }
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * sqrt(1+q*q)
+}
+@(require_results)
+hypot_f32 :: proc "contextless" (x, y: f32) -> (r: f32) {
+ p, q := abs(x), abs(y)
+ switch {
+ case is_inf(p, 1) || is_inf(q, 1):
+ return inf_f32(1)
+ case is_nan(p) || is_nan(q):
+ return nan_f32()
+ }
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * sqrt(1+q*q)
+}
+@(require_results)
+hypot_f64 :: proc "contextless" (x, y: f64) -> (r: f64) {
+ p, q := abs(x), abs(y)
+ switch {
+ case is_inf(p, 1) || is_inf(q, 1):
+ return inf_f64(1)
+ case is_nan(p) || is_nan(q):
+ return nan_f64()
+ }
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * sqrt(1+q*q)
+}
+@(require_results) hypot_f16le :: proc "contextless" (x, y: f16le) -> (r: f16le) { return f16le(hypot_f16(f16(x), f16(y))) }
+@(require_results) hypot_f16be :: proc "contextless" (x, y: f16be) -> (r: f16be) { return f16be(hypot_f16(f16(x), f16(y))) }
+@(require_results) hypot_f32le :: proc "contextless" (x, y: f32le) -> (r: f32le) { return f32le(hypot_f32(f32(x), f32(y))) }
+@(require_results) hypot_f32be :: proc "contextless" (x, y: f32be) -> (r: f32be) { return f32be(hypot_f32(f32(x), f32(y))) }
+@(require_results) hypot_f64le :: proc "contextless" (x, y: f64le) -> (r: f64le) { return f64le(hypot_f64(f64(x), f64(y))) }
+@(require_results) hypot_f64be :: proc "contextless" (x, y: f64be) -> (r: f64be) { return f64be(hypot_f64(f64(x), f64(y))) }
+
+// hypot returns Sqrt(p*p + q*q), taking care to avoid unnecessary overflow and underflow.
+//
+// Special cases:
+// hypot(±Inf, q) = +Inf
+// hypot(p, ±Inf) = +Inf
+// hypot(NaN, q) = NaN
+// hypot(p, NaN) = NaN
+hypot :: proc{
+ hypot_f16, hypot_f16le, hypot_f16be,
+ hypot_f32, hypot_f32le, hypot_f32be,
+ hypot_f64, hypot_f64le, hypot_f64be,
+}
+
F16_DIG :: 3
F16_EPSILON :: 0.00097656
F16_GUARD :: 0
diff --git a/core/math/math_basic.odin b/core/math/math_basic.odin
index 785c43b10..95e0a93ec 100644
--- a/core/math/math_basic.odin
+++ b/core/math/math_basic.odin
@@ -3,45 +3,111 @@ package math
import "core:intrinsics"
-@(default_calling_convention="none")
+@(default_calling_convention="none", private="file")
foreign _ {
@(link_name="llvm.sin.f16", require_results)
- sin_f16 :: proc(θ: f16) -> f16 ---
+ _sin_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.sin.f32", require_results)
- sin_f32 :: proc(θ: f32) -> f32 ---
+ _sin_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.sin.f64", require_results)
- sin_f64 :: proc(θ: f64) -> f64 ---
+ _sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.cos.f16", require_results)
- cos_f16 :: proc(θ: f16) -> f16 ---
+ _cos_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.cos.f32", require_results)
- cos_f32 :: proc(θ: f32) -> f32 ---
+ _cos_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.cos.f64", require_results)
- cos_f64 :: proc(θ: f64) -> f64 ---
+ _cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.pow.f16", require_results)
- pow_f16 :: proc(x, power: f16) -> f16 ---
+ _pow_f16 :: proc(x, power: f16) -> f16 ---
@(link_name="llvm.pow.f32", require_results)
- pow_f32 :: proc(x, power: f32) -> f32 ---
+ _pow_f32 :: proc(x, power: f32) -> f32 ---
@(link_name="llvm.pow.f64", require_results)
- pow_f64 :: proc(x, power: f64) -> f64 ---
+ _pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="llvm.fmuladd.f16", require_results)
- fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
+ _fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
@(link_name="llvm.fmuladd.f32", require_results)
- fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
+ _fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
@(link_name="llvm.fmuladd.f64", require_results)
- fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
+ _fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="llvm.exp.f16", require_results)
- exp_f16 :: proc(x: f16) -> f16 ---
+ _exp_f16 :: proc(x: f16) -> f16 ---
@(link_name="llvm.exp.f32", require_results)
- exp_f32 :: proc(x: f32) -> f32 ---
+ _exp_f32 :: proc(x: f32) -> f32 ---
@(link_name="llvm.exp.f64", require_results)
- exp_f64 :: proc(x: f64) -> f64 ---
+ _exp_f64 :: proc(x: f64) -> f64 ---
}
@(require_results)
+sin_f16 :: proc "contextless" (θ: f16) -> f16 {
+ return _sin_f16(θ)
+}
+@(require_results)
+sin_f32 :: proc "contextless" (θ: f32) -> f32 {
+ return _sin_f32(θ)
+}
+@(require_results)
+sin_f64 :: proc "contextless" (θ: f64) -> f64 {
+ return _sin_f64(θ)
+}
+
+@(require_results)
+cos_f16 :: proc "contextless" (θ: f16) -> f16 {
+ return _cos_f16(θ)
+}
+@(require_results)
+cos_f32 :: proc "contextless" (θ: f32) -> f32 {
+ return _cos_f32(θ)
+}
+@(require_results)
+cos_f64 :: proc "contextless" (θ: f64) -> f64 {
+ return _cos_f64(θ)
+}
+
+@(require_results)
+pow_f16 :: proc "contextless" (x, power: f16) -> f16 {
+ return _pow_f16(x, power)
+}
+@(require_results)
+pow_f32 :: proc "contextless" (x, power: f32) -> f32 {
+ return _pow_f32(x, power)
+}
+@(require_results)
+pow_f64 :: proc "contextless" (x, power: f64) -> f64 {
+ return _pow_f64(x, power)
+}
+
+@(require_results)
+fmuladd_f16 :: proc "contextless" (a, b, c: f16) -> f16 {
+ return _fmuladd_f16(a, b, c)
+}
+@(require_results)
+fmuladd_f32 :: proc "contextless" (a, b, c: f32) -> f32 {
+ return _fmuladd_f32(a, b, c)
+}
+@(require_results)
+fmuladd_f64 :: proc "contextless" (a, b, c: f64) -> f64 {
+ return _fmuladd_f64(a, b, c)
+}
+
+@(require_results)
+exp_f16 :: proc "contextless" (x: f16) -> f16 {
+ return _exp_f16(x)
+}
+@(require_results)
+exp_f32 :: proc "contextless" (x: f32) -> f32 {
+ return _exp_f32(x)
+}
+@(require_results)
+exp_f64 :: proc "contextless" (x: f64) -> f64 {
+ return _exp_f64(x)
+}
+
+
+@(require_results)
sqrt_f16 :: proc "contextless" (x: f16) -> f16 {
return intrinsics.sqrt(x)
}
diff --git a/core/math/math_sincos.odin b/core/math/math_sincos.odin
new file mode 100644
index 000000000..578876ac5
--- /dev/null
+++ b/core/math/math_sincos.odin
@@ -0,0 +1,308 @@
+package math
+
+import "core:math/bits"
+
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+// sin.c
+//
+// Circular sine
+//
+// SYNOPSIS:
+//
+// double x, y, sin();
+// y = sin( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4. The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the sine is approximated by
+// x + x**3 P(x**2).
+// Between pi/4 and pi/2 the cosine is represented as
+// 1 - x**2 Q(x**2).
+//
+// ACCURACY:
+//
+// Relative error:
+// arithmetic domain # trials peak rms
+// DEC 0, 10 150000 3.0e-17 7.8e-18
+// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
+// be meaningless for x > 2**49 = 5.6e14.
+//
+// cos.c
+//
+// Circular cosine
+//
+// SYNOPSIS:
+//
+// double x, y, cos();
+// y = cos( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4. The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the cosine is approximated by
+// 1 - x**2 Q(x**2).
+// Between pi/4 and pi/2 the sine is represented as
+// x + x**3 P(x**2).
+//
+// ACCURACY:
+//
+// Relative error:
+// arithmetic domain # trials peak rms
+// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
+// DEC 0,+1.07e9 17000 3.0e-17 7.2e-18
+//
+// Cephes Math Library Release 2.8: June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+// Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+// The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+// Stephen L. Moshier
+// moshier@na-net.ornl.gov
+
+sincos :: proc{
+ sincos_f16, sincos_f16le, sincos_f16be,
+ sincos_f32, sincos_f32le, sincos_f32be,
+ sincos_f64, sincos_f64le, sincos_f64be,
+}
+
+sincos_f16 :: proc "contextless" (x: f16) -> (sin, cos: f16) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f16(s), f16(c)
+}
+sincos_f16le :: proc "contextless" (x: f16le) -> (sin, cos: f16le) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f16le(s), f16le(c)
+}
+sincos_f16be :: proc "contextless" (x: f16be) -> (sin, cos: f16be) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f16be(s), f16be(c)
+}
+
+sincos_f32 :: proc "contextless" (x: f32) -> (sin, cos: f32) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f32(s), f32(c)
+}
+sincos_f32le :: proc "contextless" (x: f32le) -> (sin, cos: f32le) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f32le(s), f32le(c)
+}
+sincos_f32be :: proc "contextless" (x: f32be) -> (sin, cos: f32be) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f32be(s), f32be(c)
+}
+
+sincos_f64le :: proc "contextless" (x: f64le) -> (sin, cos: f64le) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f64le(s), f64le(c)
+}
+sincos_f64be :: proc "contextless" (x: f64be) -> (sin, cos: f64be) #no_bounds_check {
+ s, c := sincos_f64(f64(x))
+ return f64be(s), f64be(c)
+}
+
+sincos_f64 :: proc "contextless" (x: f64) -> (sin, cos: f64) #no_bounds_check {
+ x := x
+
+ PI4A :: 0h3fe921fb40000000 // 7.85398125648498535156e-1 PI/4 split into three parts
+ PI4B :: 0h3e64442d00000000 // 3.77489470793079817668e-8
+ PI4C :: 0h3ce8469898cc5170 // 2.69515142907905952645e-15
+
+ // special cases
+ switch {
+ case x == 0:
+ return x, 1 // return ±0.0, 1.0
+ case is_nan(x) || is_inf(x, 0):
+ return nan_f64(), nan_f64()
+ }
+
+ // make argument positive
+ sin_sign, cos_sign := false, false
+ if x < 0 {
+ x = -x
+ sin_sign = true
+ }
+
+ j: u64
+ y, z: f64
+ if x >= REDUCE_THRESHOLD {
+ j, z = _trig_reduce_f64(x)
+ } else {
+ j = u64(x * (4 / PI)) // integer part of x/(PI/4), as integer for tests on the phase angle
+ y = f64(j) // integer part of x/(PI/4), as float
+
+ if j&1 == 1 { // map zeros to origin
+ j += 1
+ y += 1
+ }
+ j &= 7 // octant modulo TAU radians (360 degrees)
+ z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+ }
+ if j > 3 { // reflect in x axis
+ j -= 4
+ sin_sign, cos_sign = !sin_sign, !cos_sign
+ }
+ if j > 1 {
+ cos_sign = !cos_sign
+ }
+
+ zz := z * z
+
+ cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+ sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+
+ if j == 1 || j == 2 {
+ sin, cos = cos, sin
+ }
+ if cos_sign {
+ cos = -cos
+ }
+ if sin_sign {
+ sin = -sin
+ }
+ return
+}
+
+// sin coefficients
+@(private="file")
+_sin := [?]f64{
+ 0h3de5d8fd1fd19ccd, // 1.58962301576546568060e-10
+ 0hbe5ae5e5a9291f5d, // -2.50507477628578072866e-8
+ 0h3ec71de3567d48a1, // 2.75573136213857245213e-6
+ 0hbf2a01a019bfdf03, // -1.98412698295895385996e-4
+ 0h3f8111111110f7d0, // 8.33333333332211858878e-3
+ 0hbfc5555555555548, // -1.66666666666666307295e-1
+}
+
+// cos coefficients
+@(private="file")
+_cos := [?]f64{
+ 0hbda8fa49a0861a9b, // -1.13585365213876817300e-11,
+ 0h3e21ee9d7b4e3f05, // 2.08757008419747316778e-9,
+ 0hbe927e4f7eac4bc6, // -2.75573141792967388112e-7,
+ 0h3efa01a019c844f5, // 2.48015872888517045348e-5,
+ 0hbf56c16c16c14f91, // -1.38888888888730564116e-3,
+ 0h3fa555555555554b, // 4.16666666666665929218e-2,
+}
+
+// REDUCE_THRESHOLD is the maximum value of x where the reduction using Pi/4
+// in 3 f64 parts still gives accurate results. This threshold
+// is set by y*C being representable as a f64 without error
+// where y is given by y = floor(x * (4 / Pi)) and C is the leading partial
+// terms of 4/Pi. Since the leading terms (PI4A and PI4B in sin.go) have 30
+// and 32 trailing zero bits, y should have less than 30 significant bits.
+//
+// y < 1<<30 -> floor(x*4/Pi) < 1<<30 -> x < (1<<30 - 1) * Pi/4
+//
+// So, conservatively we can take x < 1<<29.
+// Above this threshold Payne-Hanek range reduction must be used.
+@(private="file")
+REDUCE_THRESHOLD :: 1 << 29
+
+// _trig_reduce_f64 implements Payne-Hanek range reduction by Pi/4
+// for x > 0. It returns the integer part mod 8 (j) and
+// the fractional part (z) of x / (Pi/4).
+// The implementation is based on:
+// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"
+// K. C. Ng et al, March 24, 1992
+// The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic.
+_trig_reduce_f64 :: proc "contextless" (x: f64) -> (j: u64, z: f64) #no_bounds_check {
+ // bd_pi4 is the binary digits of 4/pi as a u64 array,
+ // that is, 4/pi = Sum bd_pi4[i]*2^(-64*i)
+ // 19 64-bit digits and the leading one bit give 1217 bits
+ // of precision to handle the largest possible f64 exponent.
+ @static bd_pi4 := [?]u64{
+ 0x0000000000000001,
+ 0x45f306dc9c882a53,
+ 0xf84eafa3ea69bb81,
+ 0xb6c52b3278872083,
+ 0xfca2c757bd778ac3,
+ 0x6e48dc74849ba5c0,
+ 0x0c925dd413a32439,
+ 0xfc3bd63962534e7d,
+ 0xd1046bea5d768909,
+ 0xd338e04d68befc82,
+ 0x7323ac7306a673e9,
+ 0x3908bf177bf25076,
+ 0x3ff12fffbc0b301f,
+ 0xde5e2316b414da3e,
+ 0xda6cfd9e4f96136e,
+ 0x9e8c7ecd3cbfd45a,
+ 0xea4f758fd7cbe2f6,
+ 0x7a0e73ef14a525d4,
+ 0xd7f6bf623f1aba10,
+ 0xac06608df8f6d757,
+ }
+
+ PI4 :: PI / 4
+ if x < PI4 {
+ return 0, x
+ }
+
+ MASK :: 0x7FF
+ SHIFT :: 64 - 11 - 1
+ BIAS :: 1023
+
+ // Extract out the integer and exponent such that,
+ // x = ix * 2 ** exp.
+ ix := transmute(u64)x
+ exp := int(ix>>SHIFT&MASK) - BIAS - SHIFT
+ ix &~= MASK << SHIFT
+ ix |= 1 << SHIFT
+ // Use the exponent to extract the 3 appropriate u64 digits from bd_pi4,
+ // B ~ (z0, z1, z2), such that the product leading digit has the exponent -61.
+ // Note, exp >= -53 since x >= PI4 and exp < 971 for maximum f64.
+ digit, bitshift := uint(exp+61)/64, uint(exp+61)%64
+ z0 := (bd_pi4[digit] << bitshift) | (bd_pi4[digit+1] >> (64 - bitshift))
+ z1 := (bd_pi4[digit+1] << bitshift) | (bd_pi4[digit+2] >> (64 - bitshift))
+ z2 := (bd_pi4[digit+2] << bitshift) | (bd_pi4[digit+3] >> (64 - bitshift))
+ // Multiply mantissa by the digits and extract the upper two digits (hi, lo).
+ z2hi, _ := bits.mul(z2, ix)
+ z1hi, z1lo := bits.mul(z1, ix)
+ z0lo := z0 * ix
+ lo, c := bits.add(z1lo, z2hi, 0)
+ hi, _ := bits.add(z0lo, z1hi, c)
+ // The top 3 bits are j.
+ j = hi >> 61
+ // Extract the fraction and find its magnitude.
+ hi = hi<<3 | lo>>61
+ lz := uint(bits.leading_zeros(hi))
+ e := u64(BIAS - (lz + 1))
+ // Clear implicit mantissa bit and shift into place.
+ hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1)))
+ hi >>= 64 - SHIFT
+ // Include the exponent and convert to a float.
+ hi |= e << SHIFT
+ z = transmute(f64)hi
+ // Map zeros to origin.
+ if j&1 == 1 {
+ j += 1
+ j &= 7
+ z -= 1
+ }
+ // Multiply the fractional part by pi/4.
+ return j, z * PI4
+}
diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin
index 603c2a6c7..7767740c9 100644
--- a/core/mem/allocators.odin
+++ b/core/mem/allocators.odin
@@ -813,22 +813,22 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
switch mode {
case .Alloc:
if size > 0 {
- panic("mem: panic allocator, .Alloc called")
+ panic("mem: panic allocator, .Alloc called", loc=loc)
}
case .Alloc_Non_Zeroed:
if size > 0 {
- panic("mem: panic allocator, .Alloc_Non_Zeroed called")
+ panic("mem: panic allocator, .Alloc_Non_Zeroed called", loc=loc)
}
case .Resize:
if size > 0 {
- panic("mem: panic allocator, .Resize called")
+ panic("mem: panic allocator, .Resize called", loc=loc)
}
case .Free:
if old_memory != nil {
- panic("mem: panic allocator, .Free called")
+ panic("mem: panic allocator, .Free called", loc=loc)
}
case .Free_All:
- panic("mem: panic allocator, .Free_All called")
+ panic("mem: panic allocator, .Free_All called", loc=loc)
case .Query_Features:
set := (^Allocator_Mode_Set)(old_memory)
@@ -838,7 +838,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, nil
case .Query_Info:
- panic("mem: panic allocator, .Query_Info called")
+ panic("mem: panic allocator, .Query_Info called", loc=loc)
}
return nil, nil
diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin
index 027a6ce6e..cfd35ab05 100644
--- a/core/mem/virtual/arena.odin
+++ b/core/mem/virtual/arena.odin
@@ -120,7 +120,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
if arena.minimum_block_size == 0 {
arena.minimum_block_size = DEFAULT_ARENA_STATIC_RESERVE_SIZE
}
- arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
+ arena_init_static(arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
}
fallthrough
case .Buffer:
@@ -242,7 +242,7 @@ arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, min
return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size)
}
-// Ability to bootstrap allocate a struct with an arena within the struct itself using the growing variant strategy.
+// Ability to bootstrap allocate a struct with an arena within the struct itself using the static variant strategy.
@(require_results)
arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
bootstrap: Arena
@@ -258,7 +258,7 @@ arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintpt
return
}
-// Ability to bootstrap allocate a struct with an arena within the struct itself using the growing variant strategy.
+// Ability to bootstrap allocate a struct with an arena within the struct itself using the static variant strategy.
@(require_results)
arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved)
@@ -271,7 +271,7 @@ arena_allocator :: proc(arena: ^Arena) -> mem.Allocator {
return mem.Allocator{arena_allocator_proc, arena}
}
-// The allocator procedured by an `Allocator` produced by `arena_allocator`
+// The allocator procedure used by an `Allocator` produced by `arena_allocator`
arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
@@ -328,7 +328,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
-// An `Arena_Temp` is a way to produce temporary watermarks to reset a arena to a previous state.
+// An `Arena_Temp` is a way to produce temporary watermarks to reset an arena to a previous state.
// All uses of an `Arena_Temp` must be handled by ending them with `arena_temp_end` or ignoring them with `arena_temp_ignore`.
Arena_Temp :: struct {
arena: ^Arena,
diff --git a/core/mem/virtual/virtual_bsd.odin b/core/mem/virtual/virtual_bsd.odin
new file mode 100644
index 000000000..103e48074
--- /dev/null
+++ b/core/mem/virtual/virtual_bsd.odin
@@ -0,0 +1,24 @@
+//+build freebsd, openbsd
+//+private
+package mem_virtual
+
+
+
+_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
+ return nil, nil
+}
+
+_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
+ return nil
+}
+_decommit :: proc "contextless" (data: rawptr, size: uint) {
+}
+_release :: proc "contextless" (data: rawptr, size: uint) {
+}
+_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
+ return false
+}
+
+_platform_memory_init :: proc() {
+
+}
diff --git a/core/net/dns_unix.odin b/core/net/dns_unix.odin
index bbecc7476..e9b7bd066 100644
--- a/core/net/dns_unix.odin
+++ b/core/net/dns_unix.odin
@@ -44,9 +44,6 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
if !hosts_ok {
return nil, .Invalid_Hosts_Config_Error
}
- if len(hosts) == 0 {
- return
- }
host_overrides := make([dynamic]DNS_Record)
for host in hosts {
@@ -80,4 +77,4 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
}
return get_dns_records_from_nameservers(hostname, type, name_servers, host_overrides[:])
-} \ No newline at end of file
+}
diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin
index f00be9915..081892afd 100644
--- a/core/net/socket_darwin.odin
+++ b/core/net/socket_darwin.odin
@@ -268,9 +268,9 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
t, ok := value.(time.Duration)
if !ok do panic("set_option() value must be a time.Duration here", loc)
- nanos := time.duration_nanoseconds(t)
- timeval_value.nanoseconds = int(nanos % 1e9)
- timeval_value.seconds = (nanos - i64(timeval_value.nanoseconds)) / 1e9
+ micros := i64(time.duration_microseconds(t))
+ timeval_value.microseconds = int(micros % 1e6)
+ timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
ptr = &timeval_value
len = size_of(timeval_value)
@@ -368,4 +368,4 @@ _sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endp
panic("native_addr is neither IP4 or IP6 address")
}
return
-} \ No newline at end of file
+}
diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin
index 690e09ab7..b7141e8ba 100644
--- a/core/net/socket_linux.odin
+++ b/core/net/socket_linux.odin
@@ -283,9 +283,9 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
t, ok := value.(time.Duration)
if !ok do panic("set_option() value must be a time.Duration here", loc)
- nanos := time.duration_nanoseconds(t)
- timeval_value.nanoseconds = int(nanos % 1e9)
- timeval_value.seconds = (nanos - i64(timeval_value.nanoseconds)) / 1e9
+ micros := i64(time.duration_microseconds(t))
+ timeval_value.microseconds = int(micros % 1e6)
+ timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
ptr = &timeval_value
len = size_of(timeval_value)
@@ -404,4 +404,4 @@ _sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint)
panic("native_addr is neither IP4 or IP6 address")
}
return
-} \ No newline at end of file
+}
diff --git a/core/os/os2/errors_windows.odin b/core/os/os2/errors_windows.odin
index 27c16e72e..6500e7ccc 100644
--- a/core/os/os2/errors_windows.odin
+++ b/core/os/os2/errors_windows.odin
@@ -37,14 +37,18 @@ _get_platform_error :: proc() -> Error {
case win32.ERROR_NOT_SUPPORTED:
return .Unsupported
+ case win32.ERROR_HANDLE_EOF:
+ return .EOF
+
+ case win32.ERROR_INVALID_HANDLE:
+ return .Invalid_File
+
case
win32.ERROR_BAD_ARGUMENTS,
win32.ERROR_INVALID_PARAMETER,
win32.ERROR_NOT_ENOUGH_MEMORY,
- win32.ERROR_INVALID_HANDLE,
win32.ERROR_NO_MORE_FILES,
win32.ERROR_LOCK_VIOLATION,
- win32.ERROR_HANDLE_EOF,
win32.ERROR_BROKEN_PIPE,
win32.ERROR_CALL_NOT_IMPLEMENTED,
win32.ERROR_INSUFFICIENT_BUFFER,
diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin
index eb6d9e366..da822374a 100644
--- a/core/os/os2/file.odin
+++ b/core/os/os2/file.odin
@@ -8,12 +8,6 @@ File :: struct {
impl: _File,
}
-Seek_From :: enum {
- Start = 0, // seek relative to the origin of the file
- Current = 1, // seek relative to the current offset
- End = 2, // seek relative to the end
-}
-
File_Mode :: distinct u32
File_Mode_Dir :: File_Mode(1<<16)
File_Mode_Named_Pipe :: File_Mode(1<<17)
@@ -72,56 +66,70 @@ fd :: proc(f: ^File) -> uintptr {
return _fd(f)
}
-
-close :: proc(f: ^File) -> Error {
- return _close(f)
-}
-
name :: proc(f: ^File) -> string {
return _name(f)
}
-seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
- return _seek(f, offset, whence)
+close :: proc(f: ^File) -> Error {
+ if f != nil {
+ return io.close(f.impl.stream)
+ }
+ return nil
}
-read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
- return _read(f, p)
+seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
+ if f != nil {
+ return io.seek(f.impl.stream, offset, whence)
+ }
+ return 0, .Invalid_File
}
-read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
- return _read_at(f, p, offset)
+read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
+ if f != nil {
+ return io.read(f.impl.stream, p)
+ }
+ return 0, .Invalid_File
}
-read_from :: proc(f: ^File, r: io.Reader) -> (n: i64, err: Error) {
- return _read_from(f, r)
+read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
+ if f != nil {
+ return io.read_at(f.impl.stream, p, offset)
+ }
+ return 0, .Invalid_File
}
write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
- return _write(f, p)
+ if f != nil {
+ return io.write(f.impl.stream, p)
+ }
+ return 0, .Invalid_File
}
write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
- return _write_at(f, p, offset)
-}
-
-write_to :: proc(f: ^File, w: io.Writer) -> (n: i64, err: Error) {
- return _write_to(f, w)
+ if f != nil {
+ return io.write_at(f.impl.stream, p, offset)
+ }
+ return 0, .Invalid_File
}
file_size :: proc(f: ^File) -> (n: i64, err: Error) {
- return _file_size(f)
+ if f != nil {
+ return io.size(f.impl.stream)
+ }
+ return 0, .Invalid_File
}
+flush :: proc(f: ^File) -> Error {
+ if f != nil {
+ return io.flush(f.impl.stream)
+ }
+ return nil
+}
sync :: proc(f: ^File) -> Error {
return _sync(f)
}
-flush :: proc(f: ^File) -> Error {
- return _flush(f)
-}
-
truncate :: proc(f: ^File, size: i64) -> Error {
return _truncate(f, size)
}
diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin
index 890bbfc43..ddd827bce 100644
--- a/core/os/os2/file_linux.odin
+++ b/core/os/os2/file_linux.odin
@@ -33,6 +33,8 @@ _File :: struct {
name: string,
fd: int,
allocator: runtime.Allocator,
+
+ stream: io.Stream,
}
_file_allocator :: proc() -> runtime.Allocator {
@@ -73,6 +75,10 @@ _new_file :: proc(fd: uintptr, _: string) -> ^File {
file.impl.fd = int(fd)
file.impl.allocator = _file_allocator()
file.impl.name = _get_full_path(file.impl.fd, file.impl.allocator)
+ file.impl.stream = {
+ data = file,
+ procedure = _file_stream_proc,
+ }
return file
}
@@ -102,7 +108,7 @@ _name :: proc(f: ^File) -> string {
return f.impl.name if f != nil else ""
}
-_seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
+_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
res := unix.sys_lseek(f.impl.fd, offset, int(whence))
if res < 0 {
return -1, _get_platform_error(int(res))
@@ -110,18 +116,18 @@ _seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error
return res, nil
}
-_read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
+_read :: proc(f: ^File, p: []byte) -> (i64, Error) {
if len(p) == 0 {
return 0, nil
}
- n = unix.sys_read(f.impl.fd, &p[0], len(p))
+ n := unix.sys_read(f.impl.fd, &p[0], len(p))
if n < 0 {
return -1, _get_platform_error(n)
}
- return n, nil
+ return i64(n), nil
}
-_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
+_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
if offset < 0 {
return 0, .Invalid_Offset
}
@@ -132,30 +138,25 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if m < 0 {
return -1, _get_platform_error(m)
}
- n += m
+ n += i64(m)
b = b[m:]
offset += i64(m)
}
return
}
-_read_from :: proc(f: ^File, r: io.Reader) -> (n: i64, err: Error) {
- //TODO
- return
-}
-
-_write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
+_write :: proc(f: ^File, p: []byte) -> (i64, Error) {
if len(p) == 0 {
return 0, nil
}
- n = unix.sys_write(f.impl.fd, &p[0], uint(len(p)))
+ n := unix.sys_write(f.impl.fd, &p[0], uint(len(p)))
if n < 0 {
return -1, _get_platform_error(n)
}
- return int(n), nil
+ return i64(n), nil
}
-_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
+_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
if offset < 0 {
return 0, .Invalid_Offset
}
@@ -166,18 +167,13 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if m < 0 {
return -1, _get_platform_error(m)
}
- n += m
+ n += i64(m)
b = b[m:]
offset += i64(m)
}
return
}
-_write_to :: proc(f: ^File, w: io.Writer) -> (n: i64, err: Error) {
- //TODO
- return
-}
-
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
s: _Stat = ---
res := unix.sys_fstat(f.impl.fd, &s)
@@ -366,3 +362,49 @@ _is_dir_fd :: proc(fd: int) -> bool {
_temp_name_to_cstring :: proc(name: string) -> (cname: cstring) {
return strings.clone_to_cstring(name, context.temp_allocator)
}
+
+
+@(private="package")
+_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ f := (^File)(stream_data)
+ ferr: Error
+ i: int
+ switch mode {
+ case .Read:
+ n, ferr = _read(f, p)
+ err = error_to_io_error(ferr)
+ return
+ case .Read_At:
+ n, ferr = _read_at(f, p, offset)
+ err = error_to_io_error(ferr)
+ return
+ case .Write:
+ n, ferr = _write(f, p)
+ err = error_to_io_error(ferr)
+ return
+ case .Write_At:
+ n, ferr = _write_at(f, p, offset)
+ err = error_to_io_error(ferr)
+ return
+ case .Seek:
+ n, ferr = _seek(f, offset, whence)
+ err = error_to_io_error(ferr)
+ return
+ case .Size:
+ n, ferr = _file_size(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Flush:
+ ferr = _flush(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Close, .Destroy:
+ ferr = _close(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Query:
+ return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query})
+ }
+ return 0, .Empty
+}
+
diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin
index 7edbd68fa..da1e3344f 100644
--- a/core/os/os2/file_stream.odin
+++ b/core/os/os2/file_stream.odin
@@ -3,17 +3,15 @@ package os2
import "core:io"
to_stream :: proc(f: ^File) -> (s: io.Stream) {
- s.stream_data = f
- s.stream_vtable = &_file_stream_vtable
+ if f != nil {
+ assert(f.impl.stream.procedure != nil)
+ s = f.impl.stream
+ }
return
}
-to_writer :: proc(f: ^File) -> (s: io.Writer) {
- return {to_stream(f)}
-}
-to_reader :: proc(f: ^File) -> (s: io.Reader) {
- return {to_stream(f)}
-}
+to_writer :: to_stream
+to_reader :: to_stream
@(private)
@@ -23,71 +21,3 @@ error_to_io_error :: proc(ferr: Error) -> io.Error {
}
return ferr.(io.Error) or_else .Unknown
}
-
-
-@(private)
-_file_stream_vtable := io.Stream_VTable{
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = read(f, p)
- err = error_to_io_error(ferr)
- return
- },
- impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = read_at(f, p, offset)
- err = error_to_io_error(ferr)
- return
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = write_to(f, w)
- err = error_to_io_error(ferr)
- return
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = write(f, p)
- err = error_to_io_error(ferr)
- return
- },
- impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = write_at(f, p, offset)
- err = error_to_io_error(ferr)
- return
- },
- impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
- f := (^File)(s.stream_data)
- ferr: Error
- n, ferr = read_from(f, r)
- err = error_to_io_error(ferr)
- return
- },
- impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
- f := (^File)(s.stream_data)
- n, ferr := seek(f, offset, Seek_From(whence))
- err := error_to_io_error(ferr)
- return n, err
- },
- impl_size = proc(s: io.Stream) -> i64 {
- f := (^File)(s.stream_data)
- sz, _ := file_size(f)
- return sz
- },
- impl_flush = proc(s: io.Stream) -> io.Error {
- f := (^File)(s.stream_data)
- ferr := flush(f)
- return error_to_io_error(ferr)
- },
- impl_close = proc(s: io.Stream) -> io.Error {
- f := (^File)(s.stream_data)
- ferr := close(f)
- return error_to_io_error(ferr)
- },
-}
diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin
index e4ae4856a..600ecde21 100644
--- a/core/os/os2/file_windows.odin
+++ b/core/os/os2/file_windows.odin
@@ -38,6 +38,8 @@ _File :: struct {
wname: win32.wstring,
kind: _File_Kind,
+ stream: io.Stream,
+
allocator: runtime.Allocator,
rw_mutex: sync.RW_Mutex, // read write calls
@@ -144,6 +146,11 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
}
f.impl.kind = kind
+ f.impl.stream = {
+ data = f,
+ procedure = _file_stream_proc,
+ }
+
return f
}
@@ -181,7 +188,7 @@ _name :: proc(f: ^File) -> string {
return f.impl.name if f != nil else ""
}
-_seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
+_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
handle := _handle(f)
if handle == win32.INVALID_HANDLE {
return 0, .Invalid_File
@@ -208,7 +215,7 @@ _seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error
return i64(hi)<<32 + i64(dw_ptr), nil
}
-_read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
+_read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) {
if len(b) == 0 {
return 0, nil
@@ -274,7 +281,7 @@ _read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
n, err := read_console(handle, p[total_read:][:to_read])
total_read += n
if err != nil {
- return int(total_read), err
+ return i64(total_read), err
}
} else {
ok = win32.ReadFile(handle, &p[total_read], to_read, &single_read_length, nil)
@@ -287,11 +294,11 @@ _read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
}
}
- return int(total_read), nil
+ return i64(total_read), err
}
-_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
- pread :: proc(f: ^File, data: []byte, offset: i64) -> (n: int, err: Error) {
+_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
+ pread :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) {
buf := data
if len(buf) > MAX_RW {
buf = buf[:MAX_RW]
@@ -313,7 +320,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
err = _get_platform_error()
done = 0
}
- n = int(done)
+ n = i64(done)
return
}
@@ -329,12 +336,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return
}
-_read_from :: proc(f: ^File, r: io.Reader) -> (n: i64, err: Error) {
- // TODO(bill)
- return
-}
-
-_write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
+_write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
if len(p) == 0 {
return
}
@@ -352,17 +354,17 @@ _write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
e := win32.WriteFile(handle, &p[total_write], to_write, &single_write_length, nil)
if single_write_length <= 0 || !e {
- n = int(total_write)
+ n = i64(total_write)
err = _get_platform_error()
return
}
total_write += i64(single_write_length)
}
- return int(total_write), nil
+ return i64(total_write), nil
}
-_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
- pwrite :: proc(f: ^File, data: []byte, offset: i64) -> (n: int, err: Error) {
+_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
+ pwrite :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) {
buf := data
if len(buf) > MAX_RW {
buf = buf[:MAX_RW]
@@ -382,7 +384,7 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
err = _get_platform_error()
done = 0
}
- n = int(done)
+ n = i64(done)
return
}
@@ -397,11 +399,6 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return
}
-_write_to :: proc(f: ^File, w: io.Writer) -> (n: i64, err: Error) {
- // TODO(bill)
- return
-}
-
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
length: win32.LARGE_INTEGER
handle := _handle(f)
@@ -727,3 +724,51 @@ _is_dir :: proc(path: string) -> bool {
}
return false
}
+
+
+@(private="package")
+_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ f := (^File)(stream_data)
+ ferr: Error
+ i: int
+ switch mode {
+ case .Read:
+ n, ferr = _read(f, p)
+ err = error_to_io_error(ferr)
+ return
+ case .Read_At:
+ n, ferr = _read_at(f, p, offset)
+ err = error_to_io_error(ferr)
+ return
+ case .Write:
+ n, ferr = _write(f, p)
+ err = error_to_io_error(ferr)
+ return
+ case .Write_At:
+ n, ferr = _write_at(f, p, offset)
+ err = error_to_io_error(ferr)
+ return
+ case .Seek:
+ n, ferr = _seek(f, offset, whence)
+ err = error_to_io_error(ferr)
+ return
+ case .Size:
+ n, ferr = _file_size(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Flush:
+ ferr = _flush(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Close:
+ ferr = _close(f)
+ err = error_to_io_error(ferr)
+ return
+ case .Query:
+ return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Query})
+ case .Destroy:
+ return 0, .Empty
+ }
+ return 0, .Empty
+}
+
diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin
index 2dc667822..a2306784e 100644
--- a/core/os/os2/path_windows.odin
+++ b/core/os/os2/path_windows.odin
@@ -23,7 +23,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
fix_root_directory :: proc(p: string) -> (s: string, allocated: bool, err: runtime.Allocator_Error) {
if len(p) == len(`\\?\c:`) {
if is_path_separator(p[0]) && is_path_separator(p[1]) && p[2] == '?' && is_path_separator(p[3]) && p[5] == ':' {
- s = strings.concatenate_safe({p, `\`}, _file_allocator()) or_return
+ s = strings.concatenate({p, `\`}, _file_allocator()) or_return
allocated = true
return
}
diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin
index a2d68aeed..d8ba40fd0 100644
--- a/core/os/os_darwin.odin
+++ b/core/os/os_darwin.odin
@@ -314,15 +314,16 @@ Dirent :: struct {
Dir :: distinct rawptr // DIR*
+ADDRESS_FAMILY :: c.char
SOCKADDR :: struct #packed {
len: c.char,
- family: c.char,
+ family: ADDRESS_FAMILY,
sa_data: [14]c.char,
}
SOCKADDR_STORAGE_LH :: struct #packed {
len: c.char,
- family: c.char,
+ family: ADDRESS_FAMILY,
__ss_pad1: [6]c.char,
__ss_align: i64,
__ss_pad2: [112]c.char,
@@ -330,7 +331,7 @@ SOCKADDR_STORAGE_LH :: struct #packed {
sockaddr_in :: struct #packed {
sin_len: c.char,
- sin_family: c.char,
+ sin_family: ADDRESS_FAMILY,
sin_port: u16be,
sin_addr: in_addr,
sin_zero: [8]c.char,
@@ -338,7 +339,7 @@ sockaddr_in :: struct #packed {
sockaddr_in6 :: struct #packed {
sin6_len: c.char,
- sin6_family: c.char,
+ sin6_family: ADDRESS_FAMILY,
sin6_port: u16be,
sin6_flowinfo: c.uint,
sin6_addr: in6_addr,
@@ -355,7 +356,7 @@ in6_addr :: struct #packed {
Timeval :: struct {
seconds: i64,
- nanoseconds: int,
+ microseconds: int,
}
Linger :: struct {
@@ -440,7 +441,7 @@ foreign libc {
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
- @(link_name="__fcntl") _unix__fcntl :: proc(fd: Handle, cmd: c.int, #c_vararg args: ..any) -> c.int ---
+ @(link_name="__fcntl") _unix__fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
@(link_name="rename") _unix_rename :: proc(old: cstring, new: cstring) -> c.int ---
@(link_name="remove") _unix_remove :: proc(path: cstring) -> c.int ---
@@ -794,14 +795,14 @@ _readlink :: proc(path: string) -> (string, Errno) {
}
absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
- buf : [256]byte
- res := _unix__fcntl(fd, F_GETPATH, &buf[0])
- if res != 0 {
- return "", Errno(get_last_error())
+ buf: [DARWIN_MAXPATHLEN]byte
+ _, err := fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0])))
+ if err != ERROR_NONE {
+ return "", err
}
path := strings.clone_from_cstring(cstring(&buf[0]))
- return path, ERROR_NONE
+ return path, err
}
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
@@ -1068,7 +1069,7 @@ shutdown :: proc(sd: Socket, how: int) -> (Errno) {
}
fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
- result := _unix__fcntl(Handle(fd), c.int(cmd), c.int(arg))
+ result := _unix__fcntl(Handle(fd), c.int(cmd), uintptr(arg))
if result < 0 {
return 0, Errno(get_last_error())
}
diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin
index 3dc48087a..1a4c1fddb 100644
--- a/core/os/os_linux.odin
+++ b/core/os/os_linux.odin
@@ -241,7 +241,7 @@ socklen_t :: c.int
Timeval :: struct {
seconds: i64,
- nanoseconds: int,
+ microseconds: int,
}
// "Argv" arguments converted to Odin strings
@@ -432,6 +432,14 @@ AT_FDCWD :: ~uintptr(99) /* -100 */
AT_REMOVEDIR :: uintptr(0x200)
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
+pollfd :: struct {
+ fd: c.int,
+ events: c.short,
+ revents: c.short,
+}
+
+sigset_t :: distinct u64
+
foreign libc {
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
@@ -450,6 +458,7 @@ foreign libc {
@(link_name="execvp") _unix_execvp :: proc(path: cstring, argv: [^]cstring) -> int ---
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int ---
+ @(link_name="setenv") _unix_setenv :: proc(key: cstring, value: cstring, overwrite: c.int) -> c.int ---
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
@@ -885,8 +894,10 @@ get_env :: proc(key: string, allocator := context.allocator) -> (value: string)
set_env :: proc(key, value: string) -> Errno {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
- s := strings.concatenate({key, "=", value, "\x00"}, context.temp_allocator)
- res := _unix_putenv(strings.unsafe_string_to_cstring(s))
+ key_cstring := strings.clone_to_cstring(key, context.temp_allocator)
+ value_cstring := strings.clone_to_cstring(value, context.temp_allocator)
+ // NOTE(GoNZooo): `setenv` instead of `putenv` because it copies both key and value more commonly
+ res := _unix_setenv(key_cstring, value_cstring, 1)
if res < 0 {
return Errno(get_last_error())
}
@@ -1086,4 +1097,20 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
return 0, _get_errno(result)
}
return result, ERROR_NONE
-} \ No newline at end of file
+}
+
+poll :: proc(fds: []pollfd, timeout: int) -> (int, Errno) {
+ result := unix.sys_poll(raw_data(fds), uint(len(fds)), timeout)
+ if result < 0 {
+ return 0, _get_errno(result)
+ }
+ return result, ERROR_NONE
+}
+
+ppoll :: proc(fds: []pollfd, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) {
+ result := unix.sys_ppoll(raw_data(fds), uint(len(fds)), timeout, sigmask, size_of(sigset_t))
+ if result < 0 {
+ return 0, _get_errno(result)
+ }
+ return result, ERROR_NONE
+}
diff --git a/core/os/stream.odin b/core/os/stream.odin
index 9506ed3a3..2b4c83663 100644
--- a/core/os/stream.odin
+++ b/core/os/stream.odin
@@ -4,66 +4,60 @@ import "core:io"
stream_from_handle :: proc(fd: Handle) -> io.Stream {
s: io.Stream
- s.stream_data = rawptr(uintptr(fd))
- s.stream_vtable = &_file_stream_vtable
+ s.data = rawptr(uintptr(fd))
+ s.procedure = _file_stream_proc
return s
}
@(private)
-_file_stream_vtable := io.Stream_VTable{
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- fd := Handle(uintptr(s.stream_data))
- os_err: Errno
- n, os_err = read(fd, p)
- return
- },
- impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- when ODIN_OS == .Windows || ODIN_OS == .WASI {
- fd := Handle(uintptr(s.stream_data))
- os_err: Errno
- n, os_err = read_at(fd, p, offset)
- }
- return
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- fd := Handle(uintptr(s.stream_data))
- os_err: Errno
- n, os_err = write(fd, p)
- return
- },
- impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- when ODIN_OS == .Windows || ODIN_OS == .WASI {
- fd := Handle(uintptr(s.stream_data))
- os_err: Errno
- n, os_err = write_at(fd, p, offset)
- _ = os_err
- }
- return
- },
- impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
- fd := Handle(uintptr(s.stream_data))
- n, os_err := seek(fd, offset, int(whence))
- _ = os_err
- return n, nil
- },
- impl_size = proc(s: io.Stream) -> i64 {
- fd := Handle(uintptr(s.stream_data))
- sz, _ := file_size(fd)
- return sz
- },
- impl_flush = proc(s: io.Stream) -> io.Error {
+_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ fd := Handle(uintptr(stream_data))
+ n_int: int
+ os_err: Errno
+ switch mode {
+ case .Close:
+ close(fd)
+ case .Flush:
when ODIN_OS == .Windows {
- fd := Handle(uintptr(s.stream_data))
flush(fd)
} else {
// TOOD(bill): other operating systems
}
- return nil
- },
- impl_close = proc(s: io.Stream) -> io.Error {
- fd := Handle(uintptr(s.stream_data))
- close(fd)
- return nil
- },
+ case .Read:
+ n_int, os_err = read(fd, p)
+ n = i64(n_int)
+ if os_err != 0 {
+ err = .Unknown
+ }
+ case .Read_At:
+ when !(ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD) {
+ n_int, os_err = read_at(fd, p, offset)
+ n = i64(n_int)
+ }
+ case .Write:
+ n_int, os_err = write(fd, p)
+ n = i64(n_int)
+ case .Write_At:
+ when !(ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD) {
+ n_int, os_err = write_at(fd, p, offset)
+ n = i64(n_int)
+ }
+ case .Seek:
+ n, os_err = seek(fd, offset, int(whence))
+ case .Size:
+ n, os_err = file_size(fd)
+ case .Destroy:
+ err = .Empty
+ case .Query:
+ when ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD {
+ return io.query_utility({.Close, .Flush, .Read, .Write, .Seek, .Size, .Query})
+ } else {
+ return io.query_utility({.Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query})
+ }
+ }
+ if err == nil && os_err != 0 {
+ err = .Unknown
+ }
+ return
}
diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin
index f8343ead2..a88557e0e 100644
--- a/core/reflect/reflect.odin
+++ b/core/reflect/reflect.odin
@@ -132,7 +132,7 @@ type_info_core :: runtime.type_info_core
type_info_base_without_enum :: type_info_core
-when !ODIN_DISALLOW_RTTI {
+when !ODIN_NO_RTTI {
typeid_base :: runtime.typeid_base
typeid_core :: runtime.typeid_core
typeid_base_without_enum :: typeid_core
@@ -781,7 +781,7 @@ set_union_variant_raw_tag :: proc(a: any, tag: i64) {
tag_ptr := uintptr(a.data) + info.tag_offset
tag_any := any{rawptr(tag_ptr), info.tag_type.id}
- switch i in &tag_any {
+ switch &i in tag_any {
case u8: i = u8(tag)
case i8: i = i8(tag)
case u16: i = u16(tag)
@@ -1312,7 +1312,7 @@ relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid)
ptr_any := any{data, base_integer_id}
ptr: rawptr
- switch i in &ptr_any {
+ switch &i in ptr_any {
case u8: ptr = _handle(&i)
case u16: ptr = _handle(&i)
case u32: ptr = _handle(&i)
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index 058ca6161..83504c9ee 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -566,7 +566,7 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
return &type_table[n]
}
-when !ODIN_DISALLOW_RTTI {
+when !ODIN_NO_RTTI {
typeid_base :: proc "contextless" (id: typeid) -> typeid {
ti := type_info_of(id)
ti = type_info_base(ti)
diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin
index c5cb8cc07..9f2899bcc 100644
--- a/core/runtime/core_builtin.odin
+++ b/core/runtime/core_builtin.odin
@@ -112,7 +112,7 @@ remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_locatio
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
@builtin
pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
- assert(len(array) > 0, "", loc)
+ assert(len(array) > 0, loc=loc)
res = array[len(array)-1]
(^Raw_Dynamic_Array)(array).len -= 1
return res
@@ -136,7 +136,7 @@ pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
@builtin
pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
- assert(len(array) > 0, "", loc)
+ assert(len(array) > 0, loc=loc)
res = array[0]
if len(array) > 1 {
copy(array[0:], array[1:])
@@ -424,7 +424,7 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
- assert(condition=data != nil, loc=loc)
+ assert(data != nil, loc=loc)
data[a.len] = arg
}
a.len += 1
@@ -459,7 +459,7 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
- assert(condition=data != nil, loc=loc)
+ assert(data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
a.len += arg_len
@@ -472,7 +472,7 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
@builtin
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
args := transmute([]E)arg
- return append_elems(array=array, args=args, loc=loc)
+ return append_elems(array, ..args, loc=loc)
}
@@ -481,7 +481,7 @@ append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #ca
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
n_arg: int
for arg in args {
- n_arg, err = append(array = array, args = transmute([]E)(arg), loc = loc)
+ n_arg, err = append(array, ..transmute([]E)(arg), loc=loc)
n += n_arg
if err != nil {
return
diff --git a/core/runtime/default_allocators_js.odin b/core/runtime/default_allocators_js.odin
index cc70b963a..715073f08 100644
--- a/core/runtime/default_allocators_js.odin
+++ b/core/runtime/default_allocators_js.odin
@@ -1,5 +1,5 @@
//+build js
package runtime
-default_allocator_proc :: nil_allocator_proc
-default_allocator :: nil_allocator
+default_allocator_proc :: panic_allocator_proc
+default_allocator :: panic_allocator
diff --git a/core/runtime/default_allocators_nil.odin b/core/runtime/default_allocators_nil.odin
index f86990581..a340050eb 100644
--- a/core/runtime/default_allocators_nil.odin
+++ b/core/runtime/default_allocators_nil.odin
@@ -35,4 +35,52 @@ nil_allocator :: proc() -> Allocator {
when ODIN_OS == .Freestanding {
default_allocator_proc :: nil_allocator_proc
default_allocator :: nil_allocator
-} \ No newline at end of file
+}
+
+
+
+panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
+ size, alignment: int,
+ old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
+ switch mode {
+ case .Alloc:
+ if size > 0 {
+ panic("panic allocator, .Alloc called", loc=loc)
+ }
+ case .Alloc_Non_Zeroed:
+ if size > 0 {
+ panic("panic allocator, .Alloc_Non_Zeroed called", loc=loc)
+ }
+ case .Resize:
+ if size > 0 {
+ panic("panic allocator, .Resize called", loc=loc)
+ }
+ case .Free:
+ if old_memory != nil {
+ panic("panic allocator, .Free called", loc=loc)
+ }
+ case .Free_All:
+ panic("panic allocator, .Free_All called", loc=loc)
+
+ case .Query_Features:
+ set := (^Allocator_Mode_Set)(old_memory)
+ if set != nil {
+ set^ = {.Query_Features}
+ }
+ return nil, nil
+
+ case .Query_Info:
+ panic("panic allocator, .Query_Info called", loc=loc)
+ }
+
+ return nil, nil
+}
+
+panic_allocator :: proc() -> Allocator {
+ return Allocator{
+ procedure = nil_allocator_proc,
+ data = nil,
+ }
+}
+
+
diff --git a/core/runtime/default_allocators_wasi.odin b/core/runtime/default_allocators_wasi.odin
index 2e475e055..a7e6842a6 100644
--- a/core/runtime/default_allocators_wasi.odin
+++ b/core/runtime/default_allocators_wasi.odin
@@ -1,5 +1,5 @@
//+build wasi
package runtime
-default_allocator_proc :: nil_allocator_proc
-default_allocator :: nil_allocator
+default_allocator_proc :: panic_allocator_proc
+default_allocator :: panic_allocator
diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin
index 05c03028f..d34c29d4b 100644
--- a/core/runtime/dynamic_map_internal.odin
+++ b/core/runtime/dynamic_map_internal.odin
@@ -414,68 +414,21 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
tk := map_cell_index_dynamic(sk, info.ks, 1)
tv := map_cell_index_dynamic(sv, info.vs, 1)
- for {
- hp := &hs[pos]
- element_hash := hp^
+ swap_loop: for {
+ element_hash := hs[pos]
if map_hash_is_empty(element_hash) {
- kp := map_cell_index_dynamic(ks, info.ks, pos)
- vp := map_cell_index_dynamic(vs, info.vs, pos)
- intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
- hp^ = h
+ k_dst := map_cell_index_dynamic(ks, info.ks, pos)
+ v_dst := map_cell_index_dynamic(vs, info.vs, pos)
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
+ hs[pos] = h
- return result if result != 0 else vp
+ return result if result != 0 else v_dst
}
if map_hash_is_deleted(element_hash) {
- next_pos := (pos + 1) & mask
-
- // backward shift
- for !map_hash_is_empty(hs[next_pos]) {
- probe_distance := map_probe_distance(m^, hs[next_pos], next_pos)
- if probe_distance == 0 {
- break
- }
- probe_distance -= 1
-
- kp := map_cell_index_dynamic(ks, info.ks, pos)
- vp := map_cell_index_dynamic(vs, info.vs, pos)
- kn := map_cell_index_dynamic(ks, info.ks, next_pos)
- vn := map_cell_index_dynamic(vs, info.vs, next_pos)
-
- if distance > probe_distance {
- if result == 0 {
- result = vp
- }
- // move stored into pos; store next
- intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
- hs[pos] = h
-
- intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(kn), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(vn), size_of_v)
- h = hs[next_pos]
- } else {
- // move next back 1
- intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(kn), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(vn), size_of_v)
- hs[pos] = hs[next_pos]
- distance = probe_distance
- }
- hs[next_pos] = 0
- pos = (pos + 1) & mask
- next_pos = (next_pos + 1) & mask
- distance += 1
- }
-
- kp := map_cell_index_dynamic(ks, info.ks, pos)
- vp := map_cell_index_dynamic(vs, info.vs, pos)
- intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
- intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
- hs[pos] = h
-
- return result if result != 0 else vp
+ break swap_loop
}
if probe_distance := map_probe_distance(m^, element_hash, pos); distance > probe_distance {
@@ -495,8 +448,8 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(tv), size_of_v)
th := h
- h = hp^
- hp^ = th
+ h = hs[pos]
+ hs[pos] = th
distance = probe_distance
}
@@ -504,6 +457,103 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
pos = (pos + 1) & mask
distance += 1
}
+
+ // backward shift loop
+ hs[pos] = 0
+ look_ahead: uintptr = 1
+ for {
+ la_pos := (pos + look_ahead) & mask
+ element_hash := hs[la_pos]
+
+ if map_hash_is_deleted(element_hash) {
+ look_ahead += 1
+ hs[la_pos] = 0
+ continue
+ }
+
+ k_dst := map_cell_index_dynamic(ks, info.ks, pos)
+ v_dst := map_cell_index_dynamic(vs, info.vs, pos)
+
+ if map_hash_is_empty(element_hash) {
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
+ hs[pos] = h
+
+ return result if result != 0 else v_dst
+ }
+
+ k_src := map_cell_index_dynamic(ks, info.ks, la_pos)
+ v_src := map_cell_index_dynamic(vs, info.vs, la_pos)
+ probe_distance := map_probe_distance(m^, element_hash, la_pos)
+
+ if probe_distance < look_ahead {
+ // probed can be made ideal while placing saved (ending condition)
+ if result == 0 {
+ result = v_dst
+ }
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
+ hs[pos] = h
+
+ // This will be an ideal move
+ pos = (la_pos - probe_distance) & mask
+ look_ahead -= probe_distance
+
+ // shift until we hit ideal/empty
+ for probe_distance != 0 {
+ k_dst = map_cell_index_dynamic(ks, info.ks, pos)
+ v_dst = map_cell_index_dynamic(vs, info.vs, pos)
+
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k_src), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v_src), size_of_v)
+ hs[pos] = element_hash
+ hs[la_pos] = 0
+
+ pos = (pos + 1) & mask
+ la_pos = (la_pos + 1) & mask
+ look_ahead = (la_pos - pos) & mask
+ element_hash = hs[la_pos]
+ if map_hash_is_empty(element_hash) {
+ return
+ }
+
+ probe_distance = map_probe_distance(m^, element_hash, la_pos)
+ if probe_distance == 0 {
+ return
+ }
+ // can be ideal?
+ if probe_distance < look_ahead {
+ pos = (la_pos - probe_distance) & mask
+ }
+ k_src = map_cell_index_dynamic(ks, info.ks, la_pos)
+ v_src = map_cell_index_dynamic(vs, info.vs, la_pos)
+ }
+ return
+ } else if distance < probe_distance - look_ahead {
+ // shift back probed
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k_src), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v_src), size_of_v)
+ hs[pos] = element_hash
+ hs[la_pos] = 0
+ } else {
+ // place saved, save probed
+ if result == 0 {
+ result = v_dst
+ }
+ intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
+ hs[pos] = h
+
+ intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(k_src), size_of_k)
+ intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(v_src), size_of_v)
+ h = hs[la_pos]
+ hs[la_pos] = 0
+ distance = probe_distance - look_ahead
+ }
+
+ pos = (pos + 1) & mask
+ distance += 1
+ }
}
@(require_results)
@@ -696,49 +746,19 @@ map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #n
m.len -= 1
ok = true
- { // coalesce tombstones
- // HACK NOTE(bill): This is an ugly bodge but it is coalescing the tombstone slots
- mask := (uintptr(1)<<map_log2_cap(m^)) - 1
- curr_index := uintptr(index)
-
- // TODO(bill): determine a good value for this empirically
- // if we do not implement backward shift deletion
- PROBE_COUNT :: 8
- for _ in 0..<PROBE_COUNT {
- next_index := (curr_index + 1) & mask
- if next_index == index {
- // looped around
- break
- }
-
- // if the next element is empty or has zero probe distance, then any lookup
- // will always fail on the next, so we can clear both of them
- hash := hs[next_index]
- if map_hash_is_empty(hash) || map_probe_distance(m^, hash, next_index) == 0 {
- hs[curr_index] = 0
- return
- }
-
- // now the next element will have a probe count of at least one,
- // so it can use the delete slot instead
- hs[curr_index] = hs[next_index]
-
- mem_copy_non_overlapping(
- rawptr(map_cell_index_dynamic(ks, info.ks, curr_index)),
- rawptr(map_cell_index_dynamic(ks, info.ks, next_index)),
- int(info.ks.size_of_type),
- )
- mem_copy_non_overlapping(
- rawptr(map_cell_index_dynamic(vs, info.vs, curr_index)),
- rawptr(map_cell_index_dynamic(vs, info.vs, next_index)),
- int(info.vs.size_of_type),
- )
-
- curr_index = next_index
- }
+ mask := (uintptr(1)<<map_log2_cap(m^)) - 1
+ curr_index := uintptr(index)
+ next_index := (curr_index + 1) & mask
+ // if the next element is empty or has zero probe distance, then any lookup
+ // will always fail on the next, so we can clear both of them
+ hash := hs[next_index]
+ if map_hash_is_empty(hash) || map_probe_distance(m^, hash, next_index) == 0 {
+ hs[curr_index] = 0
+ } else {
hs[curr_index] |= TOMBSTONE_MASK
}
+
return
}
diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin
index 8539c724d..c189642af 100644
--- a/core/runtime/error_checks.odin
+++ b/core/runtime/error_checks.odin
@@ -22,7 +22,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
+ handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Index ")
print_i64(i64(index))
@@ -83,7 +83,7 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
+ handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Invalid dynamic array indices ")
print_i64(i64(low))
@@ -104,7 +104,7 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
+ handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Matrix indices [")
print_i64(i64(row_index))
@@ -122,13 +122,13 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
}
-when ODIN_DISALLOW_RTTI {
+when ODIN_NO_RTTI {
type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) {
if ok {
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32) {
+ handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Invalid type assertion\n")
type_assertion_trap()
@@ -141,7 +141,7 @@ when ODIN_DISALLOW_RTTI {
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32) {
+ handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Invalid type assertion\n")
type_assertion_trap()
@@ -154,7 +154,7 @@ when ODIN_DISALLOW_RTTI {
return
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) {
+ handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) -> ! {
print_caller_location(Source_Code_Location{file, line, column, ""})
print_string(" Invalid type assertion from ")
print_typeid(from)
@@ -199,7 +199,7 @@ when ODIN_DISALLOW_RTTI {
}
@(cold)
- handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
+ handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! {
actual := variant_type(from, from_data)
@@ -225,7 +225,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio
return
}
@(cold)
- handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) {
+ handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) -> ! {
print_caller_location(loc)
print_string(" Invalid slice length for make: ")
print_i64(i64(len))
@@ -240,7 +240,7 @@ make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #
return
}
@(cold)
- handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) {
+ handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) -> ! {
print_caller_location(loc)
print_string(" Invalid dynamic array parameters for make: ")
print_i64(i64(len))
@@ -257,7 +257,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca
return
}
@(cold)
- handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) {
+ handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) -> ! {
print_caller_location(loc)
print_string(" Invalid map capacity for make: ")
print_i64(i64(cap))
diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin
index 71ad9386a..ad8a40acf 100644
--- a/core/runtime/internal.odin
+++ b/core/runtime/internal.odin
@@ -566,16 +566,37 @@ max_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 {
}
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
- r, i := real(x), imag(x)
- return f16(intrinsics.sqrt(f32(r*r + i*i)))
+ p, q := abs(real(x)), abs(imag(x))
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * f16(intrinsics.sqrt(f32(1 + q*q)))
}
abs_complex64 :: #force_inline proc "contextless" (x: complex64) -> f32 {
- r, i := real(x), imag(x)
- return intrinsics.sqrt(r*r + i*i)
+ p, q := abs(real(x)), abs(imag(x))
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * intrinsics.sqrt(1 + q*q)
}
abs_complex128 :: #force_inline proc "contextless" (x: complex128) -> f64 {
- r, i := real(x), imag(x)
- return intrinsics.sqrt(r*r + i*i)
+ p, q := abs(real(x)), abs(imag(x))
+ if p < q {
+ p, q = q, p
+ }
+ if p == 0 {
+ return 0
+ }
+ q = q / p
+ return p * intrinsics.sqrt(1 + q*q)
}
abs_quaternion64 :: #force_inline proc "contextless" (x: quaternion64) -> f16 {
r, i, j, k := real(x), imag(x), jmag(x), kmag(x)
diff --git a/core/runtime/print.odin b/core/runtime/print.odin
index 326a29667..732ed9c12 100644
--- a/core/runtime/print.odin
+++ b/core/runtime/print.odin
@@ -5,7 +5,7 @@ _INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
@(private="file")
_INTEGER_DIGITS_VAR := _INTEGER_DIGITS
-when !ODIN_DISALLOW_RTTI {
+when !ODIN_NO_RTTI {
print_any_single :: proc "contextless" (arg: any) {
x := arg
if loc, ok := x.(Source_Code_Location); ok {
@@ -234,7 +234,7 @@ print_caller_location :: proc "contextless" (using loc: Source_Code_Location) {
}
}
print_typeid :: proc "contextless" (id: typeid) {
- when ODIN_DISALLOW_RTTI {
+ when ODIN_NO_RTTI {
if id == nil {
print_string("nil")
} else {
diff --git a/core/slice/ptr.odin b/core/slice/ptr.odin
index e2f1c3e7b..b17a27dc8 100644
--- a/core/slice/ptr.odin
+++ b/core/slice/ptr.odin
@@ -1,7 +1,7 @@
package slice
import "core:builtin"
-import "core:mem"
+import "core:runtime"
ptr_add :: proc(p: $P/^$T, x: int) -> ^T {
return ([^]T)(p)[x:]
@@ -27,9 +27,9 @@ ptr_swap_non_overlapping :: proc(x, y: rawptr, len: int) {
a := rawptr(uintptr(x) + uintptr(i))
b := rawptr(uintptr(y) + uintptr(i))
- mem.copy(t, a, BLOCK_SIZE)
- mem.copy(a, b, BLOCK_SIZE)
- mem.copy(b, t, BLOCK_SIZE)
+ runtime.mem_copy(t, a, BLOCK_SIZE)
+ runtime.mem_copy(a, b, BLOCK_SIZE)
+ runtime.mem_copy(b, t, BLOCK_SIZE)
}
if i < len {
@@ -38,9 +38,9 @@ ptr_swap_non_overlapping :: proc(x, y: rawptr, len: int) {
a := rawptr(uintptr(x) + uintptr(i))
b := rawptr(uintptr(y) + uintptr(i))
- mem.copy(t, a, rem)
- mem.copy(a, b, rem)
- mem.copy(b, t, rem)
+ runtime.mem_copy(t, a, rem)
+ runtime.mem_copy(a, b, rem)
+ runtime.mem_copy(b, t, rem)
}
}
@@ -59,9 +59,9 @@ ptr_swap_overlapping :: proc(x, y: rawptr, len: int) {
for n := len; n > 0; n -= N {
m := builtin.min(n, N)
- mem.copy(&buffer, a, m)
- mem.copy(a, b, m)
- mem.copy(b, &buffer, m)
+ runtime.mem_copy(&buffer, a, m)
+ runtime.mem_copy(a, b, m)
+ runtime.mem_copy(b, &buffer, m)
a, b = a[N:], b[N:]
}
diff --git a/core/slice/slice.odin b/core/slice/slice.odin
index 412c90fc8..9a810141d 100644
--- a/core/slice/slice.odin
+++ b/core/slice/slice.odin
@@ -3,12 +3,12 @@ package slice
import "core:intrinsics"
import "core:builtin"
import "core:math/bits"
-import "core:mem"
+import "core:runtime"
_ :: intrinsics
_ :: builtin
_ :: bits
-_ :: mem
+_ :: runtime
/*
Turn a pointer and a length into a slice.
@@ -164,7 +164,7 @@ equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) {
return false
}
when intrinsics.type_is_simple_compare(E) {
- return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
+ return runtime.memory_compare(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
} else {
for i in 0..<len(a) {
if a[i] != b[i] {
@@ -180,7 +180,7 @@ simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_comp
if len(a) != len(b) {
return false
}
- return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
+ return runtime.memory_compare(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
}
/*
@@ -220,6 +220,12 @@ has_suffix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_c
return false
}
+zero :: proc(array: $T/[]$E) #no_bounds_check {
+ if len(array) > 0 {
+ intrinsics.mem_zero(raw_data(array), size_of(E)*len(array))
+ }
+}
+
fill :: proc(array: $T/[]$E, value: E) #no_bounds_check {
if len(array) <= 0 {
return
@@ -250,7 +256,7 @@ swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) {
}
@(require_results)
-concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, err: mem.Allocator_Error) #optional_allocator_error {
+concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, err: runtime.Allocator_Error) #optional_allocator_error {
if len(a) == 0 {
return
}
@@ -268,7 +274,7 @@ concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, er
// copies a slice into a new slice
@(require_results)
-clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, mem.Allocator_Error) #optional_allocator_error {
+clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([]E, len(a), allocator)
copy(d[:], a)
return d, err
@@ -276,7 +282,7 @@ clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, mem.Allocator
// copies slice into a new dynamic array
-clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> ([dynamic]E, mem.Allocator_Error) #optional_allocator_error {
+clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> ([dynamic]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([dynamic]E, len(a), allocator)
copy(d[:], a)
return d, err
@@ -286,12 +292,12 @@ to_dynamic :: clone_to_dynamic
// Converts slice into a dynamic array without cloning or allocating memory
@(require_results)
into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E {
- s := transmute(mem.Raw_Slice)a
- d := mem.Raw_Dynamic_Array{
+ s := transmute(runtime.Raw_Slice)a
+ d := runtime.Raw_Dynamic_Array{
data = s.data,
len = 0,
cap = s.len,
- allocator = mem.nil_allocator(),
+ allocator = runtime.nil_allocator(),
}
return transmute([dynamic]E)d
}
@@ -373,7 +379,7 @@ as_ptr :: proc(array: $T/[]$E) -> [^]E {
@(require_results)
-mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> (r: []V, err: mem.Allocator_Error) #optional_allocator_error {
+mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> (r: []V, err: runtime.Allocator_Error) #optional_allocator_error {
r = make([]V, len(s), allocator) or_return
for v, i in s {
r[i] = f(v)
@@ -402,7 +408,7 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
}
@(require_results)
-scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> (res: []V, err: mem.Allocator_Error) #optional_allocator_error {
+scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> (res: []V, err: runtime.Allocator_Error) #optional_allocator_error {
if len(s) == 0 { return }
res = make([]V, len(s), allocator) or_return
diff --git a/core/strings/builder.odin b/core/strings/builder.odin
index edde4b297..28c56f6f9 100644
--- a/core/strings/builder.odin
+++ b/core/strings/builder.odin
@@ -164,36 +164,27 @@ builder_init :: proc{
builder_init_len_cap,
}
@(private)
-_builder_stream_vtable_obj := io.Stream_VTable{
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Builder)(s.stream_data)
- n = write_bytes(b, p)
- if n < len(p) {
+_builder_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ b := (^Builder)(stream_data)
+ #partial switch mode {
+ case .Write:
+ n = i64(write_bytes(b, p))
+ if n < i64(len(p)) {
err = .EOF
}
return
- },
- impl_write_byte = proc(s: io.Stream, c: byte) -> (err: io.Error) {
- b := (^Builder)(s.stream_data)
- n := write_byte(b, c)
- if n == 0 {
- err = .EOF
- }
+ case .Size:
+ n = i64(len(b.buf))
return
- },
- impl_size = proc(s: io.Stream) -> i64 {
- b := (^Builder)(s.stream_data)
- return i64(len(b.buf))
- },
- impl_destroy = proc(s: io.Stream) -> io.Error {
- b := (^Builder)(s.stream_data)
+ case .Destroy:
builder_destroy(b)
- return .None
- },
+ return
+ case .Query:
+ return io.query_utility({.Write, .Size, .Destroy, .Query})
+ }
+ return 0, .Empty
}
-// NOTE(dweiler): Work around a miscompilation bug on Linux still.
-@(private)
-_builder_stream_vtable := &_builder_stream_vtable_obj
+
/*
Returns an io.Stream from a Builder
@@ -204,7 +195,7 @@ Returns:
- res: the io.Stream
*/
to_stream :: proc(b: ^Builder) -> (res: io.Stream) {
- return io.Stream{stream_vtable=_builder_stream_vtable, stream_data=b}
+ return io.Stream{procedure=_builder_stream_proc, data=b}
}
/*
Returns an io.Writer from a Builder
diff --git a/core/strings/reader.odin b/core/strings/reader.odin
index 081e59b4b..bb49bf917 100644
--- a/core/strings/reader.odin
+++ b/core/strings/reader.odin
@@ -35,8 +35,8 @@ Returns:
- s: An io.Stream for the given Reader
*/
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
- s.stream_data = r
- s.stream_vtable = &_reader_vtable
+ s.data = r
+ s.procedure = _reader_proc
return
}
/*
@@ -294,41 +294,21 @@ This VTable is used by the Reader struct to provide its functionality
as an `io.Stream`.
*/
@(private)
-_reader_vtable := io.Stream_VTable{
- impl_size = proc(s: io.Stream) -> i64 {
- r := (^Reader)(s.stream_data)
- return reader_size(r)
- },
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read(r, p)
- },
- impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_at(r, p, off)
- },
- impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_byte(r)
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- r := (^Reader)(s.stream_data)
- return reader_unread_byte(r)
- },
- impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_read_rune(r)
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- r := (^Reader)(s.stream_data)
- return reader_unread_rune(r)
- },
- impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_seek(r, offset, whence)
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- r := (^Reader)(s.stream_data)
- return reader_write_to(r, w)
- },
+_reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ r := (^Reader)(stream_data)
+ #partial switch mode {
+ case .Size:
+ n = reader_size(r)
+ return
+ case .Read:
+ return io._i64_err(reader_read(r, p))
+ case .Read_At:
+ return io._i64_err(reader_read_at(r, p, offset))
+ case .Seek:
+ n, err = reader_seek(r, offset, whence)
+ return
+ case .Query:
+ return io.query_utility({.Size, .Read, .Read_At, .Seek, .Query})
+ }
+ return 0, .Empty
}
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index 6daa5f9c9..66a75f96a 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -1194,7 +1194,7 @@ Output:
split_lines :: proc(s: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error {
sep :: "\n"
lines := _split(s, sep, 0, -1, allocator) or_return
- for line in &lines {
+ for &line in lines {
line = _trim_cr(line)
}
return lines, nil
@@ -1234,7 +1234,7 @@ Output:
split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error {
sep :: "\n"
lines := _split(s, sep, 0, n, allocator) or_return
- for line in &lines {
+ for &line in lines {
line = _trim_cr(line)
}
return lines, nil
@@ -1273,7 +1273,7 @@ Output:
split_lines_after :: proc(s: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error {
sep :: "\n"
lines := _split(s, sep, len(sep), -1, allocator) or_return
- for line in &lines {
+ for &line in lines {
line = _trim_cr(line)
}
return lines, nil
@@ -1314,7 +1314,7 @@ Output:
split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error {
sep :: "\n"
lines := _split(s, sep, len(sep), n, allocator) or_return
- for line in &lines {
+ for &line in lines {
line = _trim_cr(line)
}
return lines, nil
diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin
index b8bcfad70..5e71f6336 100644
--- a/core/sync/primitives.odin
+++ b/core/sync/primitives.odin
@@ -7,10 +7,21 @@ current_thread_id :: proc "contextless" () -> int {
return _current_thread_id()
}
-// A Mutex is a mutual exclusion lock
-// The zero value for a Mutex is an unlocked mutex
+// A Mutex is a [[mutual exclusion lock; https://en.wikipedia.org/wiki/Mutual_exclusion]]
+// It can be used to prevent more than one thread from executing the same piece of code,
+// and thus prevent access to same piece of memory by multiple threads, at the same time.
//
-// A Mutex must not be copied after first use
+// A Mutex's zero value represents an initial, *unlocked* state.
+//
+// If another thread tries to take the lock while another thread holds it, it will pause
+// until the lock is released. Code or memory that is "surrounded" by a mutex lock is said
+// to be "guarded by a mutex".
+//
+// A Mutex must not be copied after first use (e.g., after locking it the first time).
+// This is because, in order to coordinate with other threads, all threads must watch
+// the same memory address to know when the lock has been released. Trying to use a
+// copy of the lock at a different memory address will result in broken and unsafe
+// behavior. For this reason, Mutexes are marked as `#no_copy`.
Mutex :: struct #no_copy {
impl: _Mutex,
}
diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin
index abdcf0b92..3083c084b 100644
--- a/core/sys/unix/syscalls_linux.odin
+++ b/core/sys/unix/syscalls_linux.odin
@@ -1567,6 +1567,23 @@ MADV_HWPOISON :: 100
// pipe2 flags
O_CLOEXEC :: 0o2000000
+// poll events
+POLLIN :: 0x0001
+POLLPRI :: 0x0002
+POLLOUT :: 0x0004
+POLLERR :: 0x0008
+POLLHUP :: 0x0010
+POLLNVAL :: 0x0020
+POLLRDNORM :: 0x0040
+POLLRDBAND :: 0x0080
+POLLWRNORM :: 0x0100
+POLLWRBAND :: 0x0200
+POLLMSG :: 0x0400
+POLLREMOVE :: 0x1000
+POLLRDHUP :: 0x2000
+POLLFREE :: 0x4000
+POLL_BUSY_LOOP :: 0x8000
+
// perf event data
Perf_Sample :: struct #raw_union {
period: u64,
@@ -2057,6 +2074,23 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int {
return int(intrinsics.syscall(SYS_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg)))
}
+sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int {
+ // NOTE: specialcased here because `arm64` does not have `poll`
+ when ODIN_ARCH == .arm64 {
+ seconds := i64(timeout / 1_000)
+ nanoseconds := i64((timeout % 1000) * 1_000_000)
+ timeout_spec := timespec{seconds, nanoseconds}
+
+ return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(&timeout_spec), uintptr(0), uintptr(8)))
+ } else {
+ return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout)))
+ }
+}
+
+sys_ppoll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: rawptr, sigmask: rawptr, sigsetsize: uint) -> int {
+ return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(timeout), uintptr(sigmask), uintptr(sigsetsize)))
+}
+
get_errno :: proc "contextless" (res: int) -> i32 {
if res < 0 && res > -4096 {
return i32(-res)
diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin
index beed3a7e5..fcd9e55ed 100644
--- a/core/sys/windows/kernel32.odin
+++ b/core/sys/windows/kernel32.odin
@@ -159,6 +159,11 @@ foreign kernel32 {
WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD ---
Sleep :: proc(dwMilliseconds: DWORD) ---
GetProcessId :: proc(handle: HANDLE) -> DWORD ---
+ CopyFileW :: proc(
+ lpExistingFileName: LPCWSTR,
+ lpNewFileName: LPCWSTR,
+ bFailIfExists: BOOL,
+ ) -> BOOL ---
CopyFileExW :: proc(
lpExistingFileName: LPCWSTR,
lpNewFileName: LPCWSTR,
diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin
index 631ef4241..7b9cf1b89 100644
--- a/core/sys/windows/ws2_32.odin
+++ b/core/sys/windows/ws2_32.odin
@@ -206,4 +206,14 @@ foreign ws2_32 {
optval: ^c_char,
optlen: ^c_int,
) -> c_int ---
+ // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohl)
+ ntohl :: proc(netlong: c_ulong) -> c_ulong ---
+ // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs)
+ ntohs :: proc(netshort: c_ushort) -> c_ushort ---
+ // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl)
+ @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")
+ htonl :: proc(hostlong: c_ulong) -> c_ulong ---
+ // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons)
+ @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")
+ htons :: proc(hostshort: c_ushort) -> c_ushort ---
}
diff --git a/core/testing/runner_windows.odin b/core/testing/runner_windows.odin
index 525eae685..17bcfce26 100644
--- a/core/testing/runner_windows.odin
+++ b/core/testing/runner_windows.odin
@@ -191,7 +191,7 @@ run_internal_test :: proc(t: ^T, it: Internal_Test) {
global_exception_handler = win32.AddVectoredExceptionHandler(0, exception_handler_proc)
context.assertion_failure_proc = proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! {
- errorf(t=global_current_t, format="%s %s", args={prefix, message}, loc=loc)
+ errorf(global_current_t, "%s %s", prefix, message, loc=loc)
intrinsics.trap()
}
diff --git a/core/testing/testing.odin b/core/testing/testing.odin
index 37f9fe4d9..1ba05315c 100644
--- a/core/testing/testing.odin
+++ b/core/testing/testing.odin
@@ -4,6 +4,9 @@ import "core:fmt"
import "core:io"
import "core:time"
import "core:intrinsics"
+import "core:reflect"
+
+_ :: reflect // alias reflect to nothing to force visibility for -vet
// IMPORTANT NOTE: Compiler requires this layout
Test_Signature :: proc(^T)
@@ -46,15 +49,15 @@ errorf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) {
}
fail :: proc(t: ^T, loc := #caller_location) {
- error(t=t, args={"FAIL"}, loc=loc)
+ error(t, "FAIL", loc=loc)
t.error_count += 1
}
fail_now :: proc(t: ^T, msg := "", loc := #caller_location) {
if msg != "" {
- error(t=t, args={"FAIL:", msg}, loc=loc)
+ error(t, "FAIL:", msg, loc=loc)
} else {
- error(t=t, args={"FAIL"}, loc=loc)
+ error(t, "FAIL", loc=loc)
}
t.error_count += 1
if t._fail_now != nil {
@@ -84,14 +87,14 @@ cleanup :: proc(t: ^T, procedure: proc(rawptr), user_data: rawptr) {
expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bool {
if !ok {
- error(t=t, args={msg}, loc=loc)
+ error(t, msg, loc=loc)
}
return ok
}
expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> bool where intrinsics.type_is_comparable(T) {
- ok := value == expected
+ ok := value == expected || reflect.is_nil(value) && reflect.is_nil(expected)
if !ok {
- errorf(t=t, format="expected %v, got %v", args={expected, value}, loc=loc)
+ errorf(t, "expected %v, got %v", expected, value, loc=loc)
}
return ok
}
@@ -100,4 +103,4 @@ expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> boo
set_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location) {
_fail_timeout(t, duration, loc)
-} \ No newline at end of file
+}
diff --git a/core/text/edit/text_edit.odin b/core/text/edit/text_edit.odin
index c49a5d0d1..8520ba674 100644
--- a/core/text/edit/text_edit.odin
+++ b/core/text/edit/text_edit.odin
@@ -113,15 +113,16 @@ set_text :: proc(s: ^State, text: string) {
}
-undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) {
+undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator_Error {
text := string(s.builder.buf[:])
- item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator))
+ item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator) or_return)
item.selection = s.selection
item.len = len(text)
#no_bounds_check {
runtime.copy(item.text[:len(text)], text)
}
- append(undo, item)
+ append(undo, item) or_return
+ return nil
}
undo :: proc(s: ^State, undo, redo: ^[dynamic]^Undo_State) {
diff --git a/core/text/i18n/i18n.odin b/core/text/i18n/i18n.odin
index 9d030db16..8513f30c8 100644
--- a/core/text/i18n/i18n.odin
+++ b/core/text/i18n/i18n.odin
@@ -170,8 +170,8 @@ destroy :: proc(catalog: ^Translation = ACTIVE, allocator := context.allocator)
return
}
- for section in &catalog.k_v {
- for key in &catalog.k_v[section] {
+ for section in catalog.k_v {
+ for key in catalog.k_v[section] {
delete(catalog.k_v[section][key])
}
delete(catalog.k_v[section])
diff --git a/core/text/match/strlib.odin b/core/text/match/strlib.odin
index b8c2861fa..654996bc7 100644
--- a/core/text/match/strlib.odin
+++ b/core/text/match/strlib.odin
@@ -266,6 +266,7 @@ match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error)
return INVALID, .Invalid_Pattern_Capture
}
+
schar, ssize := utf8_peek(ms.src[s:]) or_return
pchar, psize := utf8_peek(ms.pattern[p:]) or_return
@@ -274,9 +275,9 @@ match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error)
return INVALID, .OK
}
- s_begin := s
cont := 1
- s := s + ssize
+ s := s
+ s += ssize
begin := pchar
end, _ := utf8_peek(ms.pattern[p + psize:]) or_return
diff --git a/core/text/table/table.odin b/core/text/table/table.odin
index df93ee44e..8d96cb26f 100644
--- a/core/text/table/table.odin
+++ b/core/text/table/table.odin
@@ -9,12 +9,10 @@
package text_table
import "core:io"
-import "core:os"
import "core:fmt"
import "core:mem"
import "core:mem/virtual"
import "core:runtime"
-import "core:strings"
Cell :: struct {
text: string,
@@ -116,7 +114,7 @@ set_cell_alignment :: proc(tbl: ^Table, row, col: int, alignment: Cell_Alignment
format :: proc(tbl: ^Table, _fmt: string, args: ..any, loc := #caller_location) -> string {
context.allocator = tbl.format_allocator
- return fmt.aprintf(fmt = _fmt, args = args)
+ return fmt.aprintf(_fmt, ..args)
}
header :: proc(tbl: ^Table, values: ..any, loc := #caller_location) {
diff --git a/core/thread/thread_pool.odin b/core/thread/thread_pool.odin
index 820de8ad4..1a4119e5f 100644
--- a/core/thread/thread_pool.odin
+++ b/core/thread/thread_pool.odin
@@ -81,7 +81,7 @@ pool_destroy :: proc(pool: ^Pool) {
delete(pool.tasks)
delete(pool.tasks_done)
- for t in &pool.threads {
+ for &t in pool.threads {
destroy(t)
}
diff --git a/core/unicode/tools/generate_entity_table.odin b/core/unicode/tools/generate_entity_table.odin
index 328ba9091..fb4e4c2a4 100644
--- a/core/unicode/tools/generate_entity_table.odin
+++ b/core/unicode/tools/generate_entity_table.odin
@@ -221,7 +221,7 @@ named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) {
delete(entity_map)
delete(names)
- for name in &names {
+ for &name in names {
free(&name)
}
}