Blame | Last modification | View Log | Download | RSS feed
#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 againptr = 0;#endif}#elsetemplate <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 successfulvoid * result = std::malloc(count * sizeof(T));JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));#ifdef JSON_NULL_MEMORYstd::memset(result, '\0', count * sizeof(T));#endifreturn (T *)result;#elsereturn (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 againptr = 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 successfulvoid * result = std::realloc(ptr, count * sizeof(T));JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));return (T *)result;#elsereturn (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_STREAMclass 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 destroyedtemplate <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 memorystatic inline void clearString(json_string & str) json_nothrow {#ifdef JSON_LESS_MEMORYjson_string().swap(str);#elsestr.clear();#endif}//Shrinks a stringstatic inline void shrinkString(json_string & str) json_nothrow {#ifdef JSON_LESS_MEMORYif (str.capacity() != str.length()) str = json_string(str.begin(), str.end());#endif}#endif