/*
* $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);
}