1 #ifndef JSON_MEMORY_H
2 #define JSON_MEMORY_H
3
4 #include <cstdlib> //for malloc, realloc, and free
5 #include <cstring> //for memmove
6 #include "JSONDebug.h"
7
8 #if defined(JSON_DEBUG) || defined(JSON_SAFE)
9 #define JSON_FREE_PASSTYPE &
10 #else
11 #define JSON_FREE_PASSTYPE
12 #endif
13
14 #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
15 class JSONMemory {
16 public:
17 static void * json_malloc(size_t siz) json_malloc_attr;
18 static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
19 static void json_free(void * ptr) json_nothrow;
20 static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
21 private:
22 JSONMemory(void);
23 };
24
25 template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
json_malloc(size_t count)26 template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
27 return (T *)JSONMemory::json_malloc(sizeof(T) * count);
28 }
29
30 template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
json_realloc(T * ptr,size_t count)31 template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
32 return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
33 }
34
libjson_free(T * JSON_FREE_PASSTYPE ptr)35 template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
36 JSONMemory::json_free(ptr);
37 #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
38 ptr = 0;
39 #endif
40 }
41 #else
42
43 template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
json_malloc(size_t count)44 template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
45 #ifdef JSON_DEBUG //in debug mode, see if the malloc was successful
46 void * result = std::malloc(count * sizeof(T));
47 JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
48 #ifdef JSON_NULL_MEMORY
49 std::memset(result, '\0', count * sizeof(T));
50 #endif
51 return (T *)result;
52 #else
53 return (T *)std::malloc(count * sizeof(T));
54 #endif
55 }
56
libjson_free(T * JSON_FREE_PASSTYPE ptr)57 template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
58 std::free(ptr);
59 #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
60 ptr = 0;
61 #endif
62 }
63
64 template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
json_realloc(T * ptr,size_t count)65 template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
66 #ifdef JSON_DEBUG //in debug mode, check the results of realloc to be sure it was successful
67 void * result = std::realloc(ptr, count * sizeof(T));
68 JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
69 return (T *)result;
70 #else
71 return (T *)std::realloc(ptr, count * sizeof(T));
72 #endif
73 }
74 #endif
75
76 #ifdef JSON_MEMORY_MANAGE
77 #include <map>
78 class JSONNode;
79 struct auto_expand {
80 public:
81 LIBJSON_OBJECT(auto_expand);
auto_expandauto_expand82 auto_expand(void) json_nothrow : mymap(){ LIBJSON_CTOR;}
~auto_expandauto_expand83 ~auto_expand(void) json_nothrow { purge(); LIBJSON_DTOR; }
84 void purge(void) json_nothrow;
clearauto_expand85 inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand86 inline void * insert(void * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand87 inline void remove(void * ptr) json_nothrow {
88 JSON_MAP(void *, void *)::iterator i = mymap.find(ptr);
89 JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
90 mymap.erase(i);
91 }
92 JSON_MAP(void *, void *) mymap;
93 private:
94 auto_expand(const auto_expand &);
95 auto_expand & operator = (const auto_expand &);
96 };
97
98 struct auto_expand_node {
99 public:
100 LIBJSON_OBJECT(auto_expand_node);
auto_expand_nodeauto_expand_node101 auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_nodeauto_expand_node102 ~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
103 void purge(void) json_nothrow ;
clearauto_expand_node104 inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand_node105 inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand_node106 inline void remove(void * ptr) json_nothrow {
107 JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
108 if(json_likely(i != mymap.end())) mymap.erase(i);
109 }
110 JSON_MAP(void *, JSONNode *) mymap;
111 private:
112 auto_expand_node(const auto_expand_node &);
113 auto_expand_node & operator = (const auto_expand_node &);
114 };
115
116 #ifdef JSON_STREAM
117 class JSONStream;
118 struct auto_expand_stream {
119 public:
120 LIBJSON_OBJECT(auto_expand_stream);
auto_expand_streamauto_expand_stream121 auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_streamauto_expand_stream122 ~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
123 void purge(void) json_nothrow ;
clearauto_expand_stream124 inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand_stream125 inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand_stream126 inline void remove(void * ptr) json_nothrow {
127 JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
128 if(json_likely(i != mymap.end())) mymap.erase(i);
129 }
130 JSON_MAP(void *, JSONStream *) mymap;
131 private:
132 auto_expand_stream(const auto_expand_stream &);
133 auto_expand_stream & operator = (const auto_expand_stream &);
134 };
135 #endif
136 #endif
137
138 //The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
139 template <typename T>
140 class json_auto {
141 public:
142 LIBJSON_OBJECT(json_auto);
json_auto(void)143 json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
json_auto(size_t count)144 json_auto(size_t count) json_nothrow : ptr(json_malloc<T>(count)){ LIBJSON_CTOR; }
json_auto(T * arg)145 json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
~json_auto(void)146 ~json_auto(void) json_nothrow {
147 libjson_free<T>(ptr);
148 LIBJSON_DTOR;
149 }
set(T * p)150 inline void set(T * p) json_nothrow{
151 ptr = p;
152 }
153 T * ptr;
154 private:
155 json_auto(const json_auto &);
156 json_auto & operator =(const json_auto &);
157 };
158
159 //Clears a string, if required, frees the memory
clearString(json_string & str)160 static inline void clearString(json_string & str) json_nothrow {
161 #ifdef JSON_LESS_MEMORY
162 json_string().swap(str);
163 #else
164 str.clear();
165 #endif
166 }
167
168 //Shrinks a string
shrinkString(json_string & str)169 static inline void shrinkString(json_string & str) json_nothrow {
170 #ifdef JSON_LESS_MEMORY
171 if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
172 #endif
173 }
174
175 #endif
176