[Expat-discuss] User memory pool management -- patch and description.

Corey Brenner coreybrenner at yahoo.com
Sun Sep 5 21:36:25 CEST 2004


Hi,

In the course of writing some software for myself, I
have stumbled on the need to have expat allocate and
use memory from a specified pool, using specialized
routines of my own device.  I could have used the
XML_Memory_Handling_Suite setup as is, but for the
fact that, on different occasions, the pools (and,
indeed, the allocators) could be different, and I
wanted them to be able to be swapped out at runtime.

For instance, I have a couple of heap managers:

typedef int (*memf) (int, void*, size_t, void*);

int mem1 (int, void*, size_t, void* pool);
int mem2 (int, void*, size_t, void* pool);

and a couple of different pools:

void* pool1;
void* pool2;

I have a wrapper API atop expat which takes the
heap manager function and a pool pointer to perform
its magic:

int xml_explode (memf, void* pool, doc*, char*, int);

If I set up a structure, then, which contains all
the relevant information within this wrapper, I can
use the function and pool I pass:

struct poolwrap {
	memf     func;
	void*    pool;
	int      err;
};

Additionally, I write a few simple wrappers which
dispatch calls through to the heap managers given:

void*
my_malloc (size_t size, void* pd) {
	struct poolwrap* w = (struct poolwrap*) pd;
	void*            p = NULL;

	w->err = w->func(BUFFER, size, &p, w->pool);

	return p;
}

void*
my_realloc (void* p, size_t size, void* pd) {
	struct poolwrap* w = (struct poolwrap*) pd;

	w->err = w->func(RESIZE, size, &p, w->pool);

	return p;
}

void
my_free (void* p, void* pd) {
	struct poolwrap* w = (struct poolwrap*) pd;

	w->err = w->func(RETURN, 0, &p, w->pool);
}

Now, though, I need support in expat for using these
functions and pools:

int xml_explode (memf f, void* p, ...)
{
	struct poolwrap w;

	/* expanded expat memsuite structure */
	XML_Memory_Handling_Suite ms = {
		/* malloc_fcn */	NULL,
		/* realloc_fcn */	NULL,
		/* free_fcn */		NULL,
		/* pool_malloc_fcn */	my_malloc,
		/* pool_realloc_fcn */	my_realloc,
		/* pool_free_fcn */	my_free,
		/* pool */		&w
	};

	XML_Parser p;

	/* set up allocators at runtime */
	w.func = f;
	w.pool = p;
	w.err  = 0;

	/* go! */
	p = XML_ParserCreate_MM(NULL, &ms, NULL);
	if (!p) {
		die();
	}

	...
}

The attached patch (against current CVS) implements
the expanded XML_Memory_Handling_Suite structure, and
its use in lib/xmlparse.c.  Additionally,
doc/reference.html is updated to show the addition
and describe its use.

The expanded structure, due to the way expat's data
structures are laid out, should not affect older
programs as they link against the new library.  This
/should/ be a drop-in replacement not even requiring
a re-link for programs which don't use this function-
ality.

Please direct comments to my email address.

Thanks!

