/************************************************************************
 * AUTHOR: NiuJiuRu
 * FILENAME: swmem.h
 * DESCRIPTION: 可分块/可跟踪内存泄漏位置的内存管理
 * NOTE:
 * HISTORY:
 * 1, [2010-09-06] created by NiuJiuRu
 * 2, [2013-05-30] modified by NiuJiuRu, 优化"sw_mem_alloc()"函数, 提高
                   内存分配的速度
 ***********************************************************************/
#ifndef __SWMEM_H__
#define __SWMEM_H__

#ifdef __cplusplus
extern "C"
{
#endif
////////////////////////////////////////////////////////////////
// 基本内存函数

/* 内存使用情况检查回调函数 */
typedef void (*PMemCheckCallback)(const char *filename, int line, const char *ptr, int size, void *lpParameter);

/* 创建内存管理模块, align = 1, 2, 4, 8, 16, ... */
void *sw_mem_create(char *buf, int size, int align);

/* 销毁内存管理模块 */
void sw_mem_destroy(void *hMem);

/* 复位内存管理模块 */
void sw_mem_reset(void *hMem);

/* 检查内存节点, 并返回历史上最大消耗过的内存数 */
int sw_mem_check(const void *hMem, PMemCheckCallback proc, void *lpParameter);

/* 获得总的内存大小 */
int sw_mem_getTotalSize(const void *hMem);

/* 分配内存 */
void *sw_mem_alloc(void *hMem, int size, const char *filename, int line);

/* 分配内存并初始化为"0x00" */
void *sw_mem_calloc(void *hMem, int size, const char *filename, int line);

/* 复制字符串 */
char *sw_mem_strdup(void *hMem, const char *str, const char *filename, int line);

/* 重新申请内存 */
void *sw_mem_realloc(void *hMem, void *ptr, int size, const char *filename, int line);

/* 释放内存 */
void sw_mem_free(void *hMem, void *ptr, const char *filename, int line);

////////////////////////////////////////////////////////////////
// 扩展内存函数-全局堆

/* 内存管理模块的全局堆 */
extern void *g_hSwHeap;

/* 初试化内存管理模块的全局堆, align = 1, 2, 4, 8, 16, ... */
bool sw_heap_init(char *buf, int size, int align);

/* 释放内存管理模块的全局堆 */
void sw_heap_exit();

/* 检查全局堆的内存使用情况, 并返回历史上最大消耗过的内存数 */
int sw_heap_check(PMemCheckCallback proc, void *lpParameter);

/* 获得全局堆总的内存大小 */
int sw_heap_getTotalSize();

// 申请内存, 如果初试化了内存管理模块的全局堆, 则使用堆内空间和自定义的分配操作, 否则等同于系统的"malloc()"函数
#define sw_heap_malloc(size) (g_hSwHeap ? sw_mem_alloc(g_hSwHeap, (size), __FILE__, __LINE__) : malloc((size)))

// 申请内存并全部初始化为"0x00", 如果初试化了内存管理模块的全局堆, 则使用堆内空间和自定义的分配操作, 否则等同于系统的"calloc()"函数
#define sw_heap_calloc(size) (g_hSwHeap ? sw_mem_calloc(g_hSwHeap, (size), __FILE__, __LINE__) : calloc((size), 1))

// 复制字符串, 如果初试化了内存管理模块的全局堆, 则使用堆内空间和自定义的复制操作, 否则等同于系统的"strdup()"函数
#define sw_heap_strdup(str)  (g_hSwHeap ? sw_mem_strdup(g_hSwHeap, (str), __FILE__, __LINE__) : strdup((str)))

// 重新分配内存, 如果初试化了内存管理模块的全局堆, 则使用堆内空间和自定义的重新分配操作, 否则等同于系统的"realloc()"函数
#define sw_heap_realloc(ptr, size) (g_hSwHeap ? sw_mem_realloc(g_hSwHeap, (ptr), (size), __FILE__, __LINE__) : realloc((ptr), (size)))

// 释放内存, 如果初试化了内存管理模块的全局堆, 则使用堆内空间和自定义的释放操作, 否则等同于系统的"free()"函数
#define sw_heap_free(ptr)  (g_hSwHeap ? sw_mem_free(g_hSwHeap, (ptr), __FILE__, __LINE__) : free((ptr)))

////////////////////////////////////////////////////////////////
// 扩展内存函数-栈(先进后出)

// 定义栈数据结构
typedef void (*PStackDataFreeCallback)(void *addr, int size); // 栈数据内存释放回调函数
struct stk_data
{
    long addr;
    int size;
    PStackDataFreeCallback freeFun;
    unsigned long wParam; // 附加参数1(可选)
    unsigned long lParam; // 附加参数2(可选)
};

// 创建一个栈, "hMem"为空时在系统内存中创建, "hMem"不为空时在给定的内存中创建
void *sw_stack_create(void *hMem);

// 数据压栈
bool sw_stack_push(void *hStack, struct stk_data data);

// 数据弹出栈
// 注意: 如果只弹出数据而不接收结果("result"为空时), 弹出过程中将会自动调用数据压栈时设定的内存释放回调函数
void sw_stack_pop(void *hStack, struct stk_data *result);

// 得到一个栈内当前的数据元个数
int sw_stack_getDataElementsCnt(const void *hStack);

// 销毁一个栈, 并在销毁过程中自动调用数据压栈时设定的内存释放回调函数
void sw_stack_destroy(void *hStack);

#ifdef __cplusplus
}
#endif

#endif /*__SWMEM_H__*/
