summaryrefslogtreecommitdiff
path: root/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'decode.c')
-rw-r--r--decode.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/decode.c b/decode.c
new file mode 100644
index 0000000..9a5eea8
--- /dev/null
+++ b/decode.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+typedef struct node {
+ bool is_char;
+ char ch;
+
+ struct node *left;
+ struct node *right;
+} node_t;
+
+node_t *node_char_create(char ch);
+// left right flipped because tree has to be inverted for some reason
+node_t *node_link_create(node_t* right, node_t* left);
+void node_free(node_t *root);
+void node_print(node_t *root, int indent);
+
+size_t read_tree_data(char *buf);
+node_t *read_tree_shape(char *char_buf, size_t bits);
+char read_decoded(node_t *root);
+void decode();
+
+FILE *in;
+FILE *out;
+
+node_t *root;
+
+char read_decoded(node_t *root)
+{
+ static size_t i = 0;
+ static char cur_byte = 0;
+
+ if(root == NULL) {
+ fprintf(stderr, "ERROR: real_decoded: root cannot be NULL");
+ exit(1);
+ }
+
+ if(root->is_char) return root->ch;
+
+ if(i % 8 == 0) {
+ if(fread(&cur_byte, sizeof(char), 1, in) <= 0) {
+ fprintf(stderr, "ERROR: An error has occured while reading the encoded bytes\n");
+ exit(1);
+ }
+ i = 0;
+ }
+
+ char bit = (cur_byte >> i++) & 1;
+ if(bit == 0) {
+ return read_decoded(root->left);
+ }
+
+ return read_decoded(root->right);
+}
+
+void decode()
+{
+ char buf[256] = {0};
+ size_t chars = read_tree_data(buf);
+ root = read_tree_shape(buf, chars*2 - 1);
+
+ size_t text_len;
+ fread(&text_len, sizeof(size_t), 1, in);
+
+ for(int i = 0; i < text_len; i++) {
+ char ch = read_decoded(root);
+ fwrite(&ch, sizeof(char), 1, out);
+ }
+}
+
+int main(void)
+{
+ in = stdin;
+ out = stdout;
+
+ // in = fopen(argv[1], "rb");
+ // if(!in) {
+ // fprintf(stderr, "ERROR: Could not open file %s\n", argv[1]);
+ // exit(1);
+ // }
+
+ // out = fopen(argv[1], "wb");
+ // if(!out) {
+ // fprintf(stderr, "ERROR Could not open file %s\n", argv[1]);
+ // exit(1);
+ // }
+
+ decode();
+
+ node_free(root);
+
+ // fclose(in);
+ // fclose(out);
+ return 0;
+}
+
+size_t read_tree_data(char *buf)
+{
+ unsigned int chars = 0;
+ fread(&chars, sizeof(char), 1, in);
+ fread(buf, sizeof(char), chars, in);
+ return chars;
+}
+
+node_t *read_tree_shape(char *char_buf, size_t bits)
+{
+ static size_t buf_i = 0;
+ static size_t read_bits = 0;
+ static char cur_byte = 0;
+
+ if(read_bits == bits) {
+ fprintf(stderr, "ERROR: An error has occred while reading the tree shape (read_bits == bits)");
+ exit(1);
+ }
+
+ if(read_bits % 8 == 0) {
+ if(fread(&cur_byte, sizeof(char), 1, in) <= 0) {
+ fprintf(stderr, "ERROR: An error has occured while reading the tree shape\n");
+ exit(1);
+ }
+ }
+
+ node_t *root;
+
+ char bit = (cur_byte >> (read_bits++ % 8)) & 1;
+ if(bit == 0) {
+ root = node_link_create(read_tree_shape(char_buf, bits),
+ read_tree_shape(char_buf, bits));
+ } else {
+ root = node_char_create(char_buf[buf_i++]);
+ }
+
+ return root;
+}
+
+node_t *node_char_create(char ch)
+{
+ node_t *node = malloc(sizeof(node_t));
+
+ node->is_char = true;
+ node->ch = ch;
+ node->left = NULL;
+ node->right = NULL;
+
+ return node;
+}
+node_t *node_link_create(node_t* right, node_t* left)
+{
+ node_t *node = malloc(sizeof(node_t));
+
+ node->is_char = false;
+ node->ch = 0;
+ node->left = left;
+ node->right = right;
+
+ return node;
+}
+
+void node_free(node_t *root)
+{
+ if(root == NULL) return;
+
+ node_free(root->left);
+ node_free(root->right);
+
+ free(root);
+}
+
+void node_print(node_t *root, int indent)
+{
+ if(root == NULL) return;
+
+ for(int i = 0; i < indent; i++) fprintf(stderr, " ");
+
+ fprintf(stderr, "%d '%c'\n", root->is_char, (root->ch == 0) ? '-' : root->ch);
+
+ node_print(root->left, indent + 2);
+ node_print(root->right, indent + 2);
+}