/* huff.c */
#include <huff.h>

void zero(int8 *dst, int16 size) {
    int16 n;
    int8 *p;

    for (p=dst, n=size; n; p++, n--)
        *p = 0;
    
    return;
}

leaf *mkleaf(int8 c) {
    leaf *p;
    int16 size;

    size = sizeof(struct s_leaf);
    p = $l alloc(size);
    assert(p);
    zero($1 p, size);

    p->c = c;
    p->freq = 1;
    p->up = $t 0;
    p->kind = Leaf;

    return p;
}

node *mknode(tree *left, tree *right) {
    node *p;
    int16 size;

    size = sizeof(struct s_node);
    p = $n alloc(size);
    assert(p);
    zero($1 p, size);

    conn($t p, true, left);
    conn($t p, false, right);

    p->freq = left->n.freq;
    p->freq += right->n.freq;
    p->up = $t 0;
    p->kind = Node;

    return p;
}

void conn(tree *parent, bool isleft, tree *child) {
    tree **connector;

    assert(parent && child);
    if (isleft)
        connector = (tree **)&parent->n.left;
    else
        connector = (tree **)&parent->n.right;

    *connector = child;
    child->n.up = parent;

    return;
}

void show_(tree *t, int8 *ident) {
    if (!t)
        return;
    
    switch (t->n.kind) {
        case Leaf:
            printf("(leaf *)%s = {\n", $c ident);
            printf("  char: %c\n", (char)t->l.c);
            printf("  freq: %lld\n", (unsigned long long int)t->l.freq);
            if (t->l.up)
                printf("    up: [%lld]\n", (unsigned long long int)
                    t->l.up->n.freq);
            else
                printf("    up: <disconnected>\n");
            printf("}\n");

            break;
        
        case Node:
            printf("(node *)%s = {\n", $c ident);
            printf("  freq: %lld\n", (unsigned long long int)t->n.freq);
            if (t->n.up)
                printf("    up: [%lld]\n", (unsigned long long int)
                    t->n.up->n.freq);
            else
                printf("    up: <disconnected>\n");

             if (t->n.left)
                printf("  left: [%lld]\n", (unsigned long long int)
                    t->n.left->n.freq);
            else
                printf("  left: <disconnected>\n");
            if (t->n.right)
                printf(" right: [%lld]\n", (unsigned long long int)
                    t->n.right->n.freq);
            else
                printf(" right: <disconnected>\n");
            printf("}\n");

            break;
        
        default:
            return;
    }

}




int main() {
    node *n;
    leaf *l1, *l2;

    l1 = mkleaf((int8)'a');

    l1->freq = 4;
    l2 = mkleaf((int8)'b');

    n = mknode($t l1, $t l2);

    show(n); printf("\n");
    show(l1); printf("\n");
    show(l2); printf("\n");

    free(n);
    free(l2);
    free(l1);

    return 0;
}
