#ifndef JSON_MEMORY_H #define JSON_MEMORY_H #include //for malloc, realloc, and free #include //for memmove #include "JSONOptions.h" #include "JSONDebug.h" #if defined(JSON_DEBUG) || defined(JSON_SAFE) #define JSON_FREE_PASSTYPE & #else #define JSON_FREE_PASSTYPE #endif #ifdef JSON_MEMORY_CALLBACKS class JSONMemory { public: static void * json_malloc(size_t siz); static void * json_realloc(void * ptr, size_t siz); static void json_free(void * ptr); static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre); }; template static inline T * json_malloc(size_t count){ return (T *)JSONMemory::json_malloc(sizeof(T) * count); } template static inline T * json_realloc(T * ptr, size_t count){ return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count); } template static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr){ 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){ #ifdef JSON_DEBUG //in debug mode, see if the malloc was successful void * result = malloc(count * sizeof(T)); JSON_ASSERT(result, JSON_TEXT("out of memory")); #ifdef JSON_NULL_MEMORY memset(result, '\0', count * sizeof(T)); #endif return (T *)result; #else return (T *)malloc(count * sizeof(T)); #endif } template static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr){ 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){ #ifdef JSON_DEBUG //in debug mode, check the results of realloc to be sure it was successful void * result = realloc(ptr, count * sizeof(T)); JSON_ASSERT(result, JSON_TEXT("out of memory")); #ifdef JSON_NULL_MEMORY memset(result, '\0', count * sizeof(T)); #endif return (T *)result; #else return (T *)realloc(ptr, count * sizeof(T)); #endif } #endif #ifdef JSON_MEMORY_MANAGE #include class JSONNode; struct auto_expand { auto_expand(void) : mymap() {} ~auto_expand(void){ purge(); } void purge(void); inline void clear(void){ purge(); mymap.clear(); } inline void * insert(void * ptr){ mymap[ptr] = ptr; return ptr; } inline void remove(void * ptr){ std::map::iterator i = mymap.find(ptr); JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item")); mymap.erase(i); } std::map mymap; }; struct auto_expand_node { auto_expand_node(void) : mymap() {} ~auto_expand_node(void){ purge(); } void purge(void); inline void clear(void){ purge(); mymap.clear(); } inline JSONNode * insert(JSONNode * ptr){ mymap[ptr] = ptr; return ptr; } inline void remove(void * ptr){ std::map::iterator i = mymap.find(ptr); if(i != mymap.end()) mymap.erase(i); } std::map mymap; }; #endif //The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed template class json_auto { public: json_auto(void) : ptr(0){} json_auto(size_t count) : ptr(json_malloc(count)) {} ~json_auto(void){ libjson_free(ptr); } void set(T * p){ 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){ #ifdef JSON_LESS_MEMORY json_string().swap(str); #else str.clear(); #endif } #endif