#include <pslib.h>
#include "psleak.h"

#define LEAKS "leaks.dat"       // File to which to write leaks data


psMemoryId stacMemPrint(const psMemBlock *ptr)
{
    psLogMsg("stac.memoryPrint", PS_LOG_INFO,
         "Memory block %d:\n"
         "\tFile %s, line %d, size %d\n"
         "\tPosts: %x %x %x\n",
         ptr->id, ptr->file, ptr->lineno, ptr->userMemorySize, ptr->startblock, ptr->endblock,
         *(void**)((int8_t *)(ptr + 1) + ptr->userMemorySize));
    return 0;
}


void stacMemoryProblem(const psMemBlock* ptr, ///< the pointer to the problematic memory block.
               const char *file, ///< the file in which the problem originated
               psS32 lineno ///< the line number in which the problem originated
    )
{
    psLogMsg("stac.checkMemory.corruption", PS_LOG_WARN,
         "Memory corruption detected in memBlock %d\n"
         "\tFile %s, line %d, size %d\n"
         "\tPosts: %x %x %x\n",
         ptr->id, file, lineno, ptr->userMemorySize, ptr->startblock, ptr->endblock,
         (ptr + 1 + ptr->userMemorySize));
}



void stacCheckMemory(void)
{
    psMemBlock **leaks = NULL;      // List of leaks
    FILE *leakFile;         // File to write leaks to

    psTrace("stac.checkMemory", 1, "Checking for memory problems....\n");

    (void)psMemProblemCallbackSet(stacMemoryProblem); // Set callback for corruption

    if ((leakFile = fopen(LEAKS, "w")) == NULL) {
    //psError("stac.checkMemory", "Unable to open leaks file, %s\n",LEAKS);
    return;
    }

    int nLeaks = psMemCheckLeaks(0, &leaks, leakFile, false); // Number of leaks
    psTrace("stac.checkMemory", 1, "%d leaks found.\n", nLeaks);
    for (int i = 0; i < nLeaks; i++) {
    psLogMsg("stac.checkMemory.leaks", PS_LOG_WARN,
         "Memory leak detection: memBlock %d\n"
         "\tFile %s, line %d, size %d\n",
         leaks[i]->id, leaks[i]->file, leaks[i]->lineno, leaks[i]->userMemorySize);
    }

    int nCorrupted = psMemCheckCorruption(false); // Number of corrupted
    psTrace("stac.checkMemory", 1, "%d memory blocks corrupted.\n", nCorrupted);

}

