/**************************************************************************
 *{@C
 *      Copyright:      1988-2024 Paul Obermeier (obermeier@poSoft.de)
 *
 *      Module:         Utilities
 *      Filename:       UT_Memory.h
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    Declaration of the functions and types exported
 *                      by the memory management library.
 *
 *      Additional documentation:
 *                      None.
 *
 **************************************************************************/

#ifndef __UT_MEMORY_H__
#define __UT_MEMORY_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include "UT_Compat.h"

typedef struct UT_MemHdr *UT_MemState;

extern POIMG_IMPORT_EXPORT void *UT_MemAlignPos (const void *);
extern POIMG_IMPORT_EXPORT void *UT_MemAlignNeg (const void *);

extern POIMG_IMPORT_EXPORT void       *UT_MemTempAlloc  (size_t, const char *);
extern POIMG_IMPORT_EXPORT void       *UT_MemPermAlloc  (size_t, const char *);
extern POIMG_IMPORT_EXPORT void        UT_MemFree       (void *);
extern POIMG_IMPORT_EXPORT UT_MemState UT_MemRemember   (void);
extern POIMG_IMPORT_EXPORT void        UT_MemSave       (UT_MemState);
extern POIMG_IMPORT_EXPORT void        UT_MemRestore    (UT_MemState);
extern POIMG_IMPORT_EXPORT void        UT_MemDestroy    (UT_Bool);
extern POIMG_IMPORT_EXPORT UT_Bool     UT_MemCheck      (void);
extern POIMG_IMPORT_EXPORT UT_Bool     UT_MemCheckBlock (void *);

/* A macro that expands into a string identifing the file and line number
   of the place where the macro was invoked, e.g. "UT_MemAlloc.h - 77". */

#define UT_MemId1(str)  #str
#define UT_MemId2       UT_MemId1
#define UT_MemId3(str) UT_MemId2 (str)
#define UT_MemIdString  __FILE__ " - " UT_MemId3 (__LINE__)

/* Macros which provide a more comfortable interface to the UT_MemTempAlloc
   and UT_MemPermAlloc functions; the size of the block to be allocated is
   computed automatically, and a string to identify the block for debugging
   purposes is supplied. */

#if defined (DEBUG_MEM)

    #define UT_MemTemp(mtype)                           \
            (UT_MemTempAlloc (sizeof (mtype),           \
            #mtype ": " UT_MemIdString))

    #define UT_MemPerm(mtype)                           \
            (UT_MemPermAlloc (sizeof (mtype),           \
            #mtype ": " UT_MemIdString))

    #define UT_MemTempArray(n,mtype)                    \
            (UT_MemTempAlloc ((n) * sizeof (mtype),     \
            "array of " #mtype ": " UT_MemIdString))

    #define UT_MemPermArray(n,mtype)                    \
            (UT_MemPermAlloc ((n) * sizeof (mtype),     \
            "array of " #mtype ": " UT_MemIdString))

#else

    #define UT_MemTemp(mtype) (UT_MemTempAlloc (sizeof (mtype), ""))

    #define UT_MemPerm(mtype) (UT_MemPermAlloc (sizeof (mtype), ""))

    #define UT_MemTempArray(n,mtype) (UT_MemTempAlloc ((n) * sizeof (mtype), ""))

    #define UT_MemPermArray(n,mtype) (UT_MemPermAlloc ((n) * sizeof (mtype), ""))

#endif /* DEBUG_MEM */

#ifdef __cplusplus
}
#endif

#endif /* __UT_MEMORY_H__ */
