#include "ixxl.h"

void *
xxl_malloc(size_t nbytes, xxl_assettype_t asset_type)
{
    void *ptr;

    if ((ptr = malloc(nbytes)) != NULL)
        XXL_ASSET_SAVE(ptr, xxl_cleanup_ptr, NULL, asset_type);
    return ptr;
}

void *
xxl_realloc(void *old_ptr, size_t nbytes)
{
    void *new_ptr;

    if ((new_ptr = realloc(old_ptr, nbytes)) != NULL && old_ptr != new_ptr)
        XXL_ASSET_UPDATE(old_ptr, new_ptr);
    return new_ptr;
}

void
xxl_free(void *ptr)
{
    free(ptr);
    XXL_ASSET_RELEASE(ptr, XXL_ASSET_ALL);
}

void
xxl_cleanup_ptr(void *ptr, void *arg)
{
    free(ptr);
}

FILE *
xxl_fopen(const char *filename, const char *mode, xxl_assettype_t asset_type)
{
    FILE *f;

    if ((f = fopen(filename, mode)) != NULL)
        XXL_ASSET_SAVE(f, xxl_cleanup_FILE, NULL, asset_type);
    return f;
}

int
xxl_fclose(FILE *f)
{
    int result;
    
    if (!(result = fclose(f)))
        XXL_ASSET_RELEASE(f, XXL_ASSET_ALL);
    return result;
}

void
xxl_cleanup_FILE(void *ptr, void *arg)
{
    fclose((FILE *)ptr);
}

int
#ifndef WIN32
xxl_open(const char *path, int flags, mode_t mode, xxl_assettype_t asset_type)
#else
xxl_open(const char *path, int flags, int mode, xxl_assettype_t asset_type)
#endif
{
    int fd;

    if ((fd = open(path, flags, mode)) != -1)
        XXL_ASSET_SAVE((void *)fd, xxl_cleanup_fd, NULL, asset_type);
    return fd;
}

int
xxl_close(int fd)
{
    int result;

    if ((result = close(fd)) != -1)
        XXL_ASSET_RELEASE((void *)fd, XXL_ASSET_ALL);
    return result;
}

void
xxl_cleanup_fd(void *ptr, void *arg)
{
    close((int)ptr);
}

#ifndef WIN32
int
xxl_socket(int domain, int type, int protocol, xxl_assettype_t asset_type)
{
    int sd;
    
    if ((sd = socket(domain, type, protocol)) != -1)
        XXL_ASSET_SAVE((void *)sd, xxl_cleanup_socket, NULL, asset_type);
    return sd;
}

int
xxl_shutdown(int sd, int how)
{
    int result;

    if ((result = shutdown(sd, how)) != -1)
        XXL_ASSET_RELEASE((void *)sd, XXL_ASSET_ALL);
    return result;
}

int
xxl_closesocket(int sd)
{
    int result;

    if ((result = close(sd)) != -1)
        XXL_ASSET_RELEASE((void *)sd, XXL_ASSET_ALL);
    return result;
}

void
xxl_cleanup_socket(void *ptr, void *arg)
{
    close((int)ptr);
}

#ifndef XXL_WITHOUT_THREADS
int
xxl_lock(pthread_mutex_t *mutex, xxl_assettype_t asset_type)
{
    int result;

    if (!(result = pthread_mutex_lock(mutex)))
        XXL_ASSET_SAVE(mutex, xxl_cleanup_lock, NULL, asset_type);
    return result;
}

int
xxl_unlock(pthread_mutex_t *mutex)
{
    int result;

    if (!(result = pthread_mutex_unlock(mutex)))
        XXL_ASSET_RELEASE(mutex, XXL_ASSET_FIRST);
    return result;
}

void
xxl_cleanup_lock(void *ptr, void *arg)
{
    pthread_mutex_unlock((pthread_mutex_t *)ptr);
}
#endif
#else
SOCKET
xxl_socket(int domain, int type, int protocol, xxl_assettype_t asset_type)
{
    SOCKET  sd;

    if ((sd = socket(domain, type, protocol)) != INVALID_SOCKET)
        XXL_ASSET_SAVE((void *)sd, xxl_cleanup_socket, NULL, asset_type);
    return sd;
}

int
xxl_shutdown(SOCKET sd, int how)
{
    int result;

    if ((result = shutdown(sd, how)) != SOCKET_ERROR)
        XXL_ASSET_RELEASE((void *)sd, XXL_ASSET_ALL);
    return result;
}

int
xxl_closesocket(SOCKET sd)
{
    int result;

    if ((result = closesocket(sd)) != SOCKET_ERROR)
        XXL_ASSET_RELEASE((void *)sd, XXL_ASSET_ALL);
    return -1;
}

void
xxl_cleanup_socket(void *ptr, void *arg)
{
    closesocket((SOCKET)ptr);
}

#ifndef XXL_WITHOUT_THREADS
BOOL
xxl_lock(HANDLE hMutex, xxl_assettype_t asset_type)
{
    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0)
    {
        XXL_ASSET_SAVE(hMutex, xxl_cleanup_lock, NULL, asset_type);
        return TRUE;
    }
    return FALSE;
}

