/**+
 This module provides low level memory management facilities.
+**/

#include <OpenGl_tgl_all.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <OpenGl_cmn_memory.h>

#define CHAP 0x41544154 /* 'TATA' */

typedef struct test
{
   Tint chap;
   Tint size;
} mhdr;

static Tint tot_mem;

Tint
cmn_freemem( void *ptr )
{
    mhdr *p;

    if( ptr == 0 )
        return 0;

    p = ( mhdr * )ptr ;
    p-- ;
    if( p -> chap != CHAP )
    {
        fprintf(stderr, "%%CMN-E-INVALIDPTR,  Invalid pointer value passed in\
 function cmn_freemem\n");
        return ( -1L );
    }
    else
    {
        tot_mem -= p -> size;
    }
    p->chap = 0;
    free( p );

    return 0;
}

/*+

 This routine allocates contiguous memory with or without initialising the
 the space depending on the value of flag 'clear' ( 0 for noclear , 1 for
 for clear ) and returns a pointer to the allocated block . This the lowest
 level alloc routine which calls system  malloc() and calloc() routines and
 is called by all upper level  memory_management modules.

+*/

void *
cmn_getmem( Tint no_of_objects , Tint size_of_object , Tint clear )
{

      register void *ptr;
      register mhdr *p;
      register Tint  size;

      size  =  no_of_objects ,
      size *=  size_of_object,
      size +=  sizeof(mhdr);
      p =  (mhdr *)malloc( size );

      if( p  == 0 )
      {
           fprintf(stderr,
        "%%CMN-F-ALOCERR,  Could not allocate '%d' bytes of memory.\n", size);
           fprintf(stderr,
        "%%CMN-I-TOTALLOC,  Total Memory Used in Bytes : %d\n", tot_mem);
           return 0;
      }

      size    -=  sizeof(mhdr);
      tot_mem += size;

      p -> chap = CHAP;
      p -> size = size;
      p++ ;
      ptr = ( void * )p ;
      if( clear )
           memset( ptr , (int)0 , (int)size );

      return( ptr );
}

/*+

 This routine copies n bytes of the allocated memory from
 'source_va' to 'dest_va'

+*/

void *
cmn_memcpy ( void *dest_va, void *source_va, Tint nbytes )
{
     return ( ( void * )
                memcpy  ( dest_va , source_va , nbytes ) );
}

/*+

 This routine sets the allocated memory specified by 'ptr' to the given
 byte value.

+*/

void *
cmn_memset ( void *ptr , Tint byte , Tint nbytes )
{
     return ( ( void * )memset ( ptr , byte , nbytes ) );
}

/*+

 This routine changes the size of the memory block that 'ptr' points to ,to
 'size' bytes and returns a pointer to the block . This is lowest level
 resizing routine and is called by other memory_management modules .

+*/

void *
cmn_resizemem( void *ptr , Tint size )
{
   register mhdr *p;

   p = ( mhdr * )ptr ;
   p-- ;
   if( p -> chap != CHAP )
   {
        fprintf(stderr, "%%CMN-F-INVALIDPTR,  Invalid pointer value passed in\
 function cmn_resizemem\n");
        return 0;
   }
   else
   {
        tot_mem -= p -> size;
   }

   size +=  sizeof(mhdr);

   p = ( mhdr * )realloc( p , size );

   if( p == 0 )
   {
           fprintf(stderr, "%%CMN-F-REALOCERR,  Could not reallocate '%d'\
 bytes of memory.\n", size);
           fprintf(stderr,"%%CMN-I-TOTALLOC,  Total Memory Used in Bytes:%d\n",
                                                                   tot_mem);
       return 0;
   }

   size    -=  sizeof(mhdr);
   tot_mem += size;

   p -> chap = CHAP;
   p -> size = size;
   p++ ;

   return( ( void * )p );
}

void
cmn_printmem( void )
{
   fprintf(stderr,"%%CMN-I-TOTALLOC,  Total Memory Used in Bytes : %d\n",
                                                                   tot_mem);
}
