btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: mux_tree.c,v 1.2 2005/06/23 22:02:14 av1-op Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1996 Markus Stenberg
 *       All rights reserved
 *
 * Created: Mon Nov 25 11:41:43 1996 mstenber
 * Last modified: Mon Jun 22 07:27:06 1998 fingon
 *
 */

#define FATAL(msgs...) \
{ fprintf(stderr, ##msgs); exit(1); }

#define TREAD(to,len,msg) \
if (feof(f)) FATAL("ERROR READING FILE (%s): EOF.\n", msg); \
if (fread(to,1,len,f) != len) \
FATAL("ERROR READING FILE (%s): NOT ENOUGH READ!\n", msg);

#define TSAVE(from,len,msg) \
if (fwrite(from, 1, len, tree_file) != len) \
FATAL("ERROR WRITING FILE (%s): NOT ENOUGH WRITTEN(?!?)\n", msg);

/* Main aim: Attempt to provide 1-1 interface when compared to my
   old rbtc code and the new AVL code */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tree.h"
#include "mux_tree.h"

#define Create(var,typ,count) \
if (!(var = (typ *) calloc(sizeof (typ), count))) \
{ fprintf(stderr, "Error mallocating!\n"); exit(1); }

static int NodeCompare(Node * a, Node * b)
{
    if (a->key < b->key)
	return -1;
    return (a->key > b->key);
}

static void NodeDelete(Node * a)
{
    if (a->data)
	free((void *) a->data);
    free((void *) a);
}

void AddEntry(Tree * tree, muxkey_t key, dtype_t type, dsize_t size,
    void *data)
{
    Node *foo;

    if (!tree)
	return;
    Create(foo, Node, 1);
    foo->key = key;
    foo->data = data;
    foo->type = type;
    foo->size = size;
    tree_add(tree, NodeCompare, foo, NodeDelete);
}

Node *FindNode(Tree tree, muxkey_t key)
{
    Node foo;

    foo.key = key;
    return tree_srch(&tree, NodeCompare, &foo);
}

void DeleteEntry(Tree * tree, muxkey_t key)
{
    Node foo;

    if (FindNode(*tree, key)) {
	foo.key = key;
	tree_delete(tree, NodeCompare, &foo, NodeDelete);
    }
}

static FILE *tree_file;

static int nodesave_count;

static int NodeSave(Node * n)
{
    TSAVE(&n->key, sizeof(n->key), "key");
    TSAVE(&n->type, sizeof(n->type), "type");
    TSAVE(&n->size, sizeof(n->size), "size");
    if (n->size > 0)
	TSAVE(n->data, n->size, "data");
    nodesave_count++;
    return 1;
}

int SaveTree(FILE * f, Tree tree)
{
    muxkey_t key;

    nodesave_count = 0;
    tree_file = f;
    tree_trav(&tree, NodeSave);
    key = -1;
    fwrite(&key, sizeof(key), 1, tree_file);
    return nodesave_count;
}

static void MyLoadTree(FILE * f, Tree * tree, int (*sizefunc)(int))
{
    muxkey_t key;
    dtype_t type;
    dsize_t osize;
    int nsize, rsize;
    void *data;

    TREAD(&key, sizeof(key), "first key");
    while (key >= 0 && !feof(f)) {
	TREAD(&type, sizeof(type), "type");
	TREAD(&osize, sizeof(osize), "size");
	if (sizefunc && (rsize = sizefunc(type)) >= 0) {
	    nsize = osize > rsize ? osize : rsize;
	} else
	    nsize = rsize = osize;
	if (nsize) {
	    if (!(data = malloc(nsize))) {
		printf("Error malloccing!\n");
		exit(1);
	    }
	    if (osize)
	    	TREAD(data, osize, "data");

	    if (nsize > osize)
	    	memset(data + osize, 0, nsize - osize);
	} else
	    data = NULL;

	/* Set node size to the real type size, rather than the read size,
	 * so that the object will get 'truncated' to the right size on the
	 * next dump.
	 */
	AddEntry(tree, key, type, rsize, data);
	TREAD(&key, sizeof(key), "new key");
    }
}


/* This is a _MONSTER_ :P */
void ClearTree(Tree * tree)
{
    tree_mung(tree, NodeDelete);
}

void LoadTree(FILE * f, Tree * tree, int (*sizefunc)(int))
{
    ClearTree(tree);
    MyLoadTree(f, tree, sizefunc);
}

void UpdateTree(FILE * f, Tree * tree, int(*sizefunc)(int))
{
    MyLoadTree(f, tree, sizefunc);
}

void GoThruTree(Tree tree, int (*func) (Node *))
{
    tree_trav(&tree, func);
}