/*
 * $Id: mem.h 348 2010-08-26 06:26:28Z hyunghwan.chung $
 *
    Copyright 2006-2009 Chung, Hyung-Hwan.
    This file is part of QSE.

    QSE 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 3 of 
    the License, or (at your option) any later version.

    QSE 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 QSE. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _QSE_CMN_MEM_H_
#define _QSE_CMN_MEM_H_

/** @file
 * This file defines functions and macros for memory manipulation.
 */

#include <qse/types.h>
#include <qse/macros.h>

/** 
 * The QSE_MMGR_GETDFL() macro returns the default memory manager.
 */
#define QSE_MMGR_GETDFL()  (qse_mmgr)

/**
 * The QSE_MMGR_SETDFL() macro changes the default memory manager.
 */
#define QSE_MMGR_SETDFL(m) ((qse_mmgr)=(m))

/* allocate a memory block */
#define QSE_MMGR_ALLOC(mmgr,size) \
	((mmgr)->alloc((mmgr)->udd,size))

/* reallocate a memory block */
#define QSE_MMGR_REALLOC(mmgr,ptr,size) \
	((mmgr)->realloc((mmgr)->udd,ptr,size))

/* free a memory block */
#define QSE_MMGR_FREE(mmgr,ptr) \
	((mmgr)->free((mmgr)->udd,ptr))

#ifdef __cplusplus
extern "C" {
#endif

/** 
 * The qse_mmgr global variable holds a pointer to the default memory 
 * manager. Use QSE_MMGR_GETDFL() and QSE_MMGR_SETDFL() to manipulate it.
 */
extern qse_mmgr_t* qse_mmgr;

/**
 * The qse_memcpy() functions copies @a n bytes from the source memory block 
 * @a src to the destinaion memory block @a dst. The memory blocks must not 
 * overlap. Use qse_memmove() if they overlap.
 *
 * @return destination memory block @a dst.
 */
void* qse_memcpy (
	void*       dst, /**< destination memory block */
	const void* src, /**< source memory block */
	qse_size_t  n    /**< number of bytes to copy */
);

/**
 * The qse_memmove() functions copies @a n bytes from the source memory block
 * @a src to the destinaion memory block @a dst without corrupting overlapping
 * zone.
 *
 * @return destination memory block @a dst.
 */
void* qse_memmove (
	void*       dst, /**< destination memory block */
	const void* src, /**< source memory block */
	qse_size_t  n    /**< number of bytes to copy */
);

/*
 * The qse_memset() function fills leading @a n bytes of the destination 
 * memory block @a dst with the byte @a val.
 *
 * @return destination memory block @a dst.
 */
void* qse_memset (
	void*       dst, /**< destination memory block */
	int         val, /**< value fill the memory block with */
	qse_size_t   n   /**< number of bytes to fill */
);

/**
 * The qse_memcmp() function compares leading *a n bytes of two memory blocks 
 * @a s1 and @a s2.
 *
 * @return
 * 0 if two memory ares have the same leadning @a n bytes.
 * positive number if the first different byte of s1 is greater than that of s2.
 * negative number if the first different byte of s1 is less than that of s2.
 */
int qse_memcmp (
	const void* s1, /**< first memory block to compare */
	const void* s2, /**< second memory block to compare */ 
	qse_size_t  n   /**< the number of bytes to compare */
);

/**
 * The qse_membyte() function scans the memory block @a s from the first byte
 * up to the nth byte in search of the byte @a val. If it finds a match,
 * it aborts scanning the memory block and returns the pointer to the matching
 * location.
 *
 * @return
 *  #QSE_NULL if the byte @a val is not found.
 *  pointer to the location in the memory block @a s matching the byte @a val
 *  if a match is found.
 */
void* qse_membyte (
	const void* s,     /**< memory block to scan */
	int         val,   /**< byte to find */
	qse_size_t  n      /**< number of bytes to scan */ 
);

/*
 * The qse_memrbyte() function scans the memory block @a s from the nth byte
 * backward to the first byte in search of the byte @a val. If it finds a match,
 * it aborts scanning the memory block and returns the pointer to the matching 
 * location.
 *
 * @return
 *  #QSE_NULL if the byte val is not found.
 *  pointer to the location in the memory block s matching the byte val
 *  if a match is found.
 */
void* qse_memrbyte (
	const void* s,     /**< memory block to scan */
	int         val,   /**< byte to find */
	qse_size_t  n      /**< number of bytes to scan */ 
);

/**
 * The qse_memmem() functions scans the first @a hl bytes of the memory 
 * block @a hs in search of the byte block @a nd of the length @a nl bytes.
 *
 * @return
 *  #QSE_NULL if no match is found.
 *  pointer to the start of the matching location if a match is found.
 */
void* qse_memmem (
	const void* hs,  /**< memory block to scan */
	qse_size_t  hl,  /**< number of bytes to scan */
	const void* nd,  /**< byte block to find */
	qse_size_t  nl   /**< number of bytes in the block */
);

/*
 * The qse_memrmem() functions scans the first @a hl bytes of the memory
 * block @a hs backward in search of the byte block @a nd of the length 
 * @a nl bytes.
 *
 * @return
 * #QSE_NULL if no match is found.
 * pointer to the start of the matching location if a match is found.
 */
void* qse_memrmem (
	const void* hs,  /**< memory block to scan */
	qse_size_t  hl,  /**< number of bytes to scan */
	const void* nd,  /**< byte block to find */
	qse_size_t  nl   /**< number of bytes in the block */
);

#ifdef __cplusplus
}
#endif

#endif
