#ifndef JSON_MEMORY_H #define JSON_MEMORY_H #include //for malloc, realloc, and free #include //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 static inline T * json_malloc(size_t count) json_malloc_attr; template static inline T * json_malloc(size_t count) json_nothrow { return (T *)JSONMemory::json_malloc(sizeof(T) * count); } template static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr; template static inline T * json_realloc(T * ptr, size_t count) json_nothrow { return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count); } template 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 static inline T * json_malloc(size_t count) json_malloc_attr; template 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 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 static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr; template 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 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 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(count)){ LIBJSON_CTOR; } json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; } ~json_auto(void) json_nothrow { libjson_free(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