mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-25 23:14:59 -07:00
147 lines
3.7 KiB
Odin
147 lines
3.7 KiB
Odin
package os2
|
|
|
|
import "core:mem"
|
|
import "core:strconv"
|
|
import "core:unicode/utf8"
|
|
|
|
write_string :: proc(fd: Handle, s: string) -> (n: int, err: Error) {
|
|
return write(fd, transmute([]byte)s)
|
|
}
|
|
|
|
write_byte :: proc(fd: Handle, b: byte) -> (n: int, err: Error) {
|
|
return write(fd, []byte{b})
|
|
}
|
|
|
|
write_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
|
|
if r < utf8.RUNE_SELF {
|
|
return write_byte(fd, byte(r))
|
|
}
|
|
|
|
b: [4]byte
|
|
b, n = utf8.encode_rune(r)
|
|
return write(fd, b[:n])
|
|
}
|
|
|
|
write_encoded_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
|
|
wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool {
|
|
n^ += m
|
|
if merr != nil {
|
|
err^ = merr
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
if wrap(write_byte(fd, '\''), &n, &err) { return }
|
|
|
|
switch r {
|
|
case '\a': if wrap(write_string(fd, "\\a"), &n, &err) { return }
|
|
case '\b': if wrap(write_string(fd, "\\b"), &n, &err) { return }
|
|
case '\e': if wrap(write_string(fd, "\\e"), &n, &err) { return }
|
|
case '\f': if wrap(write_string(fd, "\\f"), &n, &err) { return }
|
|
case '\n': if wrap(write_string(fd, "\\n"), &n, &err) { return }
|
|
case '\r': if wrap(write_string(fd, "\\r"), &n, &err) { return }
|
|
case '\t': if wrap(write_string(fd, "\\t"), &n, &err) { return }
|
|
case '\v': if wrap(write_string(fd, "\\v"), &n, &err) { return }
|
|
case:
|
|
if r < 32 {
|
|
if wrap(write_string(fd, "\\x"), &n, &err) { return }
|
|
b: [2]byte
|
|
s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil)
|
|
switch len(s) {
|
|
case 0: if wrap(write_string(fd, "00"), &n, &err) { return }
|
|
case 1: if wrap(write_rune(fd, '0'), &n, &err) { return }
|
|
case 2: if wrap(write_string(fd, s), &n, &err) { return }
|
|
}
|
|
} else {
|
|
if wrap(write_rune(fd, r), &n, &err) { return }
|
|
}
|
|
}
|
|
_ = wrap(write_byte(fd, '\''), &n, &err)
|
|
return
|
|
}
|
|
|
|
write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
|
|
s := transmute([]byte)mem.Raw_Slice{data, len}
|
|
return write(fd, s)
|
|
}
|
|
|
|
read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
|
|
s := transmute([]byte)mem.Raw_Slice{data, len}
|
|
return read(fd, s)
|
|
}
|
|
|
|
|
|
read_at_least :: proc(fd: Handle, buf: []byte, min: int) -> (n: int, err: Error) {
|
|
if len(buf) < min {
|
|
return 0, .Short_Buffer
|
|
}
|
|
for n < min && err == nil {
|
|
nn: int
|
|
nn, err = read(fd, buf[n:])
|
|
n += nn
|
|
}
|
|
if n >= min {
|
|
err = nil
|
|
}
|
|
return
|
|
}
|
|
|
|
read_full :: proc(fd: Handle, buf: []byte) -> (n: int, err: Error) {
|
|
return read_at_least(fd, buf, len(buf))
|
|
}
|
|
|
|
file_size_from_path :: proc(path: string) -> (length: i64, err: Error) {
|
|
fd := open(path, O_RDONLY, 0) or_return
|
|
defer close(fd)
|
|
return file_size(fd)
|
|
}
|
|
|
|
read_entire_file :: proc{
|
|
read_entire_file_from_path,
|
|
read_entire_file_from_handle,
|
|
}
|
|
|
|
read_entire_file_from_path :: proc(name: string, allocator := context.allocator) -> (data: []byte, err: Error) {
|
|
fd := open(name, {.Read}) or_return
|
|
defer close(fd)
|
|
return read_entire_file_from_handle(fd, allocator)
|
|
}
|
|
|
|
read_entire_file_from_handle :: proc(fd: Handle, allocator := context.allocator) -> (data: []byte, err: Error) {
|
|
length := file_size(fd) or_return
|
|
if length <= 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
if i64(int(length)) != length {
|
|
return nil, .Short_Buffer
|
|
}
|
|
|
|
data = make([]byte, int(length), allocator)
|
|
if data == nil {
|
|
return nil, .Short_Buffer
|
|
}
|
|
defer if err != nil {
|
|
delete(data, allocator)
|
|
}
|
|
|
|
bytes_read := read_full(fd, data) or_return
|
|
return data[:bytes_read], nil
|
|
}
|
|
|
|
write_entire_file :: proc(name: string, data: []byte, perm: File_Mode, truncate := true) -> Error {
|
|
flags := O_WRONLY|O_CREATE
|
|
if truncate {
|
|
flags |= O_TRUNC
|
|
}
|
|
f := open(name, flags, perm) or_return
|
|
|
|
_, err := write(f, data)
|
|
if cerr := close(f); cerr != nil && err == nil {
|
|
err = cerr
|
|
}
|
|
return err
|
|
}
|
|
|