From d2e274f0fe08b042dfb6751820ac4f01216248b9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 31 Oct 2025 15:51:36 +0000 Subject: [PATCH] Update documentation for `os2` once more! --- core/os/os2/dir.odin | 14 ++++++ core/os/os2/errors.odin | 24 +++++++++ core/os/os2/file.odin | 6 +++ core/os/os2/file_stream.odin | 21 ++++---- core/os/os2/file_util.odin | 96 ++++++++++++++++++++++++++++++++---- 5 files changed, 143 insertions(+), 18 deletions(-) diff --git a/core/os/os2/dir.odin b/core/os/os2/dir.odin index 10b06a8ce..f63754273 100644 --- a/core/os/os2/dir.odin +++ b/core/os/os2/dir.odin @@ -6,6 +6,10 @@ import "core:strings" read_dir :: read_directory +/* + Reads the file `f` (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ @(require_results) read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) { if f == nil { @@ -47,11 +51,18 @@ read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files } +/* + Reads the file `f` (assuming it is a directory) and returns all of the unsorted directory entries. +*/ @(require_results) read_all_directory :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { return read_directory(f, -1, allocator) } +/* + Reads the named directory by path (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ @(require_results) read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { f := open(path) or_return @@ -59,6 +70,9 @@ read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocato return read_directory(f, n, allocator) } +/* + Reads the named directory by path (assuming it is a directory) and returns all of the unsorted directory entries. +*/ @(require_results) read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { return read_directory_by_path(path, -1, allocator) diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin index 1cf7d765c..077697c0d 100644 --- a/core/os/os2/errors.odin +++ b/core/os/os2/errors.odin @@ -3,6 +3,10 @@ package os2 import "core:io" import "base:runtime" +/* + General errors that are common within this package which cannot + be categorized by `io.Error` nor `runtime.Allocator_Error`. +*/ General_Error :: enum u32 { None, @@ -33,8 +37,12 @@ General_Error :: enum u32 { Unsupported, } +// A platform specific error Platform_Error :: _Platform_Error +/* + `Error` is a union of different classes of errors that could be returned from procedures in this package. +*/ Error :: union #shared_nil { General_Error, io.Error, @@ -46,6 +54,7 @@ Error :: union #shared_nil { ERROR_NONE :: Error{} +// Attempts to convert an `Error` into a platform specific error as an integer. `ok` is false if not possible @(require_results) is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) { v := ferr.(Platform_Error) or_else {} @@ -53,6 +62,7 @@ is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) { } +// Attempts to return the error `ferr` as a string without any allocation @(require_results) error_string :: proc(ferr: Error) -> string { if ferr == nil { @@ -112,6 +122,9 @@ error_string :: proc(ferr: Error) -> string { return "unknown error" } +/* + `print_error` is a utility procedure which will print an error `ferr` to a specified file `f`. +*/ print_error :: proc(f: ^File, ferr: Error, msg: string) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) err_str := error_string(ferr) @@ -127,3 +140,14 @@ print_error :: proc(f: ^File, ferr: Error, msg: string) { buf[length - 1] = '\n' write(f, buf) } + + + +// Attempts to convert an `Error` `ferr` into an `io.Error` +@(private) +error_to_io_error :: proc(ferr: Error) -> io.Error { + if ferr == nil { + return .None + } + return ferr.(io.Error) or_else .Unknown +} diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index 1da37dfa4..85ebfcece 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -399,12 +399,18 @@ change_owner :: proc(name: string, uid, gid: int) -> Error { fchdir :: fchange_directory +/* + Changes the current working directory to the file, which must be a directory. +*/ fchange_directory :: proc(f: ^File) -> Error { return _fchdir(f) } fchmod :: fchange_mode +/* + Changes the current `mode` permissions of the file `f`. +*/ fchange_mode :: proc(f: ^File, mode: Permissions) -> Error { return _fchmod(f, mode) } diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index 84176928d..e1c29a792 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -2,6 +2,7 @@ package os2 import "core:io" +// Converts a file `f` into an `io.Stream` to_stream :: proc(f: ^File) -> (s: io.Stream) { if f != nil { assert(f.stream.procedure != nil) @@ -10,14 +11,16 @@ to_stream :: proc(f: ^File) -> (s: io.Stream) { return } +/* + This is an alias of `to_stream` which converts a file `f` to an `io.Stream`. + It can be useful to indicate what the stream is meant to be used for as a writer, + even if it has no logical difference. +*/ to_writer :: to_stream + +/* + This is an alias of `to_stream` which converts a file `f` to an `io.Stream`. + It can be useful to indicate what the stream is meant to be used for as a reader, + even if it has no logical difference. +*/ to_reader :: to_stream - - -@(private) -error_to_io_error :: proc(ferr: Error) -> io.Error { - if ferr == nil { - return .None - } - return ferr.(io.Error) or_else .Unknown -} diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index be2f1f8c7..c2cf7c121 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -4,10 +4,18 @@ import "base:runtime" import "core:strconv" import "core:unicode/utf8" +/* + `write_string` writes a string `s` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) { return write(f, transmute([]byte)s) } +/* + `write_strings` writes a variadic list of strings `strings` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) { for s in strings { m: int @@ -19,11 +27,18 @@ write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) { } return } - +/* + `write_byte` writes a byte `b` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) { return write(f, []byte{b}) } +/* + `write_rune` writes a rune `r` as an UTF-8 encoded string to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { if r < utf8.RUNE_SELF { return write_byte(f, byte(r)) @@ -34,6 +49,10 @@ write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { return write(f, b[:n]) } +/* + `write_encoded_rune` writes a rune `r` as an UTF-8 encoded string which with escaped control codes to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool { n^ += m @@ -73,6 +92,31 @@ write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { return } +/* + `write_ptr` is a utility procedure that writes the bytes points at `data` with length `len`. + + It is equivalent to: `write(f, ([^]byte)(data)[:len])` +*/ +write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { + return write(f, ([^]byte)(data)[:len]) +} + +/* + `read_ptr` is a utility procedure that reads the bytes points at `data` with length `len`. + + It is equivalent to: `read(f, ([^]byte)(data)[:len])` +*/ +read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { + return read(f, ([^]byte)(data)[:len]) +} + + + +/* + `read_at_least` reads from `f` into `buf` until it has read at least `min` bytes. + It returns the number of bytes copied and an error if fewer bytes were read. + The error is only an `io.EOF` if no bytes were read. +*/ read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) { if len(buf) < min { return 0, .Short_Buffer @@ -88,17 +132,17 @@ read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) { return } +/* + `read_full` reads exactly `len(buf)` bytes from `f` into `buf`. + It returns the number of bytes copied and an error if fewer bytes were read. + The error is only an `io.EOF` if no bytes were read. + + It is equivalent to `read_at_least(f, buf, len(buf))`. +*/ read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) { return read_at_least(f, buf, len(buf)) } -write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { - return write(f, ([^]byte)(data)[:len]) -} - -read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { - return read(f, ([^]byte)(data)[:len]) -} read_entire_file :: proc{ @@ -106,6 +150,10 @@ read_entire_file :: proc{ read_entire_file_from_file, } +/* + `read_entire_file_from_path` reads the entire named file `name` into memory allocated with `allocator`. + A slice of bytes and an error is returned, if any error is encountered. +*/ @(require_results) read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) { f := open(name) or_return @@ -113,6 +161,10 @@ read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator, l return read_entire_file_from_file(f, allocator, loc) } +/* + `read_entire_file_from_file` reads the entire file `f` into memory allocated with `allocator`. + A slice of bytes and an error is returned, if any error is encountered. +*/ @(require_results) read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) { size: int @@ -160,8 +212,23 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc : } } +/* + `write_entire_file` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ +write_entire_file :: proc{ + write_entire_file_from_bytes, + write_entire_file_from_string, +} + +/* + `write_entire_file_from_bytes` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ @(require_results) -write_entire_file :: proc(name: string, data: []byte, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error { +write_entire_file_from_bytes :: proc(name: string, data: []byte, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error { flags := O_WRONLY|O_CREATE if truncate { flags |= O_TRUNC @@ -174,3 +241,14 @@ write_entire_file :: proc(name: string, data: []byte, perm := Permissions_Read_A return err } + + +/* + `write_entire_file_from_string` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ +@(require_results) +write_entire_file_from_string :: proc(name: string, data: string, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error { + return write_entire_file(name, transmute([]byte)data, perm, truncate) +}