wordreference/libjson/_internal/Source/JSONMemory.h

175 lines
6.3 KiB
C++

#ifndef JSON_MEMORY_H
#define JSON_MEMORY_H
#include <cstdlib> //for malloc, realloc, and free
#include <cstring> //for memmove
#include "JSONDebug.h"
#if defined(JSON_DEBUG) || defined(JSON_SAFE)
#define JSON_FREE_PASSTYPE &
#else
#define JSON_FREE_PASSTYPE
#endif
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
class JSONMemory {
public:
static void * json_malloc(size_t siz) json_malloc_attr;
static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
static void json_free(void * ptr) json_nothrow;
static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
private:
JSONMemory(void);
};
template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
return (T *)JSONMemory::json_malloc(sizeof(T) * count);
}
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
}
template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
JSONMemory::json_free(ptr);
#if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
ptr = 0;
#endif
}
#else
template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
#ifdef JSON_DEBUG //in debug mode, see if the malloc was successful
void * result = std::malloc(count * sizeof(T));
JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
#ifdef JSON_NULL_MEMORY
std::memset(result, '\0', count * sizeof(T));
#endif
return (T *)result;
#else
return (T *)std::malloc(count * sizeof(T));
#endif
}
template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
std::free(ptr);
#if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
ptr = 0;
#endif
}
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
#ifdef JSON_DEBUG //in debug mode, check the results of realloc to be sure it was successful
void * result = std::realloc(ptr, count * sizeof(T));
JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
return (T *)result;
#else
return (T *)std::realloc(ptr, count * sizeof(T));
#endif
}
#endif
#ifdef JSON_MEMORY_MANAGE
#include <map>
class JSONNode;
struct auto_expand {
public:
LIBJSON_OBJECT(auto_expand);
auto_expand(void) json_nothrow : mymap(){ LIBJSON_CTOR;}
~auto_expand(void) json_nothrow { purge(); LIBJSON_DTOR; }
void purge(void) json_nothrow;
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
inline void * insert(void * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
inline void remove(void * ptr) json_nothrow {
JSON_MAP(void *, void *)::iterator i = mymap.find(ptr);
JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
mymap.erase(i);
}
JSON_MAP(void *, void *) mymap;
private:
auto_expand(const auto_expand &);
auto_expand & operator = (const auto_expand &);
};
struct auto_expand_node {
public:
LIBJSON_OBJECT(auto_expand_node);
auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
void purge(void) json_nothrow ;
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
inline void remove(void * ptr) json_nothrow {
JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
if(json_likely(i != mymap.end())) mymap.erase(i);
}
JSON_MAP(void *, JSONNode *) mymap;
private:
auto_expand_node(const auto_expand_node &);
auto_expand_node & operator = (const auto_expand_node &);
};
#ifdef JSON_STREAM
class JSONStream;
struct auto_expand_stream {
public:
LIBJSON_OBJECT(auto_expand_stream);
auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
void purge(void) json_nothrow ;
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
inline void remove(void * ptr) json_nothrow {
JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
if(json_likely(i != mymap.end())) mymap.erase(i);
}
JSON_MAP(void *, JSONStream *) mymap;
private:
auto_expand_stream(const auto_expand_stream &);
auto_expand_stream & operator = (const auto_expand_stream &);
};
#endif
#endif
//The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
template <typename T>
class json_auto {
public:
LIBJSON_OBJECT(json_auto);
json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
json_auto(size_t count) json_nothrow : ptr(json_malloc<T>(count)){ LIBJSON_CTOR; }
json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
~json_auto(void) json_nothrow {
libjson_free<T>(ptr);
LIBJSON_DTOR;
}
inline void set(T * p) json_nothrow{
ptr = p;
}
T * ptr;
private:
json_auto(const json_auto &);
json_auto & operator =(const json_auto &);
};
//Clears a string, if required, frees the memory
static inline void clearString(json_string & str) json_nothrow {
#ifdef JSON_LESS_MEMORY
json_string().swap(str);
#else
str.clear();
#endif
}
//Shrinks a string
static inline void shrinkString(json_string & str) json_nothrow {
#ifdef JSON_LESS_MEMORY
if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
#endif
}
#endif