BOOL
xxl_unlock(HANDLE hMutex)
{
    if (!ReleaseMutex(hMutex))
        return FALSE;
    XXL_ASSET_RELEASE(hMutex, XXL_ASSET_FIRST);
    return TRUE;
}

void
xxl_cleanup_lock(void *ptr, void *arg)
{
    ReleaseMutex((HANDLE)ptr);
}
#endif

HGLOBAL
xxl_GlobalAlloc(UINT uFlags, DWORD dwBytes, xxl_assettype_t asset_type)
{
    HGLOBAL hGlobal;

    if ((hGlobal = GlobalAlloc(uFlags, dwBytes)) != NULL)
        XXL_ASSET_SAVE(hGlobal, xxl_cleanup_HGLOBAL, NULL, asset_type);
    return hGlobal;
}

HGLOBAL
xxl_GlobalReAlloc(HGLOBAL hOldGlobal, DWORD dwBytes, UINT uFlags)
{
    HGLOBAL hNewGlobal;

    if ((hNewGlobal = GlobalReAlloc(hOldGlobal, dwBytes, uFlags)) != NULL &&
        hOldGlobal != hNewGlobal)
    {
        XXL_ASSET_UPDATE(hOldGlobal, hNewGlobal);
    }
    return hNewGlobal;
}

HGLOBAL
xxl_GlobalFree(HGLOBAL hGlobal)
{
    if (GlobalFree(hGlobal) == hGlobal)
        return hGlobal;
    XXL_ASSET_RELEASE(hGlobal, XXL_ASSET_ALL);
    return NULL;
}

void
xxl_cleanup_HGLOBAL(void *ptr, void *arg)
{
    GlobalFree((HGLOBAL)ptr);
}

void *
xxl_HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes, xxl_assettype_t asset_type)
{
    void    *ptr;

#ifdef XXL_WITHOUT_THREADS
    dwFlags |= HEAP_NO_SERIALIZE;
#endif
    if (!hHeap)
        hHeap = GetProcessHeap();
    if ((ptr = HeapAlloc(hHeap, dwFlags, dwBytes)) != NULL)
        XXL_ASSET_SAVE(ptr, xxl_cleanup_HGLOBAL, hHeap, asset_type);
    return ptr;
}

void *
xxl_HeapReAlloc(HANDLE hHeap, DWORD dwFlags, void *ptr, SIZE_T dwBytes)
{
    void    *newptr;

#ifdef XXL_WITHOUT_THREADS
    dwFlags |= HEAP_NO_SERIALIZE;
#endif
    if (!hHeap)
        hHeap = GetProcessHeap();
    if ((newptr = HeapReAlloc(hHeap, dwFlags, ptr, dwBytes)) != NULL &&
        ptr != newptr)
    {
        XXL_ASSET_UPDATE(ptr, newptr);
    }
    return newptr;
}

void *
xxl_HeapFree(HANDLE hHeap, void *ptr)
{
    if (!hHeap)
        hHeap = GetProcessHeap();
#ifdef XXL_WITHOUT_THREADS
    HeapFree(hHeap, HEAP_NO_SERIALIZE, ptr);
#else
    HeapFree(hHeap, 0, ptr);
#endif
    XXL_ASSET_RELEASE(ptr, XXL_ASSET_ALL);
    return NULL;
}

void
xxl_cleanup_HeapPtr(void *ptr, void *arg)
{
#ifdef XXL_WITHOUT_THREADS
    HeapFree((HANDLE)arg, HEAP_NO_SERIALIZE, ptr);
#else
    HeapFree((HANDLE)arg, 0, ptr);
#endif
}

HLOCAL
xxl_LocalAlloc(UINT uFlags, UINT uBytes, xxl_assettype_t asset_type)
{
    HLOCAL  hLocal;

    if ((hLocal = LocalAlloc(uFlags, uBytes)) != NULL)
        XXL_ASSET_SAVE(hLocal, xxl_cleanup_HLOCAL, NULL, asset_type);
    return hLocal;
}

HLOCAL
xxl_LocalReAlloc(HLOCAL hOldLocal, UINT uBytes, UINT uFlags)
{
    HLOCAL  hNewLocal;

    if ((hNewLocal = GlobalReAlloc(hOldLocal, uBytes, uFlags)) &&
        hOldLocal != hNewLocal)
    {
        XXL_ASSET_UPDATE(hOldLocal, hNewLocal);
    }
    return hNewLocal;
}

HLOCAL
xxl_LocalFree(HLOCAL hLocal)
{
    if (LocalFree(hLocal) == hLocal)
        return hLocal;
    XXL_ASSET_RELEASE(hLocal, XXL_ASSET_ALL);
    return NULL;
}

void
xxl_cleanup_HLOCAL(void *ptr, void *arg)
{
    LocalFree((HLOCAL)ptr);
}

void
xxl_cleanup_HANDLE(void *ptr, void *arg)
{
    CloseHandle((HANDLE)ptr);
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1