/**************************************************************************
 *{@C
 *      Copyright:      1988-2024 Paul Obermeier (obermeier@poSoft.de)
 *
 *      Module:         Utilities
 *      Filename:       UT_MemPrivate.h
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    Declarations for internal use in the
 *                      memory management library.
 *
 *      Additional documentation:
 *                      None.
 *
 **************************************************************************/

#ifndef __UT_MEMPRIVATE_H__
#define __UT_MEMPRIVATE_H__

#include "UT_Compat.h"

#define str_try_alloc   "tried to allocate %u bytes"
#define str_get_mem     "tried to retrieve memory usage"

/* Header for the entries in the memory block lists */

typedef struct UT_MemHdr {
    struct UT_MemHdr *next,     /* Next UT_MemHdr in memory list */
                     *previous; /* Previous UT_MemHdr in list */
    size_t size;                /* Size of the memory block */
    #if defined (DEBUG_MEM)
        const char *name;       /* Name of the memory block */
    #endif
} UT_MemHdr;

/* Given a number, "s", the following macro returns the the smallest number
   which is greater than or equal to "s" and evenly divisible by MEM_ALIGN. */

#if MEM_ALIGN == 1
    #define MEM_ALIGN_POS(s) (s)
#elif (MEM_ALIGN == 2) || (MEM_ALIGN == 4) || (MEM_ALIGN == 8) || (MEM_ALIGN == 16)
    #define MEM_ALIGN_POS(s) (((s) + (MEM_ALIGN - 1)) & ~(MEM_ALIGN - 1))
#else
    #define MEM_ALIGN_POS(s) ((s) % MEM_ALIGN? (s) + MEM_ALIGN - (s) % MEM_ALIGN: (s))
#endif

/* Given a number "s", the following macro returns the the highest number
   which is less than or equal to "s" and evenly divisible by MEM_ALIGN. */

#if MEM_ALIGN == 1
    #define MEM_ALIGN_NEG(s) (s)
#elif (MEM_ALIGN == 2) || (MEM_ALIGN == 4) || (MEM_ALIGN == 8) || (MEM_ALIGN == 16)
    #define MEM_ALIGN_NEG(s) ((s) & ~(MEM_ALIGN - 1))
#else
    #define MEM_ALIGN_NEG(s) ((s) % MEM_ALIGN? (s) - (s) % MEM_ALIGN: (s))
#endif

/* Size of a memory block header plus eventual alignment bytes */

#define memheadersize MEM_ALIGN_POS (sizeof (UT_MemHdr))

/* Size of checkbytes plus eventual alignment bytes */

#define checkbytesize MEM_ALIGN_POS (sizeof (Int32))


/* Two parameters that can be changed in order to tune the performance of
   level one of the memory management library:
   "Maxsmall" is a threshold to distinguish between small and large memory blocks.
   "Small_allocsize" is the number of bytes to be allocated when the size of the
   data segment must be increased because of a request for a small memory block
   (should be some multiple of "maxsmall"). */

#define maxsmall        1000
#define small_allocsize (50 * maxsmall)

#endif /* __UT_MEMPRIVATE_H__ */
