aboutsummaryrefslogtreecommitdiff
path: root/std/file.cup
blob: 91b02e72dae3e003b03597dfb0704744a8015196 (plain) (blame)
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;
}