aboutsummaryrefslogtreecommitdiff
path: root/std/file.cup
diff options
context:
space:
mode:
Diffstat (limited to 'std/file.cup')
-rw-r--r--std/file.cup99
1 files changed, 99 insertions, 0 deletions
diff --git a/std/file.cup b/std/file.cup
new file mode 100644
index 0000000..91b02e7
--- /dev/null
+++ b/std/file.cup
@@ -0,0 +1,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;
+} \ No newline at end of file