--Corey


		
__________________________________
Do you Yahoo!?
Yahoo! Mail - 50x more storage than other providers!
http://promotions.yahoo.com/new_mail
-------------- next part --------------
Index: doc/reference.html
===================================================================
RCS file: /cvsroot/expat/expat/doc/reference.html,v
retrieving revision 1.61
diff -r1.61 reference.html
923a924,927
>   void *(XMLCALL *pool_malloc_fcn)(size_t size, void *pool);
>   void *(XMLCALL *pool_realloc_fcn)(void *ptr, size_t size, void *pool);
>   void (XMLCALL *pool_free_fcn)(void *ptr, void *pool);
>   void *pool;
932a937,943
> <p>Note that the pool allocation routines will not be called if the
> non-pool routines are provided.  In order to use the pool management
> routines, set the first three fields to NULL.  Use one set of routines,
> or the other, but not both.  Do not mix them, either, or bad tidings
> will likely befall you.  The pool routines accept the user pool pointer
> set into the structure as their last argument, so user pool management
> may be performed on a per-parser basis.</p>
Index: lib/expat.h
===================================================================
RCS file: /cvsroot/expat/expat/lib/expat.h,v
retrieving revision 1.71
diff -r1.71 expat.h
195a196,199
>   void *(*pool_malloc_fcn)(size_t size, void *pool);
>   void *(*pool_realloc_fcn)(void *ptr, size_t size, void *pool);
>   void (*pool_free_fcn)(void *ptr, void *pool);
>   void *pool;
Index: lib/xmlparse.c
===================================================================
RCS file: /cvsroot/expat/expat/lib/xmlparse.c,v
retrieving revision 1.137
diff -r1.137 xmlparse.c
545,547c545,556
< #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
< #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
< #define FREE(p) (parser->m_mem.free_fcn((p)))
---
> #define MALLOC(s) \
>         ((parser->m_mem.malloc_fcn) \
>          ? parser->m_mem.malloc_fcn((s)) \
>          : parser->m_mem.pool_malloc_fcn((s), parser->m_mem.pool))
> #define REALLOC(p,s) \
>         ((parser->m_mem.realloc_fcn) \
>          ? parser->m_mem.realloc_fcn((p),(s)) \
>          : parser->m_mem.pool_realloc_fcn((p),(s),parser->m_mem.pool))
> #define FREE(p) \
>         ((parser->m_mem.free_fcn) \
>          ? parser->m_mem.free_fcn((p)) \
>          : parser->m_mem.pool_free_fcn((p), parser->m_mem.pool))
701c710,713
<       memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
---
>       ((memsuite->malloc_fcn)
>        ? memsuite->malloc_fcn(sizeof(struct XML_ParserStruct))
>        : memsuite->pool_malloc_fcn(sizeof(struct XML_ParserStruct),
>                                    memsuite->pool));
706a719,722
>       mtemp->pool_malloc_fcn = memsuite->pool_malloc_fcn;
>       mtemp->pool_realloc_fcn = memsuite->pool_realloc_fcn;
>       mtemp->pool_free_fcn = memsuite->pool_free_fcn;
>       mtemp->pool = memsuite->pool;
716a733,736
>       mtemp->pool_malloc_fcn = NULL;
>       mtemp->pool_realloc_fcn = NULL;
>       mtemp->pool_free_fcn = NULL;
>       mtemp->pool = NULL;
5431c5451,5453
<   DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
---
>   DTD *p = (DTD *) ((ms->malloc_fcn)
>                     ? ms->malloc_fcn(sizeof(DTD))
>                     : ms->pool_malloc_fcn(sizeof(DTD), ms->pool));
5470,5471c5492,5498
<     if (e->allocDefaultAtts != 0)
<       ms->free_fcn(e->defaultAtts);
---
> 
>     if (e->allocDefaultAtts != 0) {
>       if (ms->free_fcn)
>         ms->free_fcn(e->defaultAtts);
>       else
>         ms->pool_free_fcn(e->defaultAtts, ms->pool);
>     }
5488c5515,5522
<   ms->free_fcn(p->scaffIndex);
---
>   if (ms->free_fcn) {
>     ms->free_fcn(p->scaffIndex);
>     ms->free_fcn(p->scaffold);
>   }
>   else {
>     ms->pool_free_fcn(p->scaffIndex, ms->pool);
>     ms->pool_free_fcn(p->scaffold, ms->pool);
>   }
5490d5523
<   ms->free_fcn(p->scaffold);
5512,5513c5545,5550
<     if (e->allocDefaultAtts != 0)
<       ms->free_fcn(e->defaultAtts);
---
>     if (e->allocDefaultAtts != 0) {
>       if (ms->free_fcn)
>         ms->free_fcn(e->defaultAtts);
>       else
>         ms->pool_free_fcn(e->defaultAtts, ms->pool);
>     }
5525,5526c5562,5569
<     ms->free_fcn(p->scaffIndex);
<     ms->free_fcn(p->scaffold);
---
>     if (ms->free_fcn) {
>       ms->free_fcn(p->scaffIndex);
>       ms->free_fcn(p->scaffold);
>     }
>     else {
>       ms->pool_free_fcn(p->scaffIndex, ms->pool);
>       ms->pool_free_fcn(p->scaffold, ms->pool);
>     }
5528c5571,5574
<   ms->free_fcn(p);
---
>   if (ms->free_fcn)
>     ms->free_fcn(p);
>   else
>     ms->pool_free_fcn(p, ms->pool);
5607c5653,5656
<           ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
---
>           ((ms->malloc_fcn)
>            ? ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE))
>            : ms->pool_malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE),
>                                  ms->pool));
5609c5658,5661
<         ms->free_fcn(newE);
---
>         if (ms->free_fcn)
>           ms->free_fcn(newE);
>         else
>           ms->pool_free_fcn(newE, ms->pool);
5762c5814,5817
<     table->v = (NAMED **)table->mem->malloc_fcn(tsize);
---
>     table->v = (NAMED **)
>       ((table->mem->malloc_fcn)
>         ? table->mem->malloc_fcn(tsize)
>         : table->mem->pool_malloc_fcn(tsize, table->mem->pool));
5791c5846,5849
<       NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
---
>       NAMED **newV = (NAMED **)
>         ((table->mem->malloc_fcn)
>          ? table->mem->malloc_fcn(tsize)
>          : table->mem->pool_malloc_fcn(tsize, table->mem->pool));
5807c5865,5868
<       table->mem->free_fcn(table->v);
---
>       if (table->mem->free_fcn)
>         table->mem->free_fcn(table->v);
>       else
>         table->mem->pool_free_fcn(table->v, table->mem->pool);
5820c5881,5884
<   table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
---
>   table->v[i] = (NAMED *)
>     ((table->mem->malloc_fcn)
>      ? table->mem->malloc_fcn(createSize)
>      : table->mem->pool_malloc_fcn(createSize, table->mem->pool));
5834c5898,5901
<     table->mem->free_fcn(table->v[i]);
---
>     if (table->mem->free_fcn)
>       table->mem->free_fcn(table->v[i]);
>     else
>       table->mem->pool_free_fcn(table->v[i], table->mem->pool);
5845,5846c5912,5920
<     table->mem->free_fcn(table->v[i]);
<   table->mem->free_fcn(table->v);
---
>     if (table->mem->free_fcn)
>       table->mem->free_fcn(table->v[i]);
>     else
>       table->mem->pool_free_fcn(table->v[i], table->mem->pool);
> 
>   if (table->mem->free_fcn)
>     table->mem->free_fcn(table->v);
>   else
>     table->mem->pool_free_fcn(table->v, table->mem->pool);
5914c5988,5991
<     pool->mem->free_fcn(p);
---
>     if (pool->mem->free_fcn)
>       pool->mem->free_fcn(p);
>     else
>       pool->mem->pool_free_fcn(p, pool->mem->pool);
5920c5997,6000
<     pool->mem->free_fcn(p);
---
>     if (pool->mem->free_fcn)
>       pool->mem->free_fcn(p);
>     else
>       pool->mem->pool_free_fcn(p, pool->mem->pool);
6019,6021c6099,6106
<       pool->mem->realloc_fcn(pool->blocks,
<                              (offsetof(BLOCK, s)
<                               + blockSize * sizeof(XML_Char)));
---
>       ((pool->mem->realloc_fcn)
>        ? pool->mem->realloc_fcn(pool->blocks,
>                                 (offsetof(BLOCK, s)
>                                  + blockSize * sizeof(XML_Char)))
>        : pool->mem->pool_realloc_fcn(pool->blocks,
>                                      (offsetof(BLOCK, s)
>                                       + blockSize * sizeof(XML_Char)),
>                                      pool->mem->pool));
6036,6037c6121,6127
<     tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
<                                         + blockSize * sizeof(XML_Char));
---
>     tem = (BLOCK *)
>       ((pool->mem->malloc_fcn)
>        ? pool->mem->malloc_fcn(offsetof(BLOCK, s)
>                                + blockSize * sizeof(XML_Char))
>        : pool->mem->pool_malloc_fcn(offsetof(BLOCK, s)
>                                     + blockSize + sizeof(XML_Char),
>                                     pool->mem->pool));


More information about the Expat-discuss mailing list