176 lines
6.3 KiB
C
176 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
|