Files
Odin/core/os.odin
T
Ginger Bill 24ca106521 v0.0.3 Build
2016-11-17 22:58:00 +00:00

173 lines
3.8 KiB
Odin

#import "win32.odin"
#import "fmt.odin"
File_Time :: type u64
File :: struct {
Handle :: type win32.HANDLE
handle: Handle
last_write_time: File_Time
}
open :: proc(name: string) -> (File, bool) {
using win32
buf: [300]byte
copy(buf[:], name as []byte)
f := File{
handle = CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, nil),
}
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
f.last_write_time = last_write_time(^f)
return f, success
}
create :: proc(name: string) -> (File, bool) {
using win32
buf: [300]byte
copy(buf[:], name as []byte)
f := File{
handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, 0, nil),
}
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
f.last_write_time = last_write_time(^f)
return f, success
}
close :: proc(using f: ^File) {
win32.CloseHandle(handle)
}
write :: proc(using f: ^File, buf: []byte) -> bool {
bytes_written: i32
return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, nil) != 0
}
file_has_changed :: proc(f: ^File) -> bool {
last_write_time := last_write_time(f)
if f.last_write_time != last_write_time {
f.last_write_time = last_write_time
return true
}
return false
}
last_write_time :: proc(f: ^File) -> File_Time {
file_info: win32.BY_HANDLE_FILE_INFORMATION
win32.GetFileInformationByHandle(f.handle, ^file_info)
l := file_info.last_write_time.low_date_time as File_Time
h := file_info.last_write_time.high_date_time as File_Time
return l | h << 32
}
last_write_time_by_name :: proc(name: string) -> File_Time {
last_write_time: win32.FILETIME
data: win32.WIN32_FILE_ATTRIBUTE_DATA
buf: [1024]byte
path := buf[:0]
fmt.bprint(^path, name, "\x00")
if win32.GetFileAttributesExA(path.data, win32.GetFileExInfoStandard, ^data) != 0 {
last_write_time = data.last_write_time
}
l := last_write_time.low_date_time as File_Time
h := last_write_time.high_date_time as File_Time
return l | h << 32
}
File_Standard :: type enum {
INPUT,
OUTPUT,
ERROR,
}
// NOTE(bill): Uses startup to initialize it
__std_files := [File_Standard.count]File{
{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)},
{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)},
{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)},
}
stdin := ^__std_files[File_Standard.INPUT]
stdout := ^__std_files[File_Standard.OUTPUT]
stderr := ^__std_files[File_Standard.ERROR]
read_entire_file :: proc(name: string) -> ([]byte, bool) {
buf: [300]byte
copy(buf[:], name as []byte)
f, file_ok := open(name)
if !file_ok {
return nil, false
}
defer close(^f)
length: i64
file_size_ok := win32.GetFileSizeEx(f.handle as win32.HANDLE, ^length) != 0
if !file_size_ok {
return nil, false
}
data := new_slice(u8, length)
if data.data == nil {
return nil, false
}
single_read_length: i32
total_read: i64
for total_read < length {
remaining := length - total_read
to_read: u32
MAX :: 1<<32-1
if remaining <= MAX {
to_read = remaining as u32
} else {
to_read = MAX
}
win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, nil)
if single_read_length <= 0 {
free(data.data)
return nil, false
}
total_read += single_read_length as i64
}
return data, true
}
heap_alloc :: proc(size: int) -> rawptr {
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size)
}
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size)
}
heap_free :: proc(ptr: rawptr) {
win32.HeapFree(win32.GetProcessHeap(), 0, ptr)
}
exit :: proc(code: int) {
win32.ExitProcess(code as u32)
}
current_thread_id :: proc() -> int {
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
return GetCurrentThreadId() as int
}