Files
Odin/core/os/os2/file_util.odin
T

124 lines
3.0 KiB
Odin

package os2
import "core:mem"
import "core:io"
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_entire_file :: proc(name: string, allocator := context.allocator) -> ([]byte, Error) {
f, ferr := open(name);
if ferr != nil {
return nil, ferr;
}
defer close(f);
size: int;
if size64, err := file_size(f); err == nil {
if i64(int(size64)) != size64 {
size = int(size64);
}
}
size += 1; // for EOF
// TODO(bill): Is this correct logic?
total: int;
data := make([]byte, size, allocator);
for {
n, err := read(f, data[total:]);
total += n;
if err != nil {
if err == .EOF {
err = nil;
}
return data[:total], err;
}
}
}
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, err := open_file(name, flags, perm);
if err != nil {
return err;
}
_, err = write(f, data);
if cerr := close(f); cerr != nil && err == nil {
err = cerr;
}
return err;
}