aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-09 14:48:24 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-09 14:48:24 -0400
commit43c595cafe3a09c52a098774671bb55c7e80f128 (patch)
treee5e8c037ab43b946bfa59d1ec178c61f4ade25ee
parentdad567bfc85c0f8c767e0f1cf818493f8143d871 (diff)
Remove example module for files
-rw-r--r--examples/README.md1
-rw-r--r--examples/file.tm244
2 files changed, 0 insertions, 245 deletions
diff --git a/examples/README.md b/examples/README.md
index 2dbd4806..174546b6 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -2,7 +2,6 @@
- [coroutine.tm](coroutine.tm): A library for coroutines similar to Lua's
(using [libaco](https://libaco.org)).
-- [file.tm](file.tm): A file handling module.
- [game/](game/): An example game using raylib.
- [ini.tm](ini.tm): An INI configuration file reader tool.
- [vectors.tm](vectors.tm): A math vector library.
diff --git a/examples/file.tm b/examples/file.tm
deleted file mode 100644
index 9d4197b7..00000000
--- a/examples/file.tm
+++ /dev/null
@@ -1,244 +0,0 @@
-# A module for interacting with files
-extern builtin_last_err:func()->Text
-
-use <fcntl.h>
-use <stdio.h>
-use <sys/mman.h>
-use <sys/stat.h>
-use <unistd.h>
-use <unistr.h>
-use libunistring.so
-
-enum FileReadResult(Success(text:Text), Failure(reason:Text))
-
-func _wrap_with_finalizer(obj:@Memory, finalizer:func(obj:@Memory))->@Memory:
- return inline C (
- ({
- FILE **wrapper = GC_MALLOC(sizeof(FILE*));
- *wrapper = $obj;
- GC_register_finalizer(wrapper, (void*)$finalizer.fn, wrapper, NULL, NULL);
- wrapper;
- })
- ):@Memory
-
-func _close_file(fp:@Memory):
- inline C {
- if (*(FILE**)$fp)
- fclose(*(FILE**)$fp);
- *(FILE**)$fp = NULL;
- }
-
-func read(path:Text)->FileReadResult:
- inline C {
- int fd = open(Text$as_c_string($path), O_RDONLY);
- if (fd != -1) {
- struct stat sb;
- if (fstat(fd, &sb) == -1) {
- const char *mem = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- char *gc_mem = GC_MALLOC_ATOMIC(sb.st_size+1);
- memcpy(gc_mem, mem, sb.st_size);
- gc_mem[sb.st_size] = '\0';
- close(fd);
- return file$FileReadResult$tagged$Success(Text$from_strn(gc_mem, sb.st_size));
- } else {
- const int chunk_size = 256;
- char *buf = GC_MALLOC_ATOMIC(chunk_size);
- Text_t contents = Text("");
- size_t just_read;
- do {
- just_read = read(fd, buf, chunk_size);
- if (just_read > 0) {
- if (u8_check(buf, just_read) != NULL)
- break;
- contents = Texts(contents, Text$from_strn(buf, just_read));
- buf = GC_MALLOC_ATOMIC(chunk_size);
- }
- } while (just_read > 0);
- close(fd);
- return file$FileReadResult$tagged$Success(contents);
- }
- }
- }
- return Failure(builtin_last_err())
-
-func resolve_path(path:Text, relative_to=".")->Text:
- path_c_str := path:as_c_string()
- relative_to_c_str := relative_to:as_c_string()
- inline C {
- extern char *resolve_path(char*, char*, char*);
- }
- resolved := inline C (
- resolve_path($path_c_str, $relative_to_c_str, $relative_to_c_str)
- ): CString
- return Text.from_c_string(resolved)
-
-func relative_path(path:Text, relative_to=".")->Text:
- path = resolve_path(path, relative_to)
-
- relative_to = resolve_path(relative_to)
- if path:matches($/{start}$relative_to$"/"{..}/):
- return path:slice(relative_to.length + 2, -1)
-
- return path
-
-struct WriteHandle(_file:@Memory):
- func write(h:WriteHandle, text:Text, flush=yes):
- inline C {
- fputs(Text$as_c_string($text), *(FILE**)$h.$_file);
- if ($flush)
- fflush(*(FILE**)$h.$_file);
- }
-
- func close(h:WriteHandle):
- _close_file(h._file)
-
-enum FileWriteResult(Open(h:WriteHandle), Failure(reason:Text))
-func writing(path:Text)->FileWriteResult:
- maybe_f := inline C (
- fopen(Text$as_c_string($path), "w")
- ):@Memory?
- when maybe_f is @f:
- obj := _wrap_with_finalizer(f, _close_file)
- return Open(WriteHandle(obj))
- else:
- return Failure(builtin_last_err())
-
-func appending(path:Text)->FileWriteResult:
- maybe_f := inline C (
- fopen(Text$as_c_string($path), "a")
- ):@Memory?
- when maybe_f is @f:
- return Open(WriteHandle(f))
- else:
- return Failure(builtin_last_err())
-
-struct LineReader(_file:@Memory):
- func stdin()->LineReader:
- f := inline C (
- stdin
- ):@Memory
- return LineReader(_wrap_with_finalizer(f, _close_file))
-
- func is_finished(r:LineReader)->Bool:
- return inline C (
- feof(*(FILE**)$r.$_file) != 0;
- ):Bool
-
- func next_line(r:LineReader)->FileReadResult:
- line := inline C (
- ({
- if (*(FILE**)$r.$_file == NULL) fail("File has already been closed!");
- char *buf = NULL;
- size_t space = 0;
- ssize_t len = getline(&buf, &space, *(FILE**)$r.$_file);
- if (len < 0) {
- file$_close_file($r.$_file);
- return (file$FileReadResult_t){1, .$Failure={Text("End of file")}};
- }
- if (len > 0 && buf[len-1] == '\n') --len;
- char *line = GC_MALLOC_ATOMIC(len + 1);
- memcpy(line, buf, len);
- line[len] = '\0';
- if (buf) free(buf);
- u8_check(line, len) ? Text("") : Text$from_strn(line, len);
- })
- ):Text
- return Success(line)
-
- func from_file(path:Text)->FileLineReaderResult:
- maybe_f := inline C (
- fopen(Text$as_c_string($path), "r")
- ):@Memory?
- when maybe_f is @f:
- obj := _wrap_with_finalizer(f, _close_file)
- return Open(LineReader(obj))
- else:
- return Failure(builtin_last_err())
-
- func from_command(cmd:Text)->FileLineReaderResult:
- maybe_f := inline C (
- popen(Text$as_c_string($cmd), "r")
- ):@Memory?
- when maybe_f is @f:
- obj := _wrap_with_finalizer(f, _close_file)
- return Open(LineReader(obj))
- else:
- return Failure(builtin_last_err())
-
- func close(r:LineReader):
- _close_file(r._file)
-
-enum FileLineReaderResult(Open(reader:LineReader), Failure(reason:Text))
-
-func command(cmd:Text)->FileReadResult:
- maybe_f := inline C (
- popen(Text$as_c_string($cmd), "r")
- ):@Memory?
-
- when maybe_f is @f:
- text := inline C (
- ({
- const int chunk_size = 256;
- char *buf = GC_MALLOC_ATOMIC(chunk_size);
- Text_t contents = Text("");
- size_t just_read;
- do {
- just_read = fread(buf, sizeof(char), chunk_size, $f);
- if (just_read > 0) {
- contents = Texts(contents, Text$from_strn(buf, just_read));
- buf = GC_MALLOC_ATOMIC(chunk_size);
- }
- } while (just_read > 0);
- pclose($f);
- contents;
- })
- ):Text
- text = text:replace($/$(\n){end}/, "")
- return Success(text)
- else:
- return Failure(builtin_last_err())
-
-func main(path:Text, relative_to="."):
- >> resolve_path(path, relative_to)
- >> relative_path(resolve_path(path, relative_to))
- # word := ""
- # when command("shuf -n 1 /usr/share/dict/words") is Success(w):
- # >> word = w
- # is Failure(msg):
- # fail(msg)
-
- # when writing("test.txt") is Open(f):
- # say("Writing {word} to test.txt")
- # f:write("Hello {word}!{\n}")
- # is Failure(msg):
- # fail(msg)
-
- # when read("test.txt") is Success(text):
- # say("Roundtrip: {text}")
- # is Failure(msg):
- # fail(msg)
-
- # say("Reading stdin:")
- # reader := LineReader.stdin()
- # while yes:
- # when reader:next_line() is Success(line):
- # >> line
- # else: stop
-
- # say("Reading cmd:")
- # when LineReader.from_command("ping google.com") is Open(reader):
- # while yes:
- # when reader:next_line() is Success(line):
- # >> line
- # else: stop
- # is Failure(msg):
- # fail("{msg}")
-
- # say("Reading /dev/stdin:")
- # when LineReader.from_file("/dev/stdin") is Open(reader):
- # while yes:
- # when reader:next_line() is Success(line):
- # >> line
- # else: stop
- # is Failure(msg):
- # fail("{msg}")