|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef GMEM_H |
|
#define GMEM_H |
|
|
|
#include <cassert> |
|
#include <cstring> |
|
#include <cstdlib> |
|
#include <cstdio> |
|
|
|
#include "GooCheckedOps.h" |
|
|
|
|
|
inline void *gmalloc(size_t size, bool checkoverflow = false) |
|
{ |
|
if (size == 0) { |
|
return nullptr; |
|
} |
|
|
|
if (void *p = std::malloc(size)) { |
|
return p; |
|
} |
|
|
|
std::fputs("Out of memory\n", stderr); |
|
|
|
if (checkoverflow) { |
|
return nullptr; |
|
} |
|
|
|
std::abort(); |
|
} |
|
|
|
inline void *gmalloc_checkoverflow(size_t size) |
|
{ |
|
return gmalloc(size, true); |
|
} |
|
|
|
|
|
inline void gfree(void *p) |
|
{ |
|
std::free(p); |
|
} |
|
|
|
|
|
|
|
inline void *grealloc(void *p, size_t size, bool checkoverflow = false) |
|
{ |
|
if (size == 0) { |
|
gfree(p); |
|
return nullptr; |
|
} |
|
|
|
if (void *q = p ? std::realloc(p, size) : std::malloc(size)) { |
|
return q; |
|
} |
|
|
|
std::fputs("Out of memory\n", stderr); |
|
|
|
if (checkoverflow) { |
|
return nullptr; |
|
} |
|
|
|
std::abort(); |
|
} |
|
|
|
inline void *grealloc_checkoverflow(void *p, size_t size) |
|
{ |
|
return grealloc(p, size, true); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void *gmallocn(int count, int size, bool checkoverflow = false) |
|
{ |
|
if (count == 0) { |
|
return nullptr; |
|
} |
|
|
|
int bytes; |
|
if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) { |
|
std::fputs("Bogus memory allocation size\n", stderr); |
|
|
|
if (checkoverflow) { |
|
return nullptr; |
|
} |
|
|
|
std::abort(); |
|
} |
|
|
|
return gmalloc(bytes, checkoverflow); |
|
} |
|
|
|
inline void *gmallocn_checkoverflow(int count, int size) |
|
{ |
|
return gmallocn(count, size, true); |
|
} |
|
|
|
inline void *gmallocn3(int width, int height, int size, bool checkoverflow = false) |
|
{ |
|
if (width == 0 || height == 0) { |
|
return nullptr; |
|
} |
|
|
|
int count; |
|
int bytes; |
|
if (width < 0 || height < 0 || size <= 0 || checkedMultiply(width, height, &count) || checkedMultiply(count, size, &bytes)) { |
|
std::fputs("Bogus memory allocation size\n", stderr); |
|
|
|
if (checkoverflow) { |
|
return nullptr; |
|
} |
|
|
|
std::abort(); |
|
} |
|
|
|
return gmalloc(bytes, checkoverflow); |
|
} |
|
|
|
inline void *greallocn(void *p, int count, int size, bool checkoverflow = false, bool free_p = true) |
|
{ |
|
if (count == 0) { |
|
if (free_p) { |
|
gfree(p); |
|
} |
|
return nullptr; |
|
} |
|
|
|
int bytes; |
|
if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) { |
|
std::fputs("Bogus memory allocation size\n", stderr); |
|
|
|
if (checkoverflow) { |
|
if (free_p) { |
|
gfree(p); |
|
} |
|
return nullptr; |
|
} |
|
|
|
std::abort(); |
|
} |
|
|
|
assert(bytes > 0); |
|
if (void *q = grealloc(p, bytes, checkoverflow)) { |
|
return q; |
|
} |
|
if (free_p) { |
|
gfree(p); |
|
} |
|
return nullptr; |
|
} |
|
|
|
inline void *greallocn_checkoverflow(void *p, int count, int size) |
|
{ |
|
return greallocn(p, count, size, true); |
|
} |
|
|
|
|
|
inline char *copyString(const char *s) |
|
{ |
|
char *r = static_cast<char *>(gmalloc(std::strlen(s) + 1, false)); |
|
return std::strcpy(r, s); |
|
} |
|
|
|
|
|
inline char *copyString(const char *s, size_t n) |
|
{ |
|
char *r = static_cast<char *>(gmalloc(n + 1, false)); |
|
r[n] = '\0'; |
|
return std::strncpy(r, s, n); |
|
} |
|
|
|
#endif |
|
|