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
|
import "std/common.cup"
const __FILE_BUFFER_CAP = 1024;
struct File {
fd: int;
name: char*;
// Buffer
buffer: char[__FILE_BUFFER_CAP];
buffer_size: int;
};
fn fopen(name: char*, mode: char): File* {
let open_mode: int;
if (mode == 'w') open_mode = O_WRONLY | O_CREAT | O_TRUNC;
else if (mode == 'r') open_mode = O_RDONLY;
else die("Unknown file open mode");
let f: File* = malloc(sizeof(File));
f.name = name;
f.fd = open(name, open_mode, 438); // 438 = 0o666
if (f.fd < 0)
die("Could not open file");
f.buffer_size = 0;
return f;
}
fn fflush(f: File*) {
if (f.buffer_size > 0) {
let n = write(f.fd, f.buffer, f.buffer_size);
if (n < 0)
die("Could not write to file");
f.buffer_size = 0;
}
}
fn fwrite(f: File*, buf: char*, size: int) {
if (f.buffer_size + size > __FILE_BUFFER_CAP)
fflush(f);
if (size > __FILE_BUFFER_CAP) {
write(f.fd, buf, size);
} else {
memcpy(f.buffer + f.buffer_size, buf, size);
f.buffer_size = f.buffer_size + size;
}
}
fn fread(f: File*, buf: char*, size: int): int {
let n = read(f.fd, buf, size);
if (n < 0)
die("Could not read from file");
return n;
}
fn fclose(f: File*) {
fflush(f);
close(f.fd);
}
fn fputs(f: File*, s: char*) {
fwrite(f, s, strlen(s));
}
fn fputc(f: File*, c: char) {
fwrite(f, &c, 1);
}
fn fputu(f: File*, n: int) {
let buf: char[32];
let len = putu_buffer(n, buf);
fwrite(f, buf, len);
}
// Resets file position to the beginning of the file
fn fsize(f: File*): int {
let pos = lseek(f.fd, 0, SEEK_CUR);
let size = lseek(f.fd, 0, SEEK_END);
lseek(f.fd, pos, SEEK_SET);
return size;
}
// Map file to memory and return pointer
fn fmap(f: File*, sizeptr: int*): char* {
let size = fsize(f);
let ptr = mmap(null, size, PROT_READ, MAP_PRIVATE, f.fd, 0);
if (ptr == MAP_FAILED)
die("Could not map file");
if (sizeptr) *sizeptr = size;
return ptr;
}
fn fread_to_string(f: File*, sizeptr: int*): char* {
let size = fsize(f);
let text: char* = malloc(size + 1);
fread(f, text, size);
text[size] = 0;
if (sizeptr) *sizeptr = size;
return text;
}
|