blob: 4fb1d1c01fd839f4a9fe942c1a4200d5d3084bd6 [file] [log] [blame]
#ifndef ODIN_MEMORY_H
#define ODIN_MEMORY_H
#include <cstdint>
#include <cstddef>
#include <limits>
#include <cstring>
#include <algorithm>
#include "odin_error.h"
#ifndef __GLIBC__
# include <stdlib.h>
#else
# include <malloc.h>
#endif
namespace odin
{
extern uintptr_t min_address;
extern uintptr_t max_address;
char *strdup(const char *in);
template<typename T>
void free(T** ptr_ref)
{
oassert(ptr_ref != NULL
&& "did not pass in a valid ref");
T *ptr = (*ptr_ref);
(*ptr_ref) = NULL;
if(ptr != NULL
&& (uintptr_t)ptr >= min_address
&& (uintptr_t)ptr <= max_address )
{
std::free(ptr);
}
}
template<typename T, typename S>
void *calloc(T _n_element, S _element_size)
{
void* ret = NULL;
size_t n_element = 0;
size_t element_size = 0;
size_t n_bytes = 0;
if(std::is_unsigned<T>() || _n_element > 0)
{
n_element = static_cast<size_t>(_n_element);
}
if(std::is_unsigned<S>() || _element_size > 0)
{
element_size = static_cast<size_t>(_element_size);
}
n_bytes = n_element*element_size;
if(n_bytes > 0)
{
ret = std::calloc(n_bytes, 1);
oassert(ret != NULL
&& "odin::calloc failed, OOM?");
}
if(ret != NULL)
{
min_address = std::min(min_address, (uintptr_t)ret);
max_address = std::max(max_address, (uintptr_t)ret);
}
return (ret);
}
// we use a template to check for valid size
template<typename T>
void *malloc(T _n_bytes)
{
return calloc(_n_bytes, 1);
}
template<typename T, typename S>
void realloc(T **ptr_ref, S _n_bytes)
{
oassert(ptr_ref != NULL
&& "did not pass in a valid ref");
T *ptr = (*ptr_ref);
(*ptr_ref) = NULL;
size_t n_bytes = 0;
if(std::is_unsigned<T>() || _n_bytes > 0)
{
n_bytes = static_cast<size_t>(_n_bytes);
}
if(ptr != NULL
&& (uintptr_t)ptr >= min_address
&& (uintptr_t)ptr <= max_address )
{
if(n_bytes > 0)
{
ptr = (T*)std::realloc(ptr, n_bytes);
oassert(ptr != NULL
&& "odin::realloc failed, OOM?");
}
else
{
free(&ptr);
}
}
else
{
if(n_bytes > 0)
{
ptr = (T*)calloc(n_bytes, 1);
}
else
{
ptr = NULL;
}
}
if(ptr != NULL)
{
min_address = std::min(min_address, (uintptr_t)ptr);
max_address = std::max(max_address, (uintptr_t)ptr);
}
(*ptr_ref) = ptr;
}
}
#endif //ODIN_MEMORY_H