summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu/file.c
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
committerkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
commit2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch)
treeb0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/file.c
parentb9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff)
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/file.c')
-rw-r--r--src/runtime/c/gu/file.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/runtime/c/gu/file.c b/src/runtime/c/gu/file.c
new file mode 100644
index 000000000..ed1956537
--- /dev/null
+++ b/src/runtime/c/gu/file.c
@@ -0,0 +1,73 @@
+#include <gu/file.h>
+
+typedef struct GuFileOutStream GuFileOutStream;
+
+struct GuFileOutStream {
+ GuOutStream stream;
+ FILE* file;
+};
+
+static size_t
+gu_file_output(GuOutStream* stream, const uint8_t* buf, size_t len, GuExn* err)
+{
+ GuFileOutStream* fos = gu_container(stream, GuFileOutStream, stream);
+ errno = 0;
+ size_t wrote = fwrite(buf, 1, len, fos->file);
+ if (wrote < len) {
+ if (ferror(fos->file)) {
+ gu_raise_errno(err);
+ }
+ }
+ return wrote;
+}
+
+static void
+gu_file_flush(GuOutStream* stream, GuExn* err)
+{
+ GuFileOutStream* fos = gu_container(stream, GuFileOutStream, stream);
+ errno = 0;
+ if (fflush(fos->file) != 0) {
+ gu_raise_errno(err);
+ }
+}
+
+GuOut*
+gu_file_out(FILE* file, GuPool* pool)
+{
+ GuFileOutStream* fos = gu_new_i(pool, GuFileOutStream,
+ .stream.output = gu_file_output,
+ .stream.flush = gu_file_flush,
+ .file = file);
+ return gu_new_out(&fos->stream, pool);
+}
+
+
+typedef struct GuFileInStream GuFileInStream;
+
+struct GuFileInStream {
+ GuInStream stream;
+ FILE* file;
+};
+
+static size_t
+gu_file_input(GuInStream* stream, uint8_t* buf, size_t sz, GuExn* err)
+{
+ GuFileInStream* fis = gu_container(stream, GuFileInStream, stream);
+ errno = 0;
+ size_t got = fread(buf, 1, sz, fis->file);
+ if (got == 0) {
+ if (ferror(fis->file)) {
+ gu_raise_errno(err);
+ }
+ }
+ return got;
+}
+
+GuIn*
+gu_file_in(FILE* file, GuPool* pool)
+{
+ GuFileInStream* fis = gu_new_s(pool, GuFileInStream,
+ .stream.input = gu_file_input,
+ .file = file);
+ return gu_new_in(&fis->stream, pool);
+}