diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-30 10:50:37 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-30 11:25:35 -0400 |
commit | c920ea363635ae03e3c3575271d9acbe29d63e6d (patch) | |
tree | 50b8c0ca17f3973713fd0d9acb9d904e9f8fd1bb | |
parent | make malloc work (diff) | |
download | comus-c920ea363635ae03e3c3575271d9acbe29d63e6d.tar.gz comus-c920ea363635ae03e3c3575271d9acbe29d63e6d.tar.bz2 comus-c920ea363635ae03e3c3575271d9acbe29d63e6d.zip |
inflate / deflate
-rw-r--r-- | user/deflate.c | 68 | ||||
-rw-r--r-- | user/include/unistd.h | 26 | ||||
-rw-r--r-- | user/inflate.c | 41 | ||||
-rw-r--r-- | user/lib/fopen.c | 37 |
4 files changed, 171 insertions, 1 deletions
diff --git a/user/deflate.c b/user/deflate.c new file mode 100644 index 0000000..35018d0 --- /dev/null +++ b/user/deflate.c @@ -0,0 +1,68 @@ +#include <stdio.h> +#include <stdbool.h> + +int main(int argc, char **argv) +{ + FILE *in, *out; + int length_bytes = 0, length = 0, tracking = EOF, next; + + if (argc != 3) { + fprintf(stderr, "usage: deflate in out\n"); + return 1; + } + + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "cannot read: %s\n", argv[1]); + return 1; + } + + out = fopen(argv[2], "wb"); + if (out == NULL) { + fprintf(stderr, "cannot write %s\n", argv[2]); + return 1; + } + + while (next = getc(in), next != EOF) { + int diff; + + if (tracking == EOF) { + tracking = next; + length = 1; + length_bytes = 0; + continue; + } + + diff = tracking - next; + diff = diff < 1 ? -diff : diff; + if (diff < 2) + next = tracking; + + if (tracking == next) { + length++; + if (length == 255) { + length_bytes++; + length = 0; + } + continue; + } + + // write output + for (int i = 0; i < length_bytes; i++) + putc(255, out); + putc(length, out); + putc(tracking, out); + tracking = next; + length = 1; + length_bytes = 0; + } + + if (length) { + for (int i = 0; i < length_bytes; i++) + putc(255, out); + putc(length, out); + putc(tracking, out); + } + + return 0; +} diff --git a/user/include/unistd.h b/user/include/unistd.h index f080917..cad3a81 100644 --- a/user/include/unistd.h +++ b/user/include/unistd.h @@ -16,6 +16,20 @@ typedef unsigned short pid_t; +enum { + S_SET = 0, + S_CUR = 1, + S_END = 2, +}; + +enum { + O_CREATE = 0x01, + O_RDONLY = 0x02, + O_WRONLY = 0x04, + O_APPEND = 0x08, + O_RDWR = O_RDONLY | O_WRONLY, +}; + /** * terminates the calling process and does not return. * @@ -65,7 +79,7 @@ extern void exec(const char *filename, char **args); * @param filename - the name of the file to open * @return the file descriptior of the open file or a negative error code. */ -extern int open(const char *filename); +extern int open(const char *filename, int flags); /** * closes a stream with the given file descriptior @@ -95,6 +109,16 @@ extern int read(int fd, void *buffer, size_t nbytes); extern int write(int fd, const void *buffer, size_t nbytes); /** + * seek a file + * + * @param fd - file stream to seek + * @param off - offset to seek + * @param whence - whence to seek + * @return 0 on success, or an error code + */ +extern int seek(int fd, long int off, int whence); + +/** * gets the pid of the calling process * * @return the pid of this process diff --git a/user/inflate.c b/user/inflate.c new file mode 100644 index 0000000..2f7a3d6 --- /dev/null +++ b/user/inflate.c @@ -0,0 +1,41 @@ +#include <stdio.h> +#include <stdbool.h> + +int main(int argc, char **argv) +{ + FILE *in, *out; + int length, value; + + if (argc != 3) { + fprintf(stderr, "usage: inflate in out\n"); + return 1; + } + + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "cannot read: %s\n", argv[1]); + return 1; + } + + out = fopen(argv[2], "wb"); + if (out == NULL) { + fprintf(stderr, "cannot write %s\n", argv[2]); + return 1; + } + + while (1) { + length = getc(in); + value = getc(in); + + if (length == EOF) + break; + + if (value == EOF) + return 1; + + for (int i = 0; i < length; i++) + putc(value, out); + } + + return 0; +} diff --git a/user/lib/fopen.c b/user/lib/fopen.c new file mode 100644 index 0000000..cb2529f --- /dev/null +++ b/user/lib/fopen.c @@ -0,0 +1,37 @@ +#include <stdio.h> +#include <unistd.h> + +FILE *fopen(const char *restrict filename, const char *restrict modes) +{ + int flags = 0; + int fd; + + char c; + while (c = *modes, c) { + switch (c) { + case 'r': + flags |= O_RDONLY; + break; + case 'w': + flags |= O_CREATE | O_WRONLY; + break; + case 'a': + flags |= O_APPEND; + break; + case '+': + flags |= O_RDWR; + break; + default: + return NULL; + } + } + + if (flags == 0) + return NULL; + + fd = open(filename, flags); + if (fd < 0) + return NULL; + + return (FILE *)(uintptr_t)fd; +} |