aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-01-08 19:11:49 +0100
committerLaytan Laats <laytanlaats@hotmail.com>2024-01-08 19:20:06 +0100
commitce8801c37ff07ff628c6fc239da38d78e89a23bc (patch)
tree154695530e44a877652eb7fe0f9d2102cb831275
parentf3dc1f6e3bc44831864b832153089d009191ce9c (diff)
c/libc: add `to_stream` proc
Adds the `to_stream` procedure to `core:c/libc` to improve usability of the core collection when you have to use libc.
-rw-r--r--core/c/libc/stdio.odin101
1 files changed, 101 insertions, 0 deletions
diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin
index 94007595c..39969e4a8 100644
--- a/core/c/libc/stdio.odin
+++ b/core/c/libc/stdio.odin
@@ -1,5 +1,7 @@
package libc
+import "core:io"
+
when ODIN_OS == .Windows {
foreign import libc {
"system:libucrt.lib",
@@ -218,3 +220,102 @@ foreign libc {
ferror :: proc(stream: ^FILE) -> int ---
perror :: proc(s: cstring) ---
}
+
+to_stream :: proc(file: ^FILE) -> io.Stream {
+ stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+ unknown_or_eof :: proc(f: ^FILE) -> io.Error {
+ switch {
+ case ferror(f) != 0:
+ return .Unknown
+ case feof(f) != 0:
+ return .EOF
+ case:
+ return nil
+ }
+ }
+
+ file := (^FILE)(stream_data)
+ switch mode {
+ case .Close:
+ if fclose(file) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ case .Flush:
+ if fflush(file) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ case .Read:
+ n = i64(fread(raw_data(p), size_of(byte), len(p), file))
+ if n == 0 { err = unknown_or_eof(file) }
+
+ case .Read_At:
+ curr := ftell(file)
+ if curr == -1 {
+ return 0, unknown_or_eof(file)
+ }
+
+ if fseek(file, long(offset), SEEK_SET) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ defer fseek(file, long(curr), SEEK_SET)
+
+ n = i64(fread(raw_data(p), size_of(byte), len(p), file))
+ if n == 0 { err = unknown_or_eof(file) }
+
+ case .Write:
+ n = i64(fwrite(raw_data(p), size_of(byte), len(p), file))
+ if n == 0 { err = unknown_or_eof(file) }
+
+ case .Write_At:
+ curr := ftell(file)
+ if curr == -1 {
+ return 0, unknown_or_eof(file)
+ }
+
+ if fseek(file, long(offset), SEEK_SET) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ defer fseek(file, long(curr), SEEK_SET)
+
+ n = i64(fwrite(raw_data(p), size_of(byte), len(p), file))
+ if n == 0 { err = unknown_or_eof(file) }
+
+ case .Seek:
+ if fseek(file, long(offset), int(whence)) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ case .Size:
+ curr := ftell(file)
+ if curr == -1 {
+ return 0, unknown_or_eof(file)
+ }
+ defer fseek(file, curr, SEEK_SET)
+
+ if fseek(file, 0, SEEK_END) != 0 {
+ return 0, unknown_or_eof(file)
+ }
+
+ n = i64(ftell(file))
+ if n == -1 {
+ return 0, unknown_or_eof(file)
+ }
+
+ case .Destroy:
+ return 0, .Empty
+
+ case .Query:
+ return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size })
+ }
+ return
+ }
+
+ return {
+ data = file,
+ procedure = stream_proc,
+ }
+}