shithub: xml-9atom

ref: f1e559d47916b74f473153a0a04df6956ca4052b
dir: /libxml/heap.c/

View raw version
#include <u.h>
#include <libc.h>
#include "xml.h"

#define Roundup(x, g)	(((x) + (unsigned)(g-1)) & ~((unsigned)(g-1)))

struct Xtree {
	Xtree *left;
	Xtree *right;
	char *str;
	int hits;
};

struct Xblock {
	Xblock *next;
	char *free;
	char *end;
};

static int Strdups, Commons, Unique, Memblocks;

static void *
getmem(Xml *xp, int len)
{
	int sz;
	Xblock *b;
	char *ret;

	len = Roundup(len, sizeof(long long));

	sz = xp->alloc.blksiz;		/* shorthand */
	b = xp->alloc.active;

	if(len > sz)
		sysfatal("store: object too big (%d > %d)\n", len, sz);

	if(xp->alloc.active == nil || b->free + len >= b->end){
		Memblocks++;
		b = mallocz(sizeof(Xblock) + sz, 0);
		b->free = (char *)&b[1];
		b->end = (char *)&b->free[sz];

		b->next = xp->alloc.active;
		xp->alloc.active = b;
	}

	ret = b->free;
	b->free += len;
	return ret;
}

static Xtree *
lookadd(Xml *xp, Xtree *t, char *str, Xtree **match)
{
	int n;

	if(t == nil){
		Unique++;
		t = getmem(xp, sizeof(Xtree) + strlen(str)+1);
		t->left = nil;
		t->right = nil;
		t->str = (char *)&t[1];
		strcpy(t->str, str);
		*match = t;
		t->hits = 1;
		return t;
	}

	if((n = strcmp(str, t->str)) == 0){
		*match = t;
		t->hits++;
	}
	if(n < 0)
		t->left = lookadd(xp, t->left, str, match);
	if(n > 0)
		t->right = lookadd(xp, t->right, str, match);
	return t;
}

char *
xmlstrdup(Xml *xp, char *str, int iscommon)
{
	char *s;
	Xtree *t;

	Strdups++;
	if(iscommon){
		Commons++;
		xp->alloc.root = lookadd(xp, xp->alloc.root, str, &t);
		return t->str;
	}

	s = getmem(xp, strlen(str)+1);
	return strcpy(s, str);
}

void *
xmlcalloc(Xml *xp, int n, int m)
{
	void *v;

	v = getmem(xp, n * m);
	memset(v, 0, n * m);
	return v;
}

void *
xmlmalloc(Xml *xp, int n)
{
	return getmem(xp, n);
}


void
_Xheapstats(void)
{
	fprint(2, "total=%d common=%d -> unique=%d rare=%d memblocks=%d\n",
		Strdups, Commons, Unique, Strdups - Commons, Memblocks);
}

void
_Xheapfree(Xml *xp)
{
	Xblock *b, *n;

	for(b = xp->alloc.active; b; b = n){
		n = b->next;
		if(xmldebug)
			memset(b, 0x7e, xp->alloc.blksiz);
		free(b);
	}

}