aboutsummaryrefslogtreecommitdiff
path: root/vendor/libc/stdio_os.odin
blob: db40fb2508fbefe4c762e0ee3e4e905c5eac9c0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#+build !freestanding
#+build !js
package odin_libc

import    "core:io"
import    "core:c"
import os "core:os/os2"

_fopen :: proc(path, _mode: cstring) -> FILE {
	flags: os.File_Flags

	mode := string(_mode)
	if len(mode) > 1 {
		switch mode[0] {
		case 'r':
			flags += {.Read}
		case 'w':
			flags += {.Write, .Create, .Trunc}
		case 'a':
			flags += {.Write, .Create, .Append}
		case:
			return nil
		}

		if len(mode) > 1 && mode[1] == '+' {
			flags += {.Write, .Read}
		} else if len(mode) > 2 && mode[1] == 'b' && mode[2] == '+' {
			flags += {.Write, .Read}
		}
	}

	file, err := os.open(string(path), flags, os.Permissions_Read_Write_All)
	if err != nil {
		return nil
	}

	return FILE(file)
}

_fseek :: proc(_file: FILE, offset: c.long, whence: i32) -> i32 {
	file := __file(_file) 
	if _, err := os.seek(file, i64(offset), io.Seek_From(whence)); err != nil {
		return -1
	}

	return 0
}

_ftell :: proc(_file: FILE) -> c.long {
	file := __file(_file) 
	pos, err := os.seek(file, 0, .Current)
	if err != nil {
		return -1
	}

	return c.long(pos)
}

_fclose :: proc(_file: FILE) -> i32 {
	file := __file(_file) 
	if err := os.close(file); err != nil {
		return EOF
	}

	return 0
}

_fread :: proc(buffer: [^]byte, size: uint, count: uint, _file: FILE) -> uint {
	file := __file(_file) 
	n, _ := os.read(file, buffer[:size*count])
	return uint(max(0, n)) / size
}

_fwrite :: proc(buffer: [^]byte, size: uint, count: uint, _file: FILE) -> uint {
	file := __file(_file) 
	n, _ := os.write(file, buffer[:size*count])
	return uint(max(0, n)) / size
}

_putchar :: proc(char: c.int) -> c.int {
	n, err := os.write_byte(os.stdout, byte(char))	
	if n == 0 || err != nil {
		return EOF
	}
	return char
}

_getchar :: proc() -> c.int {
	ret: [1]byte
	n, err := os.read(os.stdin, ret[:])
	if n == 0 || err != nil {
		return EOF
	}
	return c.int(ret[0])
}

@(private="file")
__file :: proc(file: FILE) -> ^os.File {
	switch (uint(uintptr(file))) {
	case 2: return os.stdout
	case 3: return os.stderr
	case:   return (^os.File)(file)
	}
}