/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-01-29
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef MEMORYCHECKERPRIVATE_H
#define MEMORYCHECKERPRIVATE_H

#ifdef MEMORY_CHECKER

#include <QtCore>

#include "Mutex.h"

namespace QGpCoreTools {

#ifdef Q_OS_UNIX           // dll mechanism does not allow a secure allocation
                          // unless Qt is linked with this dll (this was the reason for qtbdebugmem.dll)
#define DO_MEMORY_CHECK
#endif
#define ABORT_ON_WARNING

// defines for new,... must be removed because they are defined here as functions
#undef new
#undef checkBlocks
#undef isBlockDamaged
#undef printBlockInfo

#ifdef DO_MEMORY_CHECK

struct BlockInfo
{
  void * blockAddress;
  unsigned int sz;
  bool record; // true if this block must be reported as undeleted if still in memory
  const char * fName;
  int fLine;
  BlockInfo * next;
  BlockInfo * previous;
};

// Data alignment is critical here
// The header cannot break data alignement.
// This is why NOMANSLAND is 24 instead of 16 (+8 for BlockInfo pointer)
#define NOMANSLAND_SIZE 24
#define HEADER_SIZE (sizeof(BlockInfo *)+NOMANSLAND_SIZE)
#define TAIL_SIZE NOMANSLAND_SIZE

class MemoryCheckerPrivate
{
public:
  static inline void* allocateBlock(std::size_t sz, const char* file, int line);
  static inline void freeBlock(void* v);

  static void setEnabled(bool e) {_enabled=e;}
  static bool isEnabled() {return _enabled;}

  static void setRecord(bool r) {_record=r;}
  static void setVerbose(bool v) {_verbose=v;}

  static void checkBlocks(bool showLib, bool showUndeleted, const char* file, int line);
  static bool isBlockDamaged(void* v, const char* file, int line);
  static void printBlockInfo(void * ptr, const char* file, int line);
private:
  static void printHeader(FILE * f, const char * prefix, unsigned char * ptr);
  static inline bool testNoMansLand(unsigned char * ptr);
  static inline BlockInfo * addBlock(void * blockAddress, unsigned int sz, const char * fName, int fLine);
  static inline void delBlock(BlockInfo * b);
  static inline BlockInfo * findBlock(void * blockAddress);
  static inline void srcLocation(const char * fName, int fLine);
  static inline void srcLocation(BlockInfo * b);

  static bool _enabled;
  static bool _record;
  static bool _verbose;
  static BlockInfo * _infos;
  static Mutex _mutex;
};

#endif // DO_MEMORY_CHECK

} // namespace QGpCoreTools

#endif // MEMORY_CHECKER

#endif // MEMORYCHECKERPRIVATE_H
