blob: ba74cafa8cdbcbd2c30771c13b40c3598bb85411 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * memory.c: libxml memory allocator wrapper.
3 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00004 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +00005 */
6
Bjorn Reese70a9da52001-04-21 16:57:29 +00007#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +00008
Owen Taylor3473f882001-02-23 17:55:21 +00009#include <string.h>
10
11#ifdef HAVE_SYS_TYPES_H
12#include <sys/types.h>
13#endif
14#ifdef HAVE_TIME_H
15#include <time.h>
16#endif
17#ifdef HAVE_MALLOC_H
18#include <malloc.h>
19#endif
20#ifdef HAVE_STDLIB_H
21#include <stdlib.h>
22#endif
23#ifdef HAVE_CTYPE_H
24#include <ctype.h>
25#endif
26
27
28#include <libxml/xmlmemory.h>
29#include <libxml/xmlerror.h>
30
Daniel Veillard56a4cb82001-03-24 17:00:36 +000031void xmlMallocBreakpoint(void);
Daniel Veillard8599e702001-07-17 21:38:51 +000032void * xmlMemMalloc(size_t size);
33void * xmlMallocLoc(size_t size, const char * file, int line);
34void * xmlMemRealloc(void *ptr,size_t size);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000035void xmlMemFree(void *ptr);
36char * xmlMemoryStrdup(const char *str);
37
38/************************************************************************
39 * *
40 * Macros, variables and associated types *
41 * *
42 ************************************************************************/
43
44
Owen Taylor3473f882001-02-23 17:55:21 +000045#ifdef xmlMalloc
46#undef xmlMalloc
47#endif
48#ifdef xmlRealloc
49#undef xmlRealloc
50#endif
51#ifdef xmlMemStrdup
52#undef xmlMemStrdup
53#endif
54
55
56/*
57 * Each of the blocks allocated begin with a header containing informations
58 */
59
60#define MEMTAG 0x5aa5
61
62#define MALLOC_TYPE 1
63#define REALLOC_TYPE 2
64#define STRDUP_TYPE 3
65
66typedef struct memnod {
67 unsigned int mh_tag;
68 unsigned int mh_type;
69 unsigned long mh_number;
70 size_t mh_size;
71#ifdef MEM_LIST
72 struct memnod *mh_next;
73 struct memnod *mh_prev;
74#endif
75 const char *mh_file;
76 unsigned int mh_line;
77} MEMHDR;
78
79
80#ifdef SUN4
81#define ALIGN_SIZE 16
82#else
83#define ALIGN_SIZE sizeof(double)
84#endif
85#define HDR_SIZE sizeof(MEMHDR)
86#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
87 / ALIGN_SIZE ) * ALIGN_SIZE)
88
89
90#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
91#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
92
93
94static unsigned long debugMemSize = 0;
95static unsigned long debugMaxMemSize = 0;
96static int block=0;
97int xmlMemStopAtBlock = 0;
Daniel Veillard7d7e3792001-07-30 13:42:13 +000098void *xmlMemTraceBlockAt = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +000099int xmlMemInitialized = 0;
100#ifdef MEM_LIST
101static MEMHDR *memlist = NULL;
102#endif
103
104void debugmem_tag_error(void *addr);
105#ifdef MEM_LIST
106void debugmem_list_add(MEMHDR *);
107void debugmem_list_delete(MEMHDR *);
108#endif
109#define Mem_Tag_Err(a) debugmem_tag_error(a);
110
111#ifndef TEST_POINT
112#define TEST_POINT
113#endif
114
115/**
116 * xmlMallocBreakpoint:
117 *
118 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
119 * number reaches the specified value this function is called. One need to add a breakpoint
120 * to it to get the context in which the given block is allocated.
121 */
122
123void
124xmlMallocBreakpoint(void) {
125 xmlGenericError(xmlGenericErrorContext,
126 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
127}
128
129/**
130 * xmlMallocLoc:
131 * @size: an int specifying the size in byte to allocate.
132 * @file: the file name or NULL
133 * @line: the line number
134 *
135 * a malloc() equivalent, with logging of the allocation info.
136 *
137 * Returns a pointer to the allocated area or NULL in case of lack of memory.
138 */
139
140void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000141xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000142{
143 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000144 void *ret;
Owen Taylor3473f882001-02-23 17:55:21 +0000145
146 if (!xmlMemInitialized) xmlInitMemory();
147#ifdef DEBUG_MEMORY
148 xmlGenericError(xmlGenericErrorContext,
149 "Malloc(%d)\n",size);
150#endif
151
152 TEST_POINT
153
154 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
155
156 if (!p) {
157 xmlGenericError(xmlGenericErrorContext,
158 "xmlMalloc : Out of free space\n");
159 xmlMemoryDump();
160 return(NULL);
161 }
162 p->mh_tag = MEMTAG;
163 p->mh_number = ++block;
164 p->mh_size = size;
165 p->mh_type = MALLOC_TYPE;
166 p->mh_file = file;
167 p->mh_line = line;
168 debugMemSize += size;
169 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
170#ifdef MEM_LIST
171 debugmem_list_add(p);
172#endif
173
174#ifdef DEBUG_MEMORY
175 xmlGenericError(xmlGenericErrorContext,
176 "Malloc(%d) Ok\n",size);
177#endif
178
179 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
180
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000181 ret = HDR_2_CLIENT(p);
182
183 if (xmlMemTraceBlockAt == ret) {
184 xmlGenericError(xmlGenericErrorContext,
185 "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
186 xmlMallocBreakpoint();
187 }
188
Owen Taylor3473f882001-02-23 17:55:21 +0000189 TEST_POINT
190
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000191 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000192}
193
194/**
195 * xmlMemMalloc:
196 * @size: an int specifying the size in byte to allocate.
197 *
198 * a malloc() equivalent, with logging of the allocation info.
199 *
200 * Returns a pointer to the allocated area or NULL in case of lack of memory.
201 */
202
203void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000204xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000205{
206 return(xmlMallocLoc(size, "none", 0));
207}
208
209/**
210 * xmlReallocLoc:
211 * @ptr: the initial memory block pointer
212 * @size: an int specifying the size in byte to allocate.
213 * @file: the file name or NULL
214 * @line: the line number
215 *
216 * a realloc() equivalent, with logging of the allocation info.
217 *
218 * Returns a pointer to the allocated area or NULL in case of lack of memory.
219 */
220
221void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000222xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000223{
224 MEMHDR *p;
225 unsigned long number;
226
227 if (!xmlMemInitialized) xmlInitMemory();
228 TEST_POINT
229
230 p = CLIENT_2_HDR(ptr);
231 number = p->mh_number;
232 if (p->mh_tag != MEMTAG) {
233 Mem_Tag_Err(p);
234 goto error;
235 }
236 p->mh_tag = ~MEMTAG;
237 debugMemSize -= p->mh_size;
238#ifdef MEM_LIST
239 debugmem_list_delete(p);
240#endif
241
242 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
243 if (!p) {
244 goto error;
245 }
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000246 if (xmlMemTraceBlockAt == ptr) {
247 xmlGenericError(xmlGenericErrorContext,
248 "%p : Realloced(%d -> %d) Ok\n",
249 xmlMemTraceBlockAt, p->mh_size, size);
250 xmlMallocBreakpoint();
251 }
Owen Taylor3473f882001-02-23 17:55:21 +0000252 p->mh_tag = MEMTAG;
253 p->mh_number = number;
254 p->mh_type = REALLOC_TYPE;
255 p->mh_size = size;
256 p->mh_file = file;
257 p->mh_line = line;
258 debugMemSize += size;
259 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
260#ifdef MEM_LIST
261 debugmem_list_add(p);
262#endif
263
264 TEST_POINT
265
266 return(HDR_2_CLIENT(p));
267
268error:
269 return(NULL);
270}
271
272/**
273 * xmlMemRealloc:
274 * @ptr: the initial memory block pointer
275 * @size: an int specifying the size in byte to allocate.
276 *
277 * a realloc() equivalent, with logging of the allocation info.
278 *
279 * Returns a pointer to the allocated area or NULL in case of lack of memory.
280 */
281
282void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000283xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000284 return(xmlReallocLoc(ptr, size, "none", 0));
285}
286
287/**
288 * xmlMemFree:
289 * @ptr: the memory block pointer
290 *
291 * a free() equivalent, with error checking.
292 */
293void
294xmlMemFree(void *ptr)
295{
296 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000297 char *target;
Owen Taylor3473f882001-02-23 17:55:21 +0000298
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000299 if (ptr == (void *) -1) {
300 xmlGenericError(xmlGenericErrorContext,
301 "trying to free pointer from freed area\n");
302 goto error;
303 }
304
305 if (xmlMemTraceBlockAt == ptr) {
306 xmlGenericError(xmlGenericErrorContext,
307 "%p : Freed()\n", xmlMemTraceBlockAt);
308 xmlMallocBreakpoint();
309 }
310
Owen Taylor3473f882001-02-23 17:55:21 +0000311 TEST_POINT
312
Daniel Veillard92ad2102001-03-27 12:47:33 +0000313 target = (char *) ptr;
314
Owen Taylor3473f882001-02-23 17:55:21 +0000315 p = CLIENT_2_HDR(ptr);
316 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000317 Mem_Tag_Err(p);
318 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000319 }
320 p->mh_tag = ~MEMTAG;
321 debugMemSize -= p->mh_size;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000322 memset(target, -1, p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000323
324#ifdef MEM_LIST
325 debugmem_list_delete(p);
326#endif
327 free(p);
328
329 TEST_POINT
330
331 return;
332
333error:
334 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard8599e702001-07-17 21:38:51 +0000335 "xmlFree(%lX) error\n", (unsigned long) ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000336 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000337 return;
338}
339
340/**
341 * xmlMemStrdupLoc:
342 * @ptr: the initial string pointer
343 * @file: the file name or NULL
344 * @line: the line number
345 *
346 * a strdup() equivalent, with logging of the allocation info.
347 *
348 * Returns a pointer to the new string or NULL if allocation error occured.
349 */
350
351char *
352xmlMemStrdupLoc(const char *str, const char *file, int line)
353{
354 char *s;
355 size_t size = strlen(str) + 1;
356 MEMHDR *p;
357
358 if (!xmlMemInitialized) xmlInitMemory();
359 TEST_POINT
360
361 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
362 if (!p) {
363 goto error;
364 }
365 p->mh_tag = MEMTAG;
366 p->mh_number = ++block;
367 p->mh_size = size;
368 p->mh_type = STRDUP_TYPE;
369 p->mh_file = file;
370 p->mh_line = line;
371 debugMemSize += size;
372 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
373#ifdef MEM_LIST
374 debugmem_list_add(p);
375#endif
376 s = (char *) HDR_2_CLIENT(p);
377
378 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
379
380 if (s != NULL)
381 strcpy(s,str);
382 else
383 goto error;
384
385 TEST_POINT
386
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000387 if (xmlMemTraceBlockAt == s) {
388 xmlGenericError(xmlGenericErrorContext,
389 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
390 xmlMallocBreakpoint();
391 }
392
Owen Taylor3473f882001-02-23 17:55:21 +0000393 return(s);
394
395error:
396 return(NULL);
397}
398
399/**
400 * xmlMemoryStrdup:
401 * @ptr: the initial string pointer
402 *
403 * a strdup() equivalent, with logging of the allocation info.
404 *
405 * Returns a pointer to the new string or NULL if allocation error occured.
406 */
407
408char *
409xmlMemoryStrdup(const char *str) {
410 return(xmlMemStrdupLoc(str, "none", 0));
411}
412
413/**
414 * xmlMemUsed:
415 *
416 * returns the amount of memory currenly allocated
417 *
418 * Returns an int representing the amount of memory allocated.
419 */
420
421int
422xmlMemUsed(void) {
423 return(debugMemSize);
424}
425
426#ifdef MEM_LIST
427/**
428 * xmlMemContentShow:
429 * @fp: a FILE descriptor used as the output file
430 * @p: a memory block header
431 *
432 * tries to show some content from the memory block
433 */
434
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000435static void
Owen Taylor3473f882001-02-23 17:55:21 +0000436xmlMemContentShow(FILE *fp, MEMHDR *p)
437{
438 int i,j,len = p->mh_size;
439 const char *buf = (const char *) HDR_2_CLIENT(p);
440
441 if (p == NULL) {
442 fprintf(fp, " NULL");
443 return;
444 }
445
446 for (i = 0;i < len;i++) {
447 if (buf[i] == 0) break;
448 if (!isprint(buf[i])) break;
449 }
450 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
451 if (len >= 4) {
452 MEMHDR *q;
453 void *cur;
454
455 for (j = 0;j < len -3;j += 4) {
456 cur = *((void **) &buf[j]);
457 q = CLIENT_2_HDR(cur);
458 p = memlist;
459 while (p != NULL) {
460 if (p == q) break;
461 p = p->mh_next;
462 }
463 if ((p != NULL) && (p == q)) {
464 fprintf(fp, " pointer to #%lu at index %d",
465 p->mh_number, j);
466 return;
467 }
468 }
469 }
470 } else if ((i == 0) && (buf[i] == 0)) {
471 fprintf(fp," null");
472 } else {
473 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
474 else {
475 fprintf(fp," [");
476 for (j = 0;j < i;j++)
477 fprintf(fp,"%c", buf[j]);
478 fprintf(fp,"]");
479 }
480 }
481}
482#endif
483
484/**
485 * xmlMemShow:
486 * @fp: a FILE descriptor used as the output file
487 * @nr: number of entries to dump
488 *
489 * show a show display of the memory allocated, and dump
490 * the @nr last allocated areas which were not freed
491 */
492
493void
494xmlMemShow(FILE *fp, int nr)
495{
496#ifdef MEM_LIST
497 MEMHDR *p;
498#endif
499
500 if (fp != NULL)
501 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
502 debugMemSize, debugMaxMemSize);
503#ifdef MEM_LIST
504 if (nr > 0) {
505 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
506 p = memlist;
507 while ((p) && nr > 0) {
508 fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
509 switch (p->mh_type) {
510 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
511 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
512 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
513 default:fprintf(fp," ??? in ");break;
514 }
515 if (p->mh_file != NULL)
516 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
517 if (p->mh_tag != MEMTAG)
518 fprintf(fp," INVALID");
519 xmlMemContentShow(fp, p);
520 fprintf(fp,"\n");
521 nr--;
522 p = p->mh_next;
523 }
524 }
525#endif /* MEM_LIST */
526}
527
528/**
529 * xmlMemDisplay:
530 * @fp: a FILE descriptor used as the output file, if NULL, the result is
531 * written to the file .memorylist
532 *
533 * show in-extenso the memory blocks allocated
534 */
535
536void
537xmlMemDisplay(FILE *fp)
538{
539#ifdef MEM_LIST
540 MEMHDR *p;
541 int idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000542 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000543#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
544 time_t currentTime;
545 char buf[500];
546 struct tm * tstruct;
547
548 currentTime = time(NULL);
549 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000550 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000551 fprintf(fp," %s\n\n", buf);
552#endif
553
554
555 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
556 debugMemSize, debugMaxMemSize);
557 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
558 idx = 0;
559 p = memlist;
560 while (p) {
561 fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
562 switch (p->mh_type) {
563 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
564 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
565 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
566 default:fprintf(fp," ??? in ");break;
567 }
568 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
569 if (p->mh_tag != MEMTAG)
570 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000571 nb++;
572 if (nb < 100)
573 xmlMemContentShow(fp, p);
574 else
575 fprintf(fp," skip");
576
Owen Taylor3473f882001-02-23 17:55:21 +0000577 fprintf(fp,"\n");
578 p = p->mh_next;
579 }
580#else
581 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
582#endif
583}
584
585#ifdef MEM_LIST
586
587void debugmem_list_add(MEMHDR *p)
588{
589 p->mh_next = memlist;
590 p->mh_prev = NULL;
591 if (memlist) memlist->mh_prev = p;
592 memlist = p;
593#ifdef MEM_LIST_DEBUG
594 if (stderr)
595 Mem_Display(stderr);
596#endif
597}
598
599void debugmem_list_delete(MEMHDR *p)
600{
601 if (p->mh_next)
602 p->mh_next->mh_prev = p->mh_prev;
603 if (p->mh_prev)
604 p->mh_prev->mh_next = p->mh_next;
605 else memlist = p->mh_next;
606#ifdef MEM_LIST_DEBUG
607 if (stderr)
608 Mem_Display(stderr);
609#endif
610}
611
612#endif
613
614/*
615 * debugmem_tag_error : internal error function.
616 */
617
618void debugmem_tag_error(void *p)
619{
620 xmlGenericError(xmlGenericErrorContext,
621 "Memory tag error occurs :%p \n\t bye\n", p);
622#ifdef MEM_LIST
623 if (stderr)
624 xmlMemDisplay(stderr);
625#endif
626}
627
628FILE *xmlMemoryDumpFile = NULL;
629
630
631/**
632 * xmlMemoryDump:
633 *
634 * Dump in-extenso the memory blocks allocated to the file .memorylist
635 */
636
637void
638xmlMemoryDump(void)
639{
640#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
641 FILE *dump;
642
643 dump = fopen(".memdump", "w");
644 if (dump == NULL) xmlMemoryDumpFile = stdout;
645 else xmlMemoryDumpFile = dump;
646
647 xmlMemDisplay(xmlMemoryDumpFile);
648
649 if (dump != NULL) fclose(dump);
650#endif
651}
652
653
654/****************************************************************
655 * *
656 * Initialization Routines *
657 * *
658 ****************************************************************/
659
660#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
661xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
662xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
663xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
664xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
665#else
666xmlFreeFunc xmlFree = (xmlFreeFunc) free;
667xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
668xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
669xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) strdup;
670#endif
671
672/**
673 * xmlInitMemory:
674 *
675 * Initialize the memory layer.
676 *
677 * Returns 0 on success
678 */
679
680static int xmlInitMemoryDone = 0;
681
682int
683xmlInitMemory(void)
684{
685 int ret;
686
687#ifdef HAVE_STDLIB_H
688 char *breakpoint;
689#endif
690
691 if (xmlInitMemoryDone) return(-1);
692
693#ifdef HAVE_STDLIB_H
694 breakpoint = getenv("XML_MEM_BREAKPOINT");
695 if (breakpoint != NULL) {
696 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
697 }
698#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000699#ifdef HAVE_STDLIB_H
700 breakpoint = getenv("XML_MEM_TRACE");
701 if (breakpoint != NULL) {
702 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
703 }
704#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000705
706#ifdef DEBUG_MEMORY
707 xmlGenericError(xmlGenericErrorContext,
708 "xmlInitMemory() Ok\n");
709#endif
710 ret = 0;
711 return(ret);
712}
713
714/**
715 * xmlMemSetup:
716 * @freeFunc: the free() function to use
717 * @mallocFunc: the malloc() function to use
718 * @reallocFunc: the realloc() function to use
719 * @strdupFunc: the strdup() function to use
720 *
721 * Override the default memory access functions with a new set
722 * This has to be called before any other libxml routines !
723 *
724 * Should this be blocked if there was already some allocations
725 * done ?
726 *
727 * Returns 0 on success
728 */
729int
730xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
731 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
732 if (freeFunc == NULL)
733 return(-1);
734 if (mallocFunc == NULL)
735 return(-1);
736 if (reallocFunc == NULL)
737 return(-1);
738 if (strdupFunc == NULL)
739 return(-1);
740 xmlFree = freeFunc;
741 xmlMalloc = mallocFunc;
742 xmlRealloc = reallocFunc;
743 xmlMemStrdup = strdupFunc;
744 return(0);
745}
746
747/**
748 * xmlMemGet:
749 * @freeFunc: the free() function in use
750 * @mallocFunc: the malloc() function in use
751 * @reallocFunc: the realloc() function in use
752 * @strdupFunc: the strdup() function in use
753 *
754 * Return the memory access functions set currently in use
755 *
756 * Returns 0 on success
757 */
758int
759xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
760 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
761 if (freeFunc != NULL) *freeFunc = xmlFree;
762 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
763 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
764 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
765 return(0);
766}